<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Nskm</title>
    <subtitle>Never stray from the way.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://nskm.xyz/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://nskm.xyz"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-05-02T00:00:00+00:00</updated>
    <id>https://nskm.xyz/atom.xml</id>
    <entry xml:lang="en">
        <title>ITIL 4 Foundations</title>
        <published>2026-05-02T00:00:00+00:00</published>
        <updated>2026-05-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/itil-4/"/>
        <id>https://nskm.xyz/posts/itil-4/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/itil-4/">&lt;style&gt;
.it { border-collapse: collapse; width: 100%; margin: 1.2em 0; font-size: 0.88em; }
.it th, .it td { border: 1px solid #30363d; padding: 8px 13px; text-align: left; vertical-align: top; line-height: 1.5; }
.it thead th { background: #161b22; color: #388bfd; font-weight: 600; letter-spacing: 0.02em; }
.it tbody tr:nth-child(even) td { background: #0d111799; }
&lt;&#x2F;style&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;that-word.png&quot; alt=&quot;what?&quot; title=&quot;what?&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the author, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, or affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If you are a colleague and recognize the situation described below, remember: I&#x27;m critiquing the system, not the people.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Render unto Caesar what is Caesar&#x27;s: Claude helped me find up-to-date documentation links and helped beautify all the diagrams used (and not used) in this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article has been proofread by &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&#x2F;&quot;&gt;Mame Astou&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt;. Thank you both.
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;I tend to stay in my lane. Focus on what I understand, the perimeter I actually control. Everything beyond my code, my systems, my terminal &lt;em&gt;(the hierarchy, management, all the people I work with who don&#x27;t write programs)&lt;&#x2F;em&gt; has always been a blur to me. Vague, formless, abstract. Sometimes genuinely incomprehensible. Not because I think those people are wrong, but because whatever they do has always felt like noise I couldn&#x27;t parse.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll grudgingly admit, though: since joining this &lt;a href=&quot;https:&#x2F;&#x2F;institutpasteurdakar.sn&#x2F;&quot;&gt;biomedical research center&lt;&#x2F;a&gt;, everything that happens &lt;em&gt;outside&lt;&#x2F;em&gt; my direct work has become the most interesting part of the job. Humans are fascinating creatures to observe from a safe distance. Maybe it&#x27;s because my actual technical work is no longer the hardest thing on my plate. Or maybe because what happens in the corridors and meeting rooms has a direct, outsized impact on my work, on my &lt;a href=&quot;#&quot;&gt;freedom&lt;&#x2F;a&gt; to do that work the way I&#x27;d want to.&lt;&#x2F;p&gt;
&lt;p&gt;The hardest thing is collaborating with many other people, exchanging information in a way that everyone actually understands each other. Not just hears: understands. The hardest thing is listening, really listening to what others have to say, deeply, absorbing and retaining what they meant. Then responding, expressing yourself in a way that gets through, in a way that convinces. Making the right compromises, the right calls, and moving forward together, making sure everyone gets something of what they came for.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Last Tuesday, I was enrolled in an &lt;strong&gt;ITIL 4 Foundations&lt;&#x2F;strong&gt; training organized by my hierarchy. The stated goals were clear: &lt;em&gt;garantir la disponibilité des systèmes&lt;&#x2F;em&gt; (ensure system availability), &lt;em&gt;structurer la gestion des incidents&lt;&#x2F;em&gt; (structure incident management), and &lt;em&gt;parler le même langage&lt;&#x2F;em&gt; (speak the same language). Perfectly reasonable goals.&lt;&#x2F;p&gt;
&lt;p&gt;In practice: sitting in a room while someone talks through concept after concept, deploying words and definitions at high velocity, is its own endurance sport. It&#x27;s made harder by the fact that some concepts I thought I already knew get redefined with vocabulary I would never have chosen — and some familiar words get used in ways that are subtly but persistently disorienting.&lt;&#x2F;p&gt;
&lt;p&gt;That said, I have to be honest: &lt;strong&gt;ITIL 4 is not the bureaucratic nightmare its reputation suggests&lt;&#x2F;strong&gt;. If anything, I realized I&#x27;d already been practicing most of these concepts; informally, imperfectly, without knowing there was a name for them. Done right, this is a coherent framework that actually acknowledges modern realities: Agile, DevOps, SRE, Lean.&lt;&#x2F;p&gt;
&lt;p&gt;Since I took notes anyway, might as well turn them into something useful. I hope you&#x27;ll learn something. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=mbf9aLD8E8M&quot;&gt;Music&lt;&#x2F;a&gt; \o&#x2F;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#what-is-itil-4&quot;&gt;What is itil 4?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#why-should-your-organization-care&quot;&gt;Why should your organization care?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-vocabulary&quot;&gt;The vocabulary&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#pestle-the-external-forces-you-cannot-control&quot;&gt;Pestle: external forces&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-big-picture-service-value-system-svs&quot;&gt;The service value system (svs)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#inside-the-svs-the-service-value-chain-svc&quot;&gt;The service value chain (svc)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-34-management-practices&quot;&gt;The 34 practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#incident-management&quot;&gt;Incident management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#change-enablement&quot;&gt;Change enablement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#governance-and-risk-management&quot;&gt;Governance and risk management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#itil-4-agile-devops-lean&quot;&gt;ITIL 4 ↔ agile, devops, lean&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#case-study&quot;&gt;Case study&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#tooling&quot;&gt;Tooling&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#itil-v5&quot;&gt;ITIL v5&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-itil-4&quot;&gt;What is ITIL 4?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.axelos.com&#x2F;certifications&#x2F;itil-service-management&quot;&gt;ITIL (Information Technology Infrastructure Library)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is a framework for IT Service Management (ITSM). It provides guidance on how organizations can use IT as a tool to facilitate business transformation and growth.&lt;&#x2F;p&gt;
&lt;p&gt;Key facts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Origin&lt;&#x2F;strong&gt;: Developed in the 1980s by the UK government&#x27;s CCTA (Central Computer and Telecommunications Agency) to standardize IT practices across public services.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ITIL 4&lt;&#x2F;strong&gt; (released &lt;strong&gt;2019&lt;&#x2F;strong&gt;): The current version. A major rethink compared to ITIL v3, designed to integrate with modern approaches: Agile, DevOps, Lean, SRE.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Owner&lt;&#x2F;strong&gt;: Currently maintained by &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.peoplecert.org&#x2F;&quot;&gt;PeopleCert&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, which acquired AXELOS (the previous owner) in 2021.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Who uses it?&lt;&#x2F;strong&gt; Organizations of all sizes, across industries. Particularly common in banking, telecom, healthcare, public sector, and large IT departments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One thing ITIL 4 gets right that its predecessors didn&#x27;t: it explicitly acknowledges that &lt;strong&gt;you don&#x27;t need to implement all 34 practices&lt;&#x2F;strong&gt;. You pick what fits. This was not how earlier versions were often sold and it caused a lot of unnecessary process theater in organizations that implemented ITIL like a checkbox exercise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-should-your-organization-care&quot;&gt;Why should your organization care?&lt;&#x2F;h2&gt;
&lt;p&gt;During the training, an interesting observation was made about three organizational thresholds where ITIL practices start to become relevant:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Threshold&lt;&#x2F;th&gt;&lt;th&gt;Pain Point&lt;&#x2F;th&gt;&lt;th&gt;What Starts Breaking&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;≥ 5 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Memory loss&lt;&#x2F;td&gt;&lt;td&gt;Knowledge lives in people&#x27;s heads, not in runbooks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;≥ 10 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complexity&lt;&#x2F;td&gt;&lt;td&gt;Coordination overhead grows faster than the team&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;&amp;gt; 10 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Compliance&lt;&#x2F;td&gt;&lt;td&gt;Audits, regulations, and reporting requirements appear&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The practical implication: &lt;strong&gt;you don&#x27;t need all of ITIL&lt;&#x2F;strong&gt;. A 7-person startup building an internal tool doesn&#x27;t need a Change Advisory Board. A bank with 200 IT staff probably does. ITIL 4&#x27;s design philosophy is, understand the principles, apply the practices that solve your actual problems, and leave the rest on the shelf.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-vocabulary&quot;&gt;The vocabulary&lt;&#x2F;h2&gt;
&lt;p&gt;Before we can discuss the framework, we need to agree on definitions. ITIL has precise meanings for words we use casually.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;who-s-involved&quot;&gt;Who&#x27;s involved?&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Organization&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A person or group with its own functions, responsibilities, and authorities&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Stakeholder&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any person with an interest in an organization, product, or service&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Provider&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An organization that delivers services to consumers&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Consumer&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An organization or individual that receives services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Customer&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Defines requirements and owns the outcomes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;User&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The person who uses the service day-to-day&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Sponsor&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The person who authorizes the budget&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;In practice: the &lt;strong&gt;customer&lt;&#x2F;strong&gt; decides &lt;em&gt;what&lt;&#x2F;em&gt; they need, the &lt;strong&gt;user&lt;&#x2F;strong&gt; interacts with it daily, and the &lt;strong&gt;sponsor&lt;&#x2F;strong&gt; pays for it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-are-we-delivering&quot;&gt;What are we delivering?&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Resource&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any component used to deliver value: people, infrastructure, capital, information&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Product&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A configuration of resources designed to offer value to a consumer&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A means of enabling value co-creation by facilitating outcomes that customers want&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Offering&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A formal description of one or more services, designed for a target consumer group&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-value-equation&quot;&gt;The value equation&lt;&#x2F;h3&gt;
&lt;p&gt;This is arguably the most important concept in ITIL v4:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Value = Utility × Warranty&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Utility&lt;&#x2F;strong&gt;: What the service does — &lt;em&gt;fit for purpose&lt;&#x2F;em&gt;. Does it support the customer&#x27;s performance or remove a constraint?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Warranty&lt;&#x2F;strong&gt;: How reliably it does it — &lt;em&gt;fit for use&lt;&#x2F;em&gt;. Is it available when needed? Secure? Capable of handling the load?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A service that does the right thing but crashes every Monday morning has no value. A service that&#x27;s always available but solves the wrong problem also has no value. We need both, because a zero on either side collapses the product.&lt;&#x2F;p&gt;
&lt;p&gt;And value is &lt;strong&gt;subjective, contextual, and co-created&lt;&#x2F;strong&gt;. The provider alone cannot create value, it&#x27;s always produced in interaction with the customer. This shifts the conversation from &lt;em&gt;&quot;we delivered the system&quot;&lt;&#x2F;em&gt; to &lt;em&gt;&quot;did the customer actually get what they needed?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-actors-wrapper&quot;&gt;
&lt;style&gt;
.itil4-actors-wrapper {
    --bg:      #0d1117;
    --bg2:     #161b22;
    --bg3:     #21262d;
    --border:  #30363d;
    --text:    #e6edf3;
    --muted:   #8b949e;
    --blue:    #388bfd;
    --blue-d:  #1f6feb;
    --green:   #3fb950;
    --purple:  #a371f7;
    --orange:  #f0883e;
    --yellow:  #d29922;
    font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding: 28px 20px 20px;
    border-radius: 10px;
    margin: 30px 0;
}
.itil4-actors-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

.act-header { text-align: center; margin-bottom: 22px; }
.act-header h2 { font-size: 1.2rem; font-weight: 700; color: var(--blue); text-transform: uppercase; letter-spacing: 0.05em; }
.act-header p  { color: var(--muted); font-size: 0.8rem; margin-top: 5px; }

&#x2F;* ── 3-column main layout ── *&#x2F;
.act-main {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 12px;
    align-items: center;
}

&#x2F;* ── lane (provider &#x2F; consumer) ── *&#x2F;
.act-lane {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
}
.act-lane-header {
    padding: 7px 12px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    text-align: center;
}
.act-lane-header.provider { background: rgba(56,139,253,0.15); color: var(--blue); }
.act-lane-header.consumer { background: rgba(163,113,247,0.15); color: var(--purple); }
.act-lane-body { padding: 10px; display: flex; flex-direction: column; gap: 0; background: var(--bg2); }

&#x2F;* ── nodes ── *&#x2F;
.act-node {
    border: 1px solid var(--border);
    border-radius: 7px;
    padding: 9px 12px;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.1s;
    background: var(--bg3);
}
.act-node:hover  { border-color: var(--blue); transform: translateX(2px); }
.act-node.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(56,139,253,0.2); }
.act-node .nd-icon  { font-size: 1.1rem; }
.act-node .nd-name  { font-size: 0.78rem; font-weight: 700; color: var(--text); margin-top: 3px; }
.act-node .nd-role  { font-size: 0.68rem; color: var(--muted); margin-top: 2px; line-height: 1.4; }

&#x2F;* chain arrow between nodes in a lane *&#x2F;
.act-chain-arrow {
    text-align: center;
    color: var(--muted);
    font-size: 0.9rem;
    padding: 2px 0;
    line-height: 1;
}

&#x2F;* ── centre exchange column ── *&#x2F;
.act-exchange {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 110px;
    padding: 0 4px;
}

.act-flow-row {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.7rem;
    color: var(--muted);
    white-space: nowrap;
}
.act-flow-arrow { font-size: 1rem; }
.act-flow-label { font-size: 0.65rem; color: var(--muted); text-align: center; }

.act-value-box {
    border: 1px solid var(--green);
    border-radius: 8px;
    padding: 9px 10px;
    text-align: center;
    background: rgba(63,185,80,0.06);
    cursor: pointer;
    transition: border-color 0.15s;
}
.act-value-box:hover { border-color: #5af07d; }
.act-value-box.active { box-shadow: 0 0 0 2px rgba(63,185,80,0.25); }
.act-value-box .vb-eq   { font-size: 0.8rem; font-weight: 700; color: var(--green); }
.act-value-box .vb-sub  { font-size: 0.65rem; color: var(--muted); margin-top: 3px; line-height: 1.4; }

.act-cocreate {
    font-size: 0.62rem;
    color: var(--muted);
    text-align: center;
    font-style: italic;
    padding: 0 4px;
}

&#x2F;* ── info panel ── *&#x2F;
.act-panel {
    margin-top: 16px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px 16px;
    font-size: 0.84rem;
    min-height: 72px;
}
.act-panel .ap-title { font-weight: 700; color: var(--blue); margin-bottom: 5px; font-size: 0.88rem; }
.act-panel .ap-desc  { color: var(--text); line-height: 1.6; }
.act-panel .ap-hint  { color: var(--muted); font-style: italic; font-size: 0.78rem; }
.act-panel .ap-tags  { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.act-panel .ap-tag   { font-size: 0.7rem; background: var(--bg2); border: 1px solid var(--border); border-radius: 4px; padding: 2px 8px; color: var(--orange); }

@media (max-width: 580px) {
    .act-main { grid-template-columns: 1fr; }
    .act-exchange { flex-direction: row; flex-wrap: wrap; justify-content: center; min-width: unset; }
    .act-flow-row { font-size: 0.65rem; }
}
&lt;&#x2F;style&gt;

&lt;div class=&quot;act-header&quot;&gt;
    &lt;h2&gt;Who does what — for whom&lt;&#x2F;h2&gt;
    &lt;p&gt;Click any node to see its ITIL 4 definition&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;act-main&quot;&gt;

    &lt;!-- LEFT: Service Provider lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header provider&quot;&gt;⚙ Service Provider&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;resource&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;🧱&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Resource&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Raw input to build with&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ assembles into&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;product&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;📦&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Product&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Configured for value delivery&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ packaged as&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;service&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;⚡&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Enables consumer outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ described in&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;offering&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;📋&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service Offering&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Formal promise to the consumer&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- CENTRE: exchange --&gt;
    &lt;div class=&quot;act-exchange&quot;&gt;
        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#388bfd&quot;&gt;→&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;delivers&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-value-box&quot; data-act=&quot;value&quot;&gt;
            &lt;div class=&quot;vb-eq&quot;&gt;Utility × Warranty&lt;&#x2F;div&gt;
            &lt;div class=&quot;vb-sub&quot;&gt;= Value&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-cocreate&quot;&gt;co-created&lt;br&gt;by both sides&lt;&#x2F;div&gt;

        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;requires&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#a371f7&quot;&gt;←&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- RIGHT: Service Consumer lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header consumer&quot;&gt;👥 Service Consumer&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;sponsor&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;💰&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Sponsor&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Authorizes the budget&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ funds&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;customer&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;🎯&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Customer&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Defines requirements &amp;amp; owns outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ specifies for&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;user&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;🖥&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;User&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Uses the service day-to-day&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ feeds back to&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;stakeholder&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;🌐&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Stakeholder&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Any party with an interest&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;&#x2F;div&gt;&lt;!-- &#x2F;act-main --&gt;

&lt;div class=&quot;act-panel&quot; id=&quot;act-panel&quot;&gt;
    &lt;div class=&quot;ap-hint&quot;&gt;← Click any node to see its definition&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function () {
    const defs = {
        resource: {
            title: &quot;Resource&quot;,
            desc: &quot;Any component that can be used to deliver value: people, infrastructure, capital, information, or time. Resources are the raw inputs that the service provider assembles into something useful.&quot;,
            tags: [&quot;People&quot;, &quot;Infrastructure&quot;, &quot;Capital&quot;, &quot;Information&quot;]
        },
        product: {
            title: &quot;Product&quot;,
            desc: &quot;A configuration of resources designed to offer value to a consumer. A product is what the service provider builds — it may not be directly visible to the consumer, but it&#x27;s what the service is built on top of.&quot;,
            tags: [&quot;Configuration of resources&quot;, &quot;Provider-facing&quot;, &quot;Foundation of a service&quot;]
        },
        service: {
            title: &quot;Service&quot;,
            desc: &quot;A means of enabling value co-creation by facilitating outcomes that customers want to achieve, without the customer having to manage specific costs and risks. The key insight: value is not delivered, it is co-created.&quot;,
            tags: [&quot;Enables outcomes&quot;, &quot;Removes customer risk&quot;, &quot;Co-created with consumer&quot;]
        },
        offering: {
            title: &quot;Service Offering&quot;,
            desc: &quot;A formal description of one or more services, designed to address the needs of a target consumer group. It&#x27;s the official &#x27;promise&#x27; from provider to consumer — what&#x27;s included, what&#x27;s not, and at what terms.&quot;,
            tags: [&quot;Goods&quot;, &quot;Access to resources&quot;, &quot;Service actions&quot;, &quot;Terms &amp; conditions&quot;]
        },
        sponsor: {
            title: &quot;Sponsor&quot;,
            desc: &quot;The person who authorizes the budget for the consumption of a service. The sponsor may be the customer, or a separate person (e.g., a CFO who approves a service contract that the IT team actually uses).&quot;,
            tags: [&quot;Authorizes budget&quot;, &quot;May differ from Customer&quot;, &quot;Financial accountability&quot;]
        },
        customer: {
            title: &quot;Customer&quot;,
            desc: &quot;The person who defines the requirements for a service and takes responsibility for the outcomes of service consumption. The customer decides what is needed and judges whether the service delivered value.&quot;,
            tags: [&quot;Defines requirements&quot;, &quot;Owns outcomes&quot;, &quot;Negotiates SLAs&quot;, &quot;May also be Sponsor&quot;]
        },
        user: {
            title: &quot;User&quot;,
            desc: &quot;The person who uses services in their day-to-day work. Users interact directly with the service and often experience it differently from what the customer specified or the sponsor funded. This gap is why XLAs matter.&quot;,
            tags: [&quot;Day-to-day usage&quot;, &quot;Direct experience&quot;, &quot;Source of XLA signals&quot;, &quot;May differ from Customer&quot;]
        },
        stakeholder: {
            title: &quot;Stakeholder&quot;,
            desc: &quot;Any person who has an interest in an organization, product, service, practice, or other entity. Stakeholders include everyone on both sides: providers, consumers, regulators, partners, suppliers, and even the public in some contexts.&quot;,
            tags: [&quot;Broad category&quot;, &quot;Provider side&quot;, &quot;Consumer side&quot;, &quot;Regulators &amp; partners&quot;]
        },
        value: {
            title: &quot;Value = Utility × Warranty&quot;,
            desc: &quot;Value is subjective, contextual, and co-created — it cannot be delivered unilaterally by the provider. Utility is fitness for purpose (does the service do what the customer needs?). Warranty is fitness for use (is it available, secure, and reliable enough?). A zero on either factor collapses the value entirely.&quot;,
            tags: [&quot;Utility = fit for purpose&quot;, &quot;Warranty = fit for use&quot;, &quot;Co-created&quot;, &quot;Subjective &amp; contextual&quot;]
        }
    };

    const panel = document.getElementById(&#x27;act-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function () {
            const key = this.dataset.act;
            const d = defs[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tags = d.tags.map(t =&gt; `&lt;span class=&quot;ap-tag&quot;&gt;${t}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;ap-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-tags&quot;&gt;${tags}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pestle-the-external-forces-you-cannot-control&quot;&gt;PESTLE: The external forces you cannot control&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 acknowledges that organizations don&#x27;t operate in a vacuum. &lt;strong&gt;PESTLE analysis&lt;&#x2F;strong&gt; provides a structured lens for scanning the external environment:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Factor&lt;&#x2F;th&gt;&lt;th&gt;What It Covers&lt;&#x2F;th&gt;&lt;th&gt;IT Relevance&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Political&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Government policies, regulations&lt;&#x2F;td&gt;&lt;td&gt;Data sovereignty laws, public sector mandates&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Economic&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Budget cycles, cost pressures&lt;&#x2F;td&gt;&lt;td&gt;Cloud cost optimization, license negotiation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Social&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;User expectations, workforce trends&lt;&#x2F;td&gt;&lt;td&gt;Remote work adoption, digital literacy gaps&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technological&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Emerging tech, vendor landscape&lt;&#x2F;td&gt;&lt;td&gt;AI integration, cloud migration, security threats&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Legal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Compliance requirements&lt;&#x2F;td&gt;&lt;td&gt;GDPR, HIPAA, sector-specific regulations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Environmental&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sustainability, green IT&lt;&#x2F;td&gt;&lt;td&gt;Data center energy, hardware lifecycle&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;pestle.png&quot; alt=&quot;pestle&quot; title=&quot;pestle&quot;&#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cipd.org&#x2F;en&#x2F;knowledge&#x2F;factsheets&#x2F;pestle-analysis-factsheet&#x2F;&quot;&gt;PESTLE&lt;&#x2F;a&gt; is not unique to ITIL, it&#x27;s a general strategic analysis tool. ITIL v4 borrows it because service management decisions are always made inside an organizational and environmental context. We never want to build a technically excellent system that doesn&#x27;t survive its first compliance audit or budget cut.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-big-picture-service-value-system-svs&quot;&gt;The big picture: Service Value System (SVS)&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;strong&gt;Service Value System (SVS)&lt;&#x2F;strong&gt; is ITIL v4&#x27;s model for how an organization creates value. Think of it as the engine diagram for your IT service operations.&lt;&#x2F;p&gt;
&lt;p&gt;It takes &lt;strong&gt;opportunities and demands&lt;&#x2F;strong&gt; as input, runs them through a system of governance, practices, and activities, and outputs &lt;strong&gt;value&lt;&#x2F;strong&gt; for all stakeholders.&lt;&#x2F;p&gt;
&lt;p&gt;The SVS is composed of five components:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Guiding Principles&lt;&#x2F;strong&gt; — universal recommendations that apply to all decisions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Governance&lt;&#x2F;strong&gt; — the framework for directing and controlling the organization&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Service Value Chain (SVC)&lt;&#x2F;strong&gt; — the set of interconnected activities that turn demand into value&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Management Practices&lt;&#x2F;strong&gt; — the 34 practices that provide organizational capability&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Continual Improvement&lt;&#x2F;strong&gt; — the persistent drive to improve everything&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;


&lt;div class=&quot;itil4-svs-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svs-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #388bfd;
            --blue-dim: #1f6feb;
            --green: #3fb950;
            --purple: #a371f7;
            --orange: #f0883e;
            --yellow: #d29922;
            --red: #f85149;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            border-radius: 10px;
            margin: 30px 0;
        }
        .itil4-svs-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svs-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .svs-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .svs-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        .svs-main-layout {
            display: flex;
            align-items: stretch;
            gap: 12px;
        }

        &#x2F;* --- Input&#x2F;Output columns --- *&#x2F;
        .svs-io {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            gap: 16px;
            min-width: 90px;
        }
        .svs-io-item {
            background: var(--bg3);
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 12px 10px;
            text-align: center;
            font-size: 0.78rem;
            width: 90px;
        }
        .svs-io-item .io-icon { font-size: 1.4rem; display: block; margin-bottom: 4px; }
        .svs-io-item .io-label { color: var(--muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }
        .svs-io-item .io-name { color: var(--text); font-weight: 600; margin-top: 2px; }

        .svs-arrow {
            color: var(--blue);
            font-size: 1.6rem;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 4px;
        }

        &#x2F;* --- SVS box --- *&#x2F;
        .svs-box {
            flex: 1;
            border: 2px solid var(--blue-dim);
            border-radius: 12px;
            padding: 16px;
            position: relative;
            background: var(--bg2);
        }

        .svs-guiding-label, .svs-ci-label {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.08em;
            padding: 5px 0;
            border-radius: 4px;
            margin-bottom: 10px;
        }
        .svs-guiding-label {
            color: var(--purple);
            border: 1px dashed var(--purple);
            opacity: 0.85;
        }
        .svs-ci-label {
            color: var(--green);
            border: 1px dashed var(--green);
            margin-top: 10px;
            margin-bottom: 0;
            opacity: 0.85;
        }

        .svs-inner-grid {
            display: grid;
            grid-template-columns: 1fr 2fr;
            gap: 10px;
            margin: 10px 0;
        }

        .svs-component {
            border-radius: 8px;
            padding: 12px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            border: 1px solid var(--border);
        }
        .svs-component:hover { border-color: var(--blue); transform: translateY(-1px); }
        .svs-component.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(56,139,253,0.25); }

        .svs-component .comp-icon { font-size: 1.3rem; margin-bottom: 5px; }
        .svs-component .comp-name {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .svs-component .comp-sub {
            font-size: 0.72rem;
            color: var(--muted);
            margin-top: 4px;
            line-height: 1.4;
        }

        .comp-governance { background: rgba(163,113,247,0.08); }
        .comp-svc { background: rgba(56,139,253,0.08); grid-row: 1 &#x2F; 3; }
        .comp-practices { background: rgba(240,136,62,0.08); }

        .svc-activities {
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            margin-top: 8px;
        }
        .svc-act {
            font-size: 0.68rem;
            background: var(--bg3);
            border: 1px solid var(--border);
            border-radius: 4px;
            padding: 2px 6px;
            color: var(--blue);
            font-weight: 500;
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .svs-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .svs-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .svs-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svs-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .svs-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .svs-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            border-radius: 4px;
            padding: 2px 8px;
            color: var(--text);
        }

        .svs-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .svs-legend-item { display: flex; align-items: center; gap: 5px; }
        .svs-legend-dot {
            width: 8px; height: 8px;
            border-radius: 50%;
            display: inline-block;
        }

        @media (max-width: 600px) {
            .svs-main-layout { flex-direction: column; }
            .svs-arrow { transform: rotate(90deg); }
            .svs-inner-grid { grid-template-columns: 1fr; }
            .comp-svc { grid-row: auto; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svs-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4 — Service Value System (SVS)&lt;&#x2F;h2&gt;
        &lt;p&gt;Click any component to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svs-main-layout&quot;&gt;
        &lt;!-- Inputs --&gt;
        &lt;div class=&quot;svs-io&quot;&gt;
            &lt;div class=&quot;svs-io-item&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;💡&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Input&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Opportunity&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;svs-io-item&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;📋&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Input&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Demand&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svs-arrow&quot;&gt;→&lt;&#x2F;div&gt;

        &lt;!-- SVS Box --&gt;
        &lt;div class=&quot;svs-box&quot;&gt;
            &lt;div class=&quot;svs-guiding-label&quot; data-svs=&quot;guiding&quot; style=&quot;cursor:pointer&quot;&gt;
                ✦ Guiding Principles — universally applicable ✦
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svs-inner-grid&quot;&gt;
                &lt;div class=&quot;svs-component comp-governance&quot; data-svs=&quot;governance&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;🏛&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;Governance&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;Direct · Evaluate · Monitor&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;

                &lt;div class=&quot;svs-component comp-svc&quot; data-svs=&quot;svc&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;⛓&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;Service Value Chain&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;6 interconnected activities that convert demand into value&lt;&#x2F;div&gt;
                    &lt;div class=&quot;svc-activities&quot;&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Plan&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Engage&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Design &amp;amp; Transition&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Obtain &#x2F; Build&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Deliver &amp;amp; Support&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Improve&lt;&#x2F;span&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;

                &lt;div class=&quot;svs-component comp-practices&quot; data-svs=&quot;practices&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;🔧&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;34 Practices&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;General (14) · Service (17) · Technical (3)&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svs-ci-label&quot; data-svs=&quot;ci&quot; style=&quot;cursor:pointer&quot;&gt;
                ↻ Continual Improvement — embedded at every level ↺
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svs-arrow&quot;&gt;→&lt;&#x2F;div&gt;

        &lt;!-- Output --&gt;
        &lt;div class=&quot;svs-io&quot;&gt;
            &lt;div class=&quot;svs-io-item&quot; style=&quot;width:90px&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;✨&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Output&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Value for all stakeholders&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;svs-info-panel&quot; id=&quot;svs-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a component above to see its role in the SVS&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svs-legend&quot;&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#a371f7&quot;&gt;&lt;&#x2F;span&gt; Guiding Principles&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#a371f7; opacity:0.5&quot;&gt;&lt;&#x2F;span&gt; Governance&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#388bfd&quot;&gt;&lt;&#x2F;span&gt; Service Value Chain&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#f0883e&quot;&gt;&lt;&#x2F;span&gt; 34 Practices&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#3fb950&quot;&gt;&lt;&#x2F;span&gt; Continual Improvement&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        guiding: {
            title: &quot;7 Guiding Principles&quot;,
            desc: &quot;Universal recommendations that guide organizations in all circumstances. Unlike practices or processes, they apply regardless of what you&#x27;re doing or where you are in the SVS. They cannot be overridden by management or policy.&quot;,
            items: [&quot;Focus on value&quot;, &quot;Start where you are&quot;, &quot;Progress iteratively with feedback&quot;, &quot;Collaborate and promote visibility&quot;, &quot;Think and work holistically&quot;, &quot;Keep it simple and practical&quot;, &quot;Optimize and automate&quot;]
        },
        governance: {
            title: &quot;Governance&quot;,
            desc: &quot;The framework by which an organization is directed and controlled. In the SVS, governance sits above everything else — it sets the direction and ensures accountability. Three core functions:&quot;,
            items: [&quot;Direct — set strategy, objectives, policies&quot;, &quot;Evaluate — assess performance, risk, compliance&quot;, &quot;Monitor — track adherence and verify outcomes&quot;]
        },
        svc: {
            title: &quot;Service Value Chain (SVC)&quot;,
            desc: &quot;The operational model at the heart of the SVS. Six activities that can be combined in different ways to create value streams — the specific sequences of steps for a given product or service. It is NOT linear: each value stream activates a different combination of activities.&quot;,
            items: [&quot;Plan — shared understanding of direction&quot;, &quot;Engage — stakeholder needs and relationships&quot;, &quot;Design &amp; Transition — meet stakeholder expectations&quot;, &quot;Obtain&#x2F;Build — components available when needed&quot;, &quot;Deliver &amp; Support — services per agreed specs&quot;, &quot;Improve — continual improvement across all services&quot;]
        },
        practices: {
            title: &quot;34 Management Practices&quot;,
            desc: &quot;Sets of organizational resources designed for performing work or accomplishing an objective. Organized into three categories. You do not need to implement all 34 — adopt what solves your actual problems.&quot;,
            items: [&quot;General Management (14): strategy, risk, knowledge, continual improvement...&quot;, &quot;Service Management (17): incident, change, service desk, problem...&quot;, &quot;Technical Management (3): deployment, infrastructure, software dev&quot;]
        },
        ci: {
            title: &quot;Continual Improvement&quot;,
            desc: &quot;A recurring practice embedded across the entire SVS — not just a step at the end. Every component, every practice, every activity should be subject to improvement. The Continual Improvement Register (CIR) tracks improvement ideas and their status.&quot;,
            items: [&quot;7-step model: vision → baseline → target → plan → act → measure → sustain&quot;, &quot;3 axes: strategic, tactical, operational&quot;, &quot;Tools: OKR, KPI, SLA, XLA, CIR&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svs-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svs-wrapper [data-svs]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svs;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svs-wrapper [data-svs]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;NOTA BENE: &lt;strong&gt;Guiding Principles&lt;&#x2F;strong&gt; and &lt;strong&gt;Continual Improvement&lt;&#x2F;strong&gt; are not steps in a sequence. They&#x27;re a mindset that applies to all activities, at all times. You don&#x27;t &quot;do continual improvement&quot; after you&#x27;re done. You do it while you&#x27;re doing everything else.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inside-the-svs-the-service-value-chain-svc&quot;&gt;Inside the SVS: the Service Value Chain (SVC)&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;strong&gt;Service Value Chain&lt;&#x2F;strong&gt; is the operational model at the core of the SVS. It defines 6 activities that can be combined in different ways. The combination for a given service or request is called a &lt;strong&gt;value stream&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Activity&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Plan&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Shared understanding of vision, direction, and current state&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Engage&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Understand stakeholder needs; maintain transparency and relationships&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Design &amp;amp; Transition&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure products and services meet stakeholder expectations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Obtain &#x2F; Build&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure service components are available when and where needed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Deliver &amp;amp; Support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure services are delivered and supported per agreed specifications&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Improve&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Continual improvement across all products, services, and practices&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The SVC is &lt;strong&gt;not linear&lt;&#x2F;strong&gt;. An incident resolution primarily activates Engage, Deliver &amp;amp; Support, and Improve. A new service launch activates all six. A routine service request might only need Engage and Deliver &amp;amp; Support.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-svc-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svc-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #388bfd;
            --blue-dim: #1f6feb;
            --green: #3fb950;
            --purple: #a371f7;
            --orange: #f0883e;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 28px 20px;
            border-radius: 10px;
            margin: 30px 0;
        }
        .itil4-svc-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svc-header {
            text-align: center;
            margin-bottom: 24px;
        }
        .svc-header h2 {
            font-size: 1.3rem;
            font-weight: 700;
            color: var(--blue);
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
        .svc-header p {
            color: var(--muted);
            font-size: 0.82rem;
            margin-top: 5px;
        }

        .svc-flow {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            justify-content: center;
            gap: 6px;
            margin-bottom: 20px;
        }

        .svc-node {
            background: var(--bg2);
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 10px 14px;
            cursor: pointer;
            text-align: center;
            min-width: 110px;
            transition: border-color 0.2s, transform 0.1s, background 0.2s;
        }
        .svc-node:hover { border-color: var(--blue); transform: translateY(-2px); }
        .svc-node.active { border-color: var(--blue); background: rgba(56,139,253,0.1); }
        .svc-node .node-icon { font-size: 1.3rem; display: block; margin-bottom: 4px; }
        .svc-node .node-name {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .svc-node .node-sub {
            font-size: 0.68rem;
            color: var(--muted);
            margin-top: 3px;
        }

        .svc-connector {
            color: var(--blue-dim);
            font-size: 1.1rem;
            opacity: 0.7;
        }

        .svc-note {
            text-align: center;
            font-size: 0.75rem;
            color: var(--muted);
            margin-bottom: 16px;
            font-style: italic;
        }

        .svc-info-panel {
            background: var(--bg3);
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 16px;
            font-size: 0.84rem;
            min-height: 70px;
        }
        .svc-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            margin-bottom: 5px;
        }
        .svc-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svc-info-panel .panel-hint { color: var(--muted); font-style: italic; font-size: 0.78rem; }
        .svc-info-panel .panel-examples {
            margin-top: 8px;
            font-size: 0.78rem;
            color: var(--muted);
        }
        .svc-info-panel .panel-examples span {
            background: var(--bg2);
            border: 1px solid var(--border);
            border-radius: 4px;
            padding: 1px 7px;
            margin-right: 4px;
            display: inline-block;
            margin-top: 4px;
            color: var(--orange);
        }

        @media (max-width: 600px) {
            .svc-flow { flex-direction: column; }
            .svc-connector { transform: rotate(90deg); }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svc-header&quot;&gt;
        &lt;h2&gt;Service Value Chain (SVC)&lt;&#x2F;h2&gt;
        &lt;p&gt;Six interconnected activities — combined differently for each value stream&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-flow&quot;&gt;
        &lt;div class=&quot;svc-node&quot; data-svc=&quot;plan&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;🗺&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Plan&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Direction &amp;amp; strategy&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;engage&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;🤝&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Engage&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Stakeholders &amp;amp; needs&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;design&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;📐&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Design &amp;amp; Transition&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Meet expectations&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;build&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;🔨&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Obtain &#x2F; Build&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Components ready&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;deliver&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;🚀&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Deliver &amp;amp; Support&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Run &amp;amp; resolve&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;improve&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;📈&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Improve&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Always, for everything&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-note&quot;&gt;↔ Activities are non-linear: each service interaction combines them differently&lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-info-panel&quot; id=&quot;svc-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click an activity above to see what it covers&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        plan: {
            title: &quot;Plan&quot;,
            desc: &quot;Ensures a shared understanding of vision, current status, and direction for all four dimensions. Produces plans, policies, portfolios, and architectures used by all other activities.&quot;,
            examples: [&quot;Capacity planning&quot;, &quot;IT strategy&quot;, &quot;Risk register updates&quot;, &quot;Architecture decisions&quot;]
        },
        engage: {
            title: &quot;Engage&quot;,
            desc: &quot;Provides a good understanding of stakeholder needs, enables transparency, and maintains productive relationships. The primary contact point between the organization and its customers and users.&quot;,
            examples: [&quot;Service requests intake&quot;, &quot;User feedback collection&quot;, &quot;Customer communications&quot;, &quot;SLA negotiation&quot;]
        },
        design: {
            title: &quot;Design &amp; Transition&quot;,
            desc: &quot;Ensures products and services continually meet stakeholder expectations for quality, costs, and time-to-market. Includes design, testing, and transitioning services into live operation.&quot;,
            examples: [&quot;Service design documents&quot;, &quot;Test plans&quot;, &quot;Release planning&quot;, &quot;Training materials&quot;]
        },
        build: {
            title: &quot;Obtain &#x2F; Build&quot;,
            desc: &quot;Ensures service components are available when and where needed, meeting agreed specifications. Covers both acquiring from suppliers and building internally.&quot;,
            examples: [&quot;Software development&quot;, &quot;Infrastructure provisioning&quot;, &quot;Vendor procurement&quot;, &quot;Configuration of components&quot;]
        },
        deliver: {
            title: &quot;Deliver &amp; Support&quot;,
            desc: &quot;Ensures services are delivered and supported according to agreed specifications and stakeholder expectations. Day-to-day operations, incident management, and service fulfillment.&quot;,
            examples: [&quot;Incident resolution&quot;, &quot;Service desk operations&quot;, &quot;Monitoring &amp; alerting&quot;, &quot;Fulfilling service requests&quot;]
        },
        improve: {
            title: &quot;Improve&quot;,
            desc: &quot;Ensures continual improvement across all products, services, and practices. Works in parallel with all other activities — every component of the SVS should be subject to improvement at all times.&quot;,
            examples: [&quot;Post-incident reviews&quot;, &quot;Performance trend analysis&quot;, &quot;Process optimization&quot;, &quot;Updating the CIR (Continual Improvement Register)&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svc-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svc-wrapper [data-svc]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svc;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svc-wrapper [data-svc]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const examples = d.examples.map(e =&gt; `&lt;span&gt;${e}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-examples&quot;&gt;${examples}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;h2&gt;
&lt;p&gt;Every component of the SVS should be considered from 4 perspectives. Ignoring any of them is one of the most reliable ways to make a project fail.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;&#x2F;th&gt;&lt;th&gt;What It Covers&lt;&#x2F;th&gt;&lt;th&gt;Classic Failure Mode&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Organizations and People&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Org structure, culture, roles, responsibilities&lt;&#x2F;td&gt;&lt;td&gt;&quot;We deployed the tool but nobody knows how to use it&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Information and Technology&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Data, knowledge, tools, infrastructure&lt;&#x2F;td&gt;&lt;td&gt;&quot;The system works but we can&#x27;t query the data we need&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Partners and Suppliers&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;External providers, contracts, integrations&lt;&#x2F;td&gt;&lt;td&gt;&quot;Our vendor went down and we had no fallback&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Value Streams and Processes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;How work flows through the organization&lt;&#x2F;td&gt;&lt;td&gt;&quot;Everyone&#x27;s busy but nothing ships&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;These 4 dimensions are interdependent. Migrating to a new monitoring tool (Information &amp;amp; Technology) means retraining people (Organizations &amp;amp; People), renegotiating vendor contracts (Partners &amp;amp; Suppliers), and redesigning on-call workflows (Value Streams &amp;amp; Processes).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;h2&gt;
&lt;p&gt;These are universal principles that guide decision-making in any circumstance. They apply regardless of which practices you&#x27;re implementing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. Focus on value&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Every activity should link back to value for stakeholders. Before starting anything, ask: who benefits, and how? If you can&#x27;t answer that, stop.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. Start where you are&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Never ever assume you need to start from scratch. Assess what already works before designing something new. Most organizations already have something useful, the goal is to build on it, not erase it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. Progress iteratively with feedback&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Don&#x27;t try to design the perfect solution upfront. Deliver in small increments, gather feedback, adjust. This is the same philosophy behind Agile sprints and DevOps Continuous Delivery.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. Collaborate and promote visibility&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Work done in silos fails. Decisions made without the right people in the room fail. Make work visible: kanban boards, incident dashboards, change calendars; and involve stakeholders early, not at the end.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. Think and work holistically&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Services are systems. A change to one component can have unexpected effects elsewhere. Consider end-to-end impact, not just the piece in front of you. &lt;em&gt;Lol!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;6. Keep it simple and practical&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
If a process step doesn&#x27;t add value, eliminate it. If a tool creates more overhead than it saves, reconsider. Complexity is the enemy of reliability. Where I come from, we say &lt;strong&gt;&lt;em&gt;keep it simple and stupid&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;, see &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;KISS_principle&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;7. Optimize and automate&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
First, optimize the process (eliminate waste, reduce friction). Then, automate what remains. Automating a broken process gives you broken results, faster. The order matters.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-34-management-practices&quot;&gt;The 34 management practices&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 defines &lt;strong&gt;34 practices&lt;&#x2F;strong&gt; designed for performing work or accomplishing an objective. They replace what ITIL v3 called &quot;processes&quot; (the shift reflects that a practice includes culture, tools, and knowledge, not just the steps).&lt;&#x2F;p&gt;
&lt;p&gt;They&#x27;re organized into 3 categories:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Category&lt;&#x2F;th&gt;&lt;th&gt;Count&lt;&#x2F;th&gt;&lt;th&gt;Examples&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;General management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;14&lt;&#x2F;td&gt;&lt;td&gt;Risk management, knowledge management, project management, continual improvement, organizational change management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;17&lt;&#x2F;td&gt;&lt;td&gt;Incident management, problem management, change enablement, service desk, service level management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technical management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;Deployment management, infrastructure &amp;amp; platform management, software development &amp;amp; management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The full list of &lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;34-itil-4-management-practices&#x2F;&quot;&gt;34 ITIL 4 practices&lt;&#x2F;a&gt; exists for reference. No, you do not need to apply all 34 ITIL v4 practices. ITIL v4 is designed to be &lt;strong&gt;adopted and adapted&lt;&#x2F;strong&gt;. The core philosophy is to use &lt;strong&gt;only&lt;&#x2F;strong&gt; the practices that address your &lt;strong&gt;organization&#x27;s specific needs, pain points, and goals.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When you start, you need to identify your top 3 pain points (e.g., too many incidents, slow changes) to pick the right practices to implement first.&lt;&#x2F;p&gt;
&lt;p&gt;Here, we are almost starting from zero and we are already overwhelmed to the max. I would like to suggest 4 practices that, if we don&#x27;t have them, we&#x27;re operating blind:&lt;&#x2F;p&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;IT asset management        → What do we actually own?&lt;&#x2F;li&gt;
&lt;li&gt;Service request management → What are our users asking for?&lt;&#x2F;li&gt;
&lt;li&gt;Incident Management        → What is broken right now?&lt;&#x2F;li&gt;
&lt;li&gt;Change Enablement          → What is changing and why?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The 4 together cover the 4 basic operational questions any IT team needs answered at any moment. Everything else can be phased in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;incident-management&quot;&gt;Incident management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Incident management&lt;&#x2F;strong&gt; is the practice responsible for managing the lifecycle of all incidents: unplanned interruptions or reductions in the quality of a service. Before we go further, let&#x27;s nail the vocabulary:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A flaw in a component that could cause incidents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Incident&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An unplanned interruption or reduction in service quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Problem&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The cause (known or unknown) of one or more incidents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Known error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A problem that has been successfully analyzed, and a workaround or permanent solution has been identified&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Root Cause&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The fundamental reason behind a problem&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;These are distinct. An &lt;strong&gt;incident&lt;&#x2F;strong&gt; is what you respond to at 2am. A &lt;strong&gt;problem&lt;&#x2F;strong&gt; is what you investigate to prevent the next one. Conflating them is how teams fix the same incident repeatedly without ever addressing what&#x27;s actually causing it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-7-step-incident-lifecycle&quot;&gt;The 7-Step incident lifecycle&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Identification&lt;&#x2F;strong&gt;: monitoring alert, user report, or support ticket&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Logging&lt;&#x2F;strong&gt;: full record: timestamp, description, affected service, reporter&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Categorization&lt;&#x2F;strong&gt;: what type of incident? which service&#x2F;component?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Prioritization&lt;&#x2F;strong&gt;: how urgent? how impactful?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Diagnosis&lt;&#x2F;strong&gt;: initial investigation, probable cause&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Resolution&lt;&#x2F;strong&gt;: fix applied, service restored&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Closure&lt;&#x2F;strong&gt;: confirm resolution, document lessons, update knowledge base&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;incident-priority-matrix&quot;&gt;Incident Priority Matrix&lt;&#x2F;h3&gt;
&lt;p&gt;Priority is determined by &lt;strong&gt;Impact&lt;&#x2F;strong&gt; (how many users&#x2F;processes are affected) and &lt;strong&gt;Urgency&lt;&#x2F;strong&gt; (how quickly the business needs resolution). The matrix:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;High Urgency&lt;&#x2F;th&gt;&lt;th&gt;Medium Urgency&lt;&#x2F;th&gt;&lt;th&gt;Low Urgency&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;High Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;P1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P2&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Medium Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P2&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Low Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Trivial Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Priority codes (not to be confused with Biosafety Levels):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;P1 (Critical)&lt;&#x2F;strong&gt;: Production down, major business impact. Immediate response, all hands.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P2 (High)&lt;&#x2F;strong&gt;: Significant service degradation. Fast response, escalation ready.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P3 (Medium)&lt;&#x2F;strong&gt;: Partial impact, workaround available. Normal SLA response.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P4 (Low)&lt;&#x2F;strong&gt;: Minimal impact, cosmetic or edge case. Can be scheduled.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;NB: BSL (Biosafety Level) is the standard, modern terminology, while P (P1, P2, P3, P4) is an older designation standing for Pathogen&#x2F;Protection level.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;escalation&quot;&gt;Escalation&lt;&#x2F;h3&gt;
&lt;p&gt;The process within incident and service request management used to transfer issues to higher levels of authority or expertise when they cannot be resolved within normal, front-line support procedures.&lt;&#x2F;p&gt;
&lt;p&gt;When should we escalate ? When the incident exceed SLA timeframes, require higher expertise, or need more management authority.&lt;&#x2F;p&gt;
&lt;p&gt;There are 2 types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Functional escalation&lt;&#x2F;strong&gt;: pass to someone with more technical expertise&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical escalation&lt;&#x2F;strong&gt;: involve management when impact warrants it or when SLA breach is imminent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A &lt;strong&gt;crisis&lt;&#x2F;strong&gt; is when an incident has business-wide consequences that require executive involvement. Knowing when a P1 becomes a crisis (and who to call) should be documented &lt;em&gt;before&lt;&#x2F;em&gt; the crisis, not during it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;change-enablement&quot;&gt;Change enablement&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Change Enablement&lt;&#x2F;strong&gt; manages the lifecycle of all changes to maximize the probability of success and minimize disruption.&lt;&#x2F;p&gt;
&lt;p&gt;ITIL v4 recognizes 3 change types:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Risk&lt;&#x2F;th&gt;&lt;th&gt;Authorization&lt;&#x2F;th&gt;&lt;th&gt;Examples&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Standard&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Low, well-understood&lt;&#x2F;td&gt;&lt;td&gt;Pre-authorized&lt;&#x2F;td&gt;&lt;td&gt;Antivirus update, user account creation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Normal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable&lt;&#x2F;td&gt;&lt;td&gt;Change authority &#x2F; CAB review&lt;&#x2F;td&gt;&lt;td&gt;Application deployment, infrastructure change&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Emergency&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;High urgency&lt;&#x2F;td&gt;&lt;td&gt;Emergency authority (fast-track)&lt;&#x2F;td&gt;&lt;td&gt;Critical security patch, production hotfix&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-cab-change-advisory-board&quot;&gt;The CAB (Change Advisory Board)&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;strong&gt;CAB&lt;&#x2F;strong&gt; is a group that reviews and authorizes significant normal changes. Typical members: IT operations, security, business stakeholders, and the change owner. The CAB doesn&#x27;t exist to slow things down, it exists to catch problems before they become incidents. It is the organizational mechanism that &lt;em&gt;prevents the finance team from being unable to run payroll on a Friday.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A proper CAB dossier for a normal change includes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: which services, users, and systems are affected?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Risk&lt;&#x2F;strong&gt;: what&#x27;s the probability of failure, and what&#x27;s the impact if it fails?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rollback plan&lt;&#x2F;strong&gt;: how do we revert cleanly if the change fails? (Tested rollback, not theoretical)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Post-implementation review&lt;&#x2F;strong&gt;: how do we verify success after deployment?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;h2&gt;
&lt;p&gt;Continual improvement is both a guiding principle and a dedicated practice in ITIL 4. It ensures the organization continuously improves its services, practices, and the SVS itself.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;Continual Improvement Register (CIR)&lt;&#x2F;strong&gt; is the operational tool: a log of all improvement ideas, their status, priority, and outcomes. Think of it as a backlog specifically for operational improvements, not features, not incidents, but &lt;em&gt;how we work&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-7-step-improvement-model&quot;&gt;The 7-Step improvement model&lt;&#x2F;h3&gt;
&lt;p&gt;This model is cyclical by design. Reaching step 7 doesn&#x27;t mean you&#x27;re done, it means you start over with a new vision.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Question to Answer&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;What is the vision?&lt;&#x2F;strong&gt; Align the improvement to business strategy&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Where are we now?&lt;&#x2F;strong&gt; Baseline assessment: metrics, maturity, current state&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Where do we want to be?&lt;&#x2F;strong&gt; Define target state and measurable success criteria&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;How do we get there?&lt;&#x2F;strong&gt; Build the improvement plan&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Take action.&lt;&#x2F;strong&gt; Execute iteratively&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Did we get there?&lt;&#x2F;strong&gt; Measure against success criteria&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;How do we keep the momentum?&lt;&#x2F;strong&gt; Embed the change, celebrate wins, start the cycle again&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;measuring-improvement-sla-vs-xla-and-beyond&quot;&gt;Measuring improvement: SLA vs XLA and beyond&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;&#x2F;th&gt;&lt;th&gt;What It Measures&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;KPI&lt;&#x2F;strong&gt; (Key Performance Indicator)&lt;&#x2F;td&gt;&lt;td&gt;Technical performance against defined targets&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;SLA&lt;&#x2F;strong&gt; (Service Level Agreement)&lt;&#x2F;td&gt;&lt;td&gt;Contractual service commitments (uptime, response times)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;OKR&lt;&#x2F;strong&gt; (Objective and Key Result)&lt;&#x2F;td&gt;&lt;td&gt;Strategic goal achievement across a period&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;XLA&lt;&#x2F;strong&gt; (Experience Level Agreement)&lt;&#x2F;td&gt;&lt;td&gt;User satisfaction and actual experience quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;CIR&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Improvement pipeline health and throughput&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;SLA vs XLA&lt;&#x2F;strong&gt; deserves its own paragraph. An SLA measures &lt;em&gt;what the system does&lt;&#x2F;em&gt; (was uptime ≥ 99.9%?). An &lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;what-exactly-are-xlas-and-how-do-you-use-them&#x2F;&quot;&gt;XLA&lt;&#x2F;a&gt; measures &lt;em&gt;how the user felt about it&lt;&#x2F;em&gt;. You can meet every SLA and still have furious users, because the system was slow even within the threshold, or the error messages were unhelpful, or the support experience was frustrating. XLAs align IT metrics with actual business outcomes, not just technical compliance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-axes-of-improvement&quot;&gt;3 Axes of improvement&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strategic&lt;&#x2F;strong&gt;: organization-wide, long-term (e.g., &lt;em&gt;&quot;reach 95% automated change deployment by end of year&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tactical&lt;&#x2F;strong&gt;: team&#x2F;process level, medium-term (e.g., &lt;em&gt;&quot;reduce MTTR on P1 incidents by 40% this quarter&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Operational&lt;&#x2F;strong&gt;: day-to-day (e.g., &lt;em&gt;&quot;update the incident categorization taxonomy this sprint&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;governance-and-risk-management&quot;&gt;Governance and Risk Management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Governance&lt;&#x2F;strong&gt; sits at the top of the SVS. It provides direction and ensures the organization stays aligned with its objectives and obligations. Three functions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Direct&lt;&#x2F;strong&gt;: Set strategy, policies, and organizational objectives&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Evaluate&lt;&#x2F;strong&gt;: Assess organizational performance, risks, and compliance&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monitor&lt;&#x2F;strong&gt;: Track adherence to policies and verify outcomes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For service management, governance ensures that the SVS is accountable: decisions are traceable, risks are understood, and exceptions are handled systematically.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk Management&lt;&#x2F;strong&gt; in ITIL follows a straightforward formula:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Risk = Probability × Impact&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Three responses:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mitigate&lt;&#x2F;strong&gt;: reduce probability or impact (implement redundancy, add monitoring, require peer review)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Transfer&lt;&#x2F;strong&gt;: shift the risk to another party (insurance, contractual SLAs with vendors, outsourcing)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Accept&lt;&#x2F;strong&gt;: acknowledge the risk and decide to live with it (for low probability, low impact scenarios)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Risk isn&#x27;t inherently bad. The problem is &lt;strong&gt;unacknowledged risk&lt;&#x2F;strong&gt;, for example: changes deployed without a risk assessment, dependencies unknown until they fail, vulnerabilities known but not documented. Risk management doesn&#x27;t eliminate uncertainty; it makes it visible and traceable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;itil-4-agile-devops-lean&quot;&gt;ITIL 4 ↔ Agile, DevOps, Lean&lt;&#x2F;h2&gt;
&lt;p&gt;One of the major improvements in ITIL v4 over its predecessors is the explicit integration with modern practices. The framework doesn&#x27;t compete with DevOps or Agile. It provides the governance layer that makes them sustainable at scale.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;ITIL 4 Concept&lt;&#x2F;th&gt;&lt;th&gt;Agile Equivalent&lt;&#x2F;th&gt;&lt;th&gt;DevOps Equivalent&lt;&#x2F;th&gt;&lt;th&gt;Lean Equivalent&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;Service Value System&lt;&#x2F;td&gt;&lt;td&gt;Product Delivery Flow&lt;&#x2F;td&gt;&lt;td&gt;CI&#x2F;CD Pipeline&lt;&#x2F;td&gt;&lt;td&gt;Value Stream&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Continual Improvement&lt;&#x2F;td&gt;&lt;td&gt;Sprint Retrospective&lt;&#x2F;td&gt;&lt;td&gt;Blameless Post-mortem&lt;&#x2F;td&gt;&lt;td&gt;Kaizen&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Change Enablement&lt;&#x2F;td&gt;&lt;td&gt;Sprint Planning&lt;&#x2F;td&gt;&lt;td&gt;Deployment Pipeline&lt;&#x2F;td&gt;&lt;td&gt;Flow Management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Incident Management&lt;&#x2F;td&gt;&lt;td&gt;Bug Sprint&lt;&#x2F;td&gt;&lt;td&gt;Incident Response&lt;&#x2F;td&gt;&lt;td&gt;A3 Problem Solving&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Service Request&lt;&#x2F;td&gt;&lt;td&gt;Backlog Item&lt;&#x2F;td&gt;&lt;td&gt;Work Item&lt;&#x2F;td&gt;&lt;td&gt;Pull System&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;SLA &#x2F; XLA&lt;&#x2F;td&gt;&lt;td&gt;Definition of Done&lt;&#x2F;td&gt;&lt;td&gt;SLO &#x2F; SLI&lt;&#x2F;td&gt;&lt;td&gt;Quality Standards&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;CAB Review&lt;&#x2F;td&gt;&lt;td&gt;Sprint Review&lt;&#x2F;td&gt;&lt;td&gt;Deployment Gate&lt;&#x2F;td&gt;&lt;td&gt;Go&#x2F;No-Go Decision&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Problem Management&lt;&#x2F;td&gt;&lt;td&gt;Root Cause Analysis&lt;&#x2F;td&gt;&lt;td&gt;Post-mortem&lt;&#x2F;td&gt;&lt;td&gt;5 Whys&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Service Desk&lt;&#x2F;td&gt;&lt;td&gt;Product Owner (ops)&lt;&#x2F;td&gt;&lt;td&gt;L1&#x2F;L2 Support&lt;&#x2F;td&gt;&lt;td&gt;Andon Cord&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.axelos.com&#x2F;resource-hub&quot;&gt;official ITIL 4 and DevOps resources&lt;&#x2F;a&gt; make the integration case explicitly. The short version: &lt;strong&gt;ITIL handles governance and accountability; DevOps handles speed and flow. You need both.&lt;&#x2F;strong&gt; Speed without governance creates chaos. Governance without speed creates bureaucracy. ITIL v4 was redesigned precisely to not be the bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;case-study&quot;&gt;Case study&lt;&#x2F;h2&gt;
&lt;p&gt;Here is what ITIL v4 looks like applied to a real IT direction inside a biomedical research center in Senegal. Any resemblance to real persons, living or dead, is &lt;em&gt;purely coincidental.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-1-service-catalog&quot;&gt;Part 1 — Service catalog&lt;&#x2F;h3&gt;
&lt;p&gt;The official list of what the IT direction provides, to whom, under what terms. It is the operational contract between the IT team and the rest of the organization. Without it, users don&#x27;t know what to ask for, IT doesn&#x27;t know what they&#x27;re accountable for, and incidents pile up in a shared mailbox nobody consistently monitors.&lt;&#x2F;p&gt;
&lt;p&gt;Below: 5 services covering the majority of what a research institute IT direction actually handles day-to-day.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Service&lt;&#x2F;th&gt;
      &lt;th&gt;Description&lt;&#x2F;th&gt;
      &lt;th&gt;Channel&lt;&#x2F;th&gt;
      &lt;th&gt;SLA — Response &#x2F; Resolution&lt;&#x2F;th&gt;
      &lt;th&gt;Responsible&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;User account provisioning&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Creation, modification, or deactivation of accounts (Active Directory, email, VPN, application access). Covers onboarding and offboarding.&lt;&#x2F;td&gt;
      &lt;td&gt;ITSM ticketing portal &#x2F; HR workflow trigger&lt;&#x2F;td&gt;
      &lt;td&gt;4h &#x2F; 1 business day&lt;&#x2F;td&gt;
      &lt;td&gt;Sysadmin — Identity &amp;amp; Access team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Workstation support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Hardware diagnosis and repair, OS reinstall, peripheral setup (printers, scanners, external drives). On-site or remote via support session.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — phone for P1&#x2F;P2 only&lt;&#x2F;td&gt;
      &lt;td&gt;P3: 4h &#x2F; 2 days &amp;mdash; P4: next business day &#x2F; 5 days&lt;&#x2F;td&gt;
      &lt;td&gt;IT Support technician&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Application support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Functional support for lab and corporate applications: LIMS, ERP (finance, HR), syndromic surveillance platform, email (M365). Includes access requests and usage questions.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal, categorized by application&lt;&#x2F;td&gt;
      &lt;td&gt;P2: 2h &#x2F; 4h &amp;mdash; P3: 4h &#x2F; 1 day &amp;mdash; P4: 1 day &#x2F; 3 days&lt;&#x2F;td&gt;
      &lt;td&gt;Application owner + IT Operations&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;VPN &amp;amp; remote access&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Setup, configuration, and troubleshooting of remote access (VPN client, MFA token). Covers new setups for approved staff and incident resolution for existing connections.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — escalation via phone if blocking remote work&lt;&#x2F;td&gt;
      &lt;td&gt;New setup: 1 day &#x2F; 2 days &amp;mdash; Incident: 2h &#x2F; 4h&lt;&#x2F;td&gt;
      &lt;td&gt;Network team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Backup &amp;amp; data recovery&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Scheduled backups of research data, institutional databases, and user file shares. Restore requests for accidental deletions or corruption. Covers file-level and full-system restores.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — critical restores via phone (P1&#x2F;P2)&lt;&#x2F;td&gt;
      &lt;td&gt;P1 restore: 1h acknowledged &#x2F; 4h RTO &amp;mdash; P3 file restore: 4h &#x2F; 1 day&lt;&#x2F;td&gt;
      &lt;td&gt;Sysadmin — Infrastructure team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;part-2-rfc-cab-dossier-lims-major-version-upgrade&quot;&gt;Part 2 — RFC &amp;amp; CAB Dossier: LIMS major version upgrade&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;Request for Change (RFC)&lt;&#x2F;strong&gt; is the formal input to the Change Enablement practice. For a Normal or a Major change, it triggers a full CAB review before any action is taken. Here is what a complete dossier looks like.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;: Institut Patrick de Kinshasa uses a LIMS (Laboratory Information Management System) to track samples, tests, and results across all its labs. The vendor has released version 4.0, which drops support for the current version 3.x at end of year. The upgrade is not optional, but it touches sample data, active test runs, and integrations with the syndromic surveillance platform.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;rfc-identification&quot;&gt;RFC identification&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&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;strong&gt;RFC Number&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;RFC-2026-014&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Title&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS major version upgrade: v3.8 → v4.0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Change type&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Normal — Major&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Requestor&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Head of IT Operations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Application owner&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Director of Laboratory Services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Submission date&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Requested deployment window&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-23, Saturday 22:00 → Sunday 06:00 (WAT)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;CAB review date&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-13&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h4 id=&quot;justification&quot;&gt;Justification&lt;&#x2F;h4&gt;
&lt;p&gt;The current LIMS v3.x reaches vendor end-of-life on 2026-12-31. After that date: no security patches, no bug fixes, no vendor support. Version 4.0 also introduces a native REST API required by the next release of the syndromic surveillance platform. This change is driven by compliance (security posture) and technical dependency (surveillance platform roadmap) simultaneously.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;impact-assessment&quot;&gt;Impact assessment&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;&#x2F;th&gt;&lt;th&gt;Details&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Systems affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS application servers (lims-prod-01, lims-prod-02), LIMS PostgreSQL database (lims-db-01), integration bridge with surveillance platform&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Users affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~65 lab technicians and researchers across 4 departments: Virology, Bacteriology, Epidemiology, Quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Business processes affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sample reception, test assignment, result entry, result validation, report generation, QC workflows&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Downstream services&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Surveillance platform reads LIMS results via API — will operate in read-only degraded mode during the window&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Duration of impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS unavailable ~8 hours; all impact contained within the Saturday night window&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Data at risk&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~120,000 sample records, 3 years of test history. No patient PII in LIMS (samples referenced by anonymous ID).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;risk-assessment&quot;&gt;Risk assessment&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Risk&lt;&#x2F;th&gt;&lt;th&gt;Probability&lt;&#x2F;th&gt;&lt;th&gt;Impact&lt;&#x2F;th&gt;&lt;th&gt;Score&lt;&#x2F;th&gt;&lt;th&gt;Mitigation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;DB migration script fails mid-run, leaving schema in inconsistent state&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;Critical&lt;&#x2F;td&gt;&lt;td&gt;🔴 High&lt;&#x2F;td&gt;&lt;td&gt;Full DB snapshot before migration; script tested 3× on staging with a copy of production data&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;v4.0 breaks custom report templates (Quality dept uses non-standard format)&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;All 12 templates validated on staging; Quality dept sign-off obtained before CAB submission&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Surveillance platform integration fails after API change&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;High&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;Integration tested on staging against v4.0 API; surveillance team on standby Sunday 00:30&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Deployment overruns window, runs into Monday lab opening at 07:30&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;High&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;Hard rollback decision point at 04:00 — if not complete by then, rollback regardless of progress&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;UI changes slow down lab technicians Monday morning&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;🟢 Low&lt;&#x2F;td&gt;&lt;td&gt;30-min walkthrough session Monday 08:00; quick reference card distributed Friday&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;implementation-plan&quot;&gt;Implementation plan&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Time (WAT)&lt;&#x2F;th&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Responsible&lt;&#x2F;th&gt;&lt;th&gt;Checkpoint&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;Sat 21:30&lt;&#x2F;td&gt;&lt;td&gt;Pre-deployment checklist: verify backup completed, confirm no active test runs, notify on-call lab manager&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:00&lt;&#x2F;td&gt;&lt;td&gt;Put LIMS in maintenance mode (users see scheduled maintenance banner)&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:05&lt;&#x2F;td&gt;&lt;td&gt;Full PostgreSQL dump to backup server + verify checksum&lt;&#x2F;td&gt;&lt;td&gt;DBA&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:30&lt;&#x2F;td&gt;&lt;td&gt;Stop LIMS application services on both nodes&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:35&lt;&#x2F;td&gt;&lt;td&gt;Run database schema migration script (estimated: 45 min)&lt;&#x2F;td&gt;&lt;td&gt;DBA&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 23:20&lt;&#x2F;td&gt;&lt;td&gt;Deploy v4.0 application package on lims-prod-01 (primary node)&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 23:40&lt;&#x2F;td&gt;&lt;td&gt;Run automated smoke test suite against lims-prod-01&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 00:00&lt;&#x2F;td&gt;&lt;td&gt;Deploy v4.0 on lims-prod-02, verify cluster synchronization&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 00:30&lt;&#x2F;td&gt;&lt;td&gt;Test surveillance platform integration against new v4.0 API&lt;&#x2F;td&gt;&lt;td&gt;Surveillance team&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 01:00&lt;&#x2F;td&gt;&lt;td&gt;Manual validation by on-call lab manager: create test sample, enter result, generate report&lt;&#x2F;td&gt;&lt;td&gt;Lab manager&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 01:30&lt;&#x2F;td&gt;&lt;td&gt;Remove maintenance mode, monitor application logs for 30 min&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 02:00&lt;&#x2F;td&gt;&lt;td&gt;Deployment declared successful — confirmation sent to all stakeholders&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Hard rollback decision point: Sunday 04:00.&lt;&#x2F;strong&gt; If not complete and validated by then, rollback is initiated regardless of progress. No exceptions — the lab opens at 07:30.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;rollback-procedure&quot;&gt;Rollback procedure&lt;&#x2F;h4&gt;
&lt;p&gt;Triggered if: any required checkpoint fails and cannot be resolved within 30 minutes, OR the 04:00 hard deadline is reached.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Stop all LIMS application services on both nodes&lt;&#x2F;li&gt;
&lt;li&gt;Drop the migrated database: &lt;code&gt;dropdb lims_production&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Restore from the pre-migration dump: &lt;code&gt;pg_restore -d lims_production &#x2F;backup&#x2F;lims-premig-20260523.dump&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Verify integrity: compare row counts for &lt;code&gt;samples&lt;&#x2F;code&gt;, &lt;code&gt;tests&lt;&#x2F;code&gt;, &lt;code&gt;results&lt;&#x2F;code&gt; tables against the pre-migration snapshot&lt;&#x2F;li&gt;
&lt;li&gt;Redeploy the v3.8 package from artifact registry on both nodes&lt;&#x2F;li&gt;
&lt;li&gt;Restart application services, verify cluster health&lt;&#x2F;li&gt;
&lt;li&gt;Remove maintenance mode, run the same smoke test suite&lt;&#x2F;li&gt;
&lt;li&gt;Notify all stakeholders: rollback completed, root cause analysis scheduled Monday&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Estimated rollback duration: &lt;strong&gt;45 minutes.&lt;&#x2F;strong&gt; The 04:00 decision point leaves 2.5 hours of margin before lab opening.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;communication-plan&quot;&gt;Communication plan&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Audience&lt;&#x2F;th&gt;&lt;th&gt;Message&lt;&#x2F;th&gt;&lt;th&gt;When&lt;&#x2F;th&gt;&lt;th&gt;Channel&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;All LIMS users&lt;&#x2F;td&gt;&lt;td&gt;Scheduled maintenance — LIMS unavailable Saturday 22:00 → Sunday 06:00&lt;&#x2F;td&gt;&lt;td&gt;Friday 2026-05-22, 14:00&lt;&#x2F;td&gt;&lt;td&gt;Email + in-app banner&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Lab managers&lt;&#x2F;td&gt;&lt;td&gt;Upgrade rationale, v4.0 UI changes, quick reference card attached&lt;&#x2F;td&gt;&lt;td&gt;Friday 2026-05-22, 14:00&lt;&#x2F;td&gt;&lt;td&gt;Email&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Surveillance team&lt;&#x2F;td&gt;&lt;td&gt;API changes summary, integration test results, standby request for Sunday 00:30&lt;&#x2F;td&gt;&lt;td&gt;Thursday 2026-05-21&lt;&#x2F;td&gt;&lt;td&gt;Direct message + ticket&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;All stakeholders&lt;&#x2F;td&gt;&lt;td&gt;Outcome (success or rollback) + next steps&lt;&#x2F;td&gt;&lt;td&gt;Sunday 2026-05-24, by 06:00&lt;&#x2F;td&gt;&lt;td&gt;Email&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;post-implementation-review&quot;&gt;Post-implementation review&lt;&#x2F;h4&gt;
&lt;p&gt;Scheduled: &lt;strong&gt;Monday 2026-05-25, 10:00&lt;&#x2F;strong&gt; &#x2F; 30 minutes. Attendees: IT Ops lead, application owner, one representative per affected lab department.&lt;&#x2F;p&gt;
&lt;p&gt;Agenda:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Did deployment complete within window? If not: what caused the overrun?&lt;&#x2F;li&gt;
&lt;li&gt;Were all required checkpoints met? Document any deviations or waivers.&lt;&#x2F;li&gt;
&lt;li&gt;User-reported issues since go-live (collected Monday morning, before the review)&lt;&#x2F;li&gt;
&lt;li&gt;Was rollback triggered? If yes: full root cause analysis before next major change&lt;&#x2F;li&gt;
&lt;li&gt;Were Application Support SLAs met during the post-go-live monitoring period?&lt;&#x2F;li&gt;
&lt;li&gt;Update the LIMS runbook with any new procedures discovered during the upgrade&lt;&#x2F;li&gt;
&lt;li&gt;Close RFC-2026-014 in the ITSM tool; status: &lt;em&gt;Successful&lt;&#x2F;em&gt; or &lt;em&gt;Successful with deviations&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The output feeds directly into the &lt;strong&gt;Continual Improvement Register&lt;&#x2F;strong&gt;: anything harder than expected, any gap in the rollback procedure, any user adoption friction; logged as improvement items before the next major change.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h2&gt;
&lt;p&gt;No tool enforces ITIL by itself. The process has to exist first, the tool just reduces friction. That said, the right tooling makes the difference between a practice that lives on paper and one that teams actually follow.&lt;&#x2F;p&gt;
&lt;p&gt;A word on scope: &lt;strong&gt;ServiceNow&lt;&#x2F;strong&gt; is the de facto enterprise standard and covers nearly everything in the table below. It is also expensive, slow to configure, and overkill for most organizations below a few hundred IT staff.&lt;&#x2F;p&gt;
&lt;p&gt;The open source column below deserves serious consideration. &lt;strong&gt;GLPI&lt;&#x2F;strong&gt; in particular covers incident, change, CMDB, and knowledge management in a single self-hosted package.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;&#x2F;th&gt;
      &lt;th&gt;ITSM Platform&lt;&#x2F;th&gt;
      &lt;th&gt;Incident Detection &amp; Alerting&lt;&#x2F;th&gt;
      &lt;th&gt;Incident Response&lt;&#x2F;th&gt;
      &lt;th&gt;Knowledge Management&lt;&#x2F;th&gt;
      &lt;th&gt;Change Tracking&lt;&#x2F;th&gt;
      &lt;th&gt;Continual Improvement&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Suggested tools&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;ServiceNow, Jira Service Management, Freshservice&lt;&#x2F;td&gt;
      &lt;td&gt;PagerDuty, OpsGenie, incident.io&lt;&#x2F;td&gt;
      &lt;td&gt;FireHydrant, Rootly&lt;&#x2F;td&gt;
      &lt;td&gt;Confluence, Notion, GitBook&lt;&#x2F;td&gt;
      &lt;td&gt;Jira, LinearB&lt;&#x2F;td&gt;
      &lt;td&gt;Sleuth, Datadog, LinearB&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Free &amp; open source&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glpi-project.org&#x2F;&quot;&gt;GLPI&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.combodo.com&#x2F;itop&quot;&gt;iTop&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.znuny.org&#x2F;en&quot;&gt;Znuny&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;&quot;&gt;Prometheus + Alertmanager&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.zabbix.com&#x2F;&quot;&gt;Zabbix&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;—&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;js.wiki&#x2F;&quot;&gt;Wiki.js&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.getoutline.com&#x2F;&quot;&gt;Outline&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.bookstackapp.com&#x2F;&quot;&gt;BookStack&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;plane.so&#x2F;&quot;&gt;Plane&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;about.gitea.com&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dora-team&#x2F;fourkeys&quot;&gt;Four Keys (Google)&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;itil-v5&quot;&gt;ITIL v5&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve been taught during the training ITIL v5 was launched in february 2026. I tried to watch this &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8IxxdEgE_OE&quot;&gt;video&lt;&#x2F;a&gt; to have an overview of what is ITIL v5. The only thing I understood was: &quot;The new pace of changes today driven by &lt;a href=&quot;#&quot;&gt;cloud&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;ai&lt;&#x2F;a&gt;, digital products, experience-focused services, demand a new way of thinking.&quot; ITIL v5 answers that need. &lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 is a framework providing a &lt;strong&gt;vocabulary&lt;&#x2F;strong&gt; and a &lt;strong&gt;structure for conversations&lt;&#x2F;strong&gt; your organization was probably already having informally: &lt;em&gt;Who decides what gets changed? How do we prioritize when everything is on fire? How do we know we&#x27;re actually improving?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The most valuable takeaways from this training:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Value is co-created, not delivered.&lt;&#x2F;strong&gt; You can deploy perfect infrastructure and still fail if users can&#x27;t get value from it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;SLA ≠ user happiness&lt;&#x2F;strong&gt;. XLAs measure what actually matters to the business.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ITIL v4 and DevOps are complementary.&lt;&#x2F;strong&gt; ITIL provides the accountability layer that makes continuous delivery safe at organizational scale.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Adopt and adapt.&lt;&#x2F;strong&gt; Apply the practices that solve real problems, and leave the rest on the shelf until you need them.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If your systems go down and nobody knows who to call, what changed yesterday, or how long things have been broken, that&#x27;s not a technical problem. That&#x27;s a service management problem. ITIL v4 gives you the vocabulary to fix it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations, you made it to the end. If you enjoyed this, please &lt;em&gt;like, share &amp;amp; subscriiiibe&lt;&#x2F;em&gt;. You might also like my amazing post about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;AWS fundamentals&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;how I&#x27;m helping save lives in West Africa using free software&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This article is a summary of a three-day training course. Impossible to explore all the aspects of ITIL v4 in such a short post. Here are some useful links to lean more:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.peoplecert.org&#x2F;browse-certifications&#x2F;it-governance-and-service-management&#x2F;ITIL-1&quot;&gt;ITIL 4 official certification path&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;itil-guiding-principles&#x2F;&quot;&gt;ITIL 4 Guiding Principles explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;34-itil-4-management-practices&#x2F;&quot;&gt;34 ITIL 4 management practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;what-exactly-are-xlas-and-how-do-you-use-them&#x2F;&quot;&gt;What are XLAs and how do you use them?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itrevolution.com&#x2F;product&#x2F;the-phoenix-project&#x2F;&quot;&gt;The Phoenix project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sc.edu&#x2F;about&#x2F;offices_and_divisions&#x2F;ehs&#x2F;research_and_laboratory_safety&#x2F;biological_safety&#x2F;biosafety_level_criteria&#x2F;&quot;&gt;Biosafety Levels&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even more:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gamingworks.nl&#x2F;business-simulations&#x2F;apollo-13&#x2F;&quot;&gt;Apollo 13 – An ITSM Case Experience (GamingWorks)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gamechanginginsight.com&#x2F;itil-in-play&quot;&gt;GameChangingInsight ITIL simulations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;d12.github.io&#x2F;itil-quiz&#x2F;&quot;&gt;ITIL v4 quiz (open source)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;purplegriffon.com&#x2F;quizzes&#x2F;itil-4-foundation-quiz-questions-and-answers&quot;&gt;Purple Griffon ITIL 4 quiz&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.careersmarter.com&#x2F;itil-4-foundation-exam-questions&#x2F;&quot;&gt;Career Smarter mock exam&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.processexam.com&#x2F;peoplecert&#x2F;peoplecert-itil-4-foundation-certification-exam-sample-questions&quot;&gt;PeopleCert official sample questions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>From rsync to CI&#x2F;CD: automating a static site deployment</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://nskm.xyz/posts/mvln2/"/>
        <id>https://nskm.xyz/posts/mvln2/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/mvln2/">&lt;img style=&quot;display: block; margin: 0 auto; width: 700px&quot; src=&quot;&#x2F;images&#x2F;praying_ci_god.jpeg&quot; alt=&quot;Praying the CI&#x2F;CD god&quot; title=&quot;Praying the CI&#x2F;CD god&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;&#x2F;h2&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Opinions&lt;&#x2F;strong&gt;: The views expressed here are my own unless otherwise specified. They do not represent any employer, organization, or affiliated group.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;: This case study documents my personal journey automating a static Zola site. Your infrastructure needs may differ.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audience&lt;&#x2F;strong&gt;: This article assumes DevOps familiarity. You should be comfortable with Docker, shell scripts, git workflows, and Linux administration.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing environment&lt;&#x2F;strong&gt;: Everything in this article was tested on Ubuntu (WSL2 on Windows) running locally, and deployed to the cheapest DigitalOcean.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Thanks a million to &lt;a href=&quot;https:&#x2F;&#x2F;morgan.zoemp.be&#x2F;about&#x2F;&quot;&gt;Morgan&lt;&#x2F;a&gt; alias &lt;em&gt;SansGuidon&lt;&#x2F;em&gt; online. He took the time to tell me that I broke my atom.xml file during this experiment.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;If I recall correctly, I started writing tech articles somewhere around 2014. During all those years, my deployment workflow was delightfully simple: some Markdown files, two &lt;code&gt;make&lt;&#x2F;code&gt; commands, and my static site was live. It worked. It was fast. It required zero external infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;The irony? I spent years and years toying with CI&#x2F;CD pipelines for employers, using all the modern &lt;em&gt;(and all the very old)&lt;&#x2F;em&gt; tooling. Yet my &lt;em&gt;own&lt;&#x2F;em&gt; site ran like it was 2005. &lt;em&gt;What a world!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I sincerely believe that there was no good reason to change. I only did it for fun and to entertain myself a little (&lt;em&gt;and maybe, maybe, to improve things a little bit&lt;&#x2F;em&gt;). This is the story of how I did it: from a &lt;code&gt;git push&lt;&#x2F;code&gt; on my local machine to a fully built, containerized, deployed site on a fresh server, with automatic TLS. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=82-P9ZNYnik&quot;&gt;Music \o&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#journey&quot;&gt;The journey: where we were vs where we are going&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci&quot;&gt;GitLab CI pipeline&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci-config&quot;&gt; The GitLab CI configuration file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci-vars&quot;&gt; Required GitLab CI&#x2F;CD variables&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-registry&quot;&gt; GitLab container registry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#notification&quot;&gt; Notification mechanism: GitLab CI SSHes directly into VPS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#container-image&quot;&gt;The Container image&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#dockerfile&quot;&gt; The multi-stage Container file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#nginx-config&quot;&gt; The Nginx configuration file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#vps-provisioning&quot;&gt;The VPS provisioning&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#droplet&quot;&gt; Droplet recommendation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#provisioning-steps&quot;&gt; Provisioning steps&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#vps-hardening&quot;&gt; VPS security hardening&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#doctl&quot;&gt; Going further: one-command provisioning with doctl&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#deploy-script&quot;&gt; Deploy script&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#podman-critical&quot;&gt; Critical: rootless Podman and SSH session lifecycle&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#ssl-tls&quot;&gt;SSL &amp;amp; Let&#x27;s Encrypt&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#caddy&quot;&gt; Decision: Caddy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#letsencrypt-ip&quot;&gt; Let&#x27;s Encrypt IP address certificates&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#operations&quot;&gt;Operations&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#rollback&quot;&gt; Rollback procedure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#image-scanning&quot;&gt; Container image security scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#monitoring&quot;&gt; Uptime monitoring&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#zero-downtime&quot;&gt; Zero-downtime deploys&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#more&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;journey&quot;&gt;The journey&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;where-i-was-simple-short-deployment&quot;&gt;Where I was, simple&#x2F;short deployment&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;publish:
&lt;&#x2F;span&gt;&lt;span&gt;	zola build
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;rsync_deploy_site:
&lt;&#x2F;span&gt;&lt;span&gt;	zola build
&lt;&#x2F;span&gt;&lt;span&gt;	find public -name &amp;quot;*.xml&amp;quot; -o -name &amp;quot;*.html&amp;quot; | xargs sed -i -e &amp;#39;&#x2F;\&amp;amp;lt;!--.*--\&amp;amp;gt;&#x2F;d&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;	rsync -P -a -v --recursive -e &amp;quot;ssh -p $(SSH_PORT)&amp;quot; $(OUTPUTDIR)&#x2F; $(SSH_NICK):$(SSH_SITE_DIR) --cvs-exclude
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.PHONY: help publish rsync_deploy_site 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple deployment because it involved 3 tools. Short deployment because there was a straight, direct path between my laptop and the server. I built the site locally and pushed the output directly to the VPS via rsync over SSH. The Makefile orchestrates everything — it runs &lt;code&gt;zola build&lt;&#x2F;code&gt; and then calls &lt;code&gt;rsync&lt;&#x2F;code&gt; to copy the &lt;code&gt;public&#x2F;&lt;&#x2F;code&gt; directory to the server. That&#x27;s it.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[Local Machine]
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | 1. make publish
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ zola build  →  generates public&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | 2. make rsync_deploy_site
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ rsync -a public&#x2F; mlvn@1.2.3.4:&#x2F;home&#x2F;mlvn&#x2F;public (via SSH, port 1022)
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[DigitalOcean VPS]
&lt;&#x2F;span&gt;&lt;span&gt;  &#x2F;home&#x2F;mlvn&#x2F;public&#x2F;   ← raw static files on disk that are served by Nginx
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Nginx&#x2F;web server on VPS]
&lt;&#x2F;span&gt;&lt;span&gt;  Handles TLS (Let&amp;#39;s Encrypt, auto-renewed)
&lt;&#x2F;span&gt;&lt;span&gt;  serves files directly from disk
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Visitor&amp;#39;s browser]
&lt;&#x2F;span&gt;&lt;span&gt;  https:&#x2F;&#x2F;nskm.xyz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There were no external dependencies, no container images to build, no container registries to manage, no GitLab CI runners to wait for. Life was beautiful.&lt;&#x2F;p&gt;
&lt;p&gt;But... I did realize, &lt;em&gt;maaybe&lt;&#x2F;em&gt; I need a way to roll back a bad deployment. &lt;em&gt;Maaaybe&lt;&#x2F;em&gt; I need some version control. &lt;em&gt;Maaaaaybe&lt;&#x2F;em&gt; it&#x27;s not a good idea to have the source code living only on my laptop. &lt;em&gt;Maaaaaaaaybe&lt;&#x2F;em&gt; I need the build process to be reproducible. I mean, &lt;em&gt;come on man, I can do better&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;was_not_that_bad.png&quot; alt=&quot;When you take a step back, you realise that we have come a very long way.&quot; title=&quot;When you take a step back, you realise that we have come a very long way.&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;where-i-am-right-now-slightly-more-complex-deployment&quot;&gt;Where I am right now, slightly more complex deployment&lt;&#x2F;h3&gt;
&lt;p&gt;I do a git push to &lt;a href=&quot;https:&#x2F;&#x2F;raccoon.onyxbits.de&#x2F;blog&#x2F;why-not-use-github&quot;&gt;GitLab&lt;&#x2F;a&gt;. Everything else happens automagically: CI builds the HTML pages from the Markdown files, CI builds a Docker image containing the compiled site, then pushes it to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;&quot;&gt;GitLab Container Registry&lt;&#x2F;a&gt; and finally, SSHes into the VPS to pull and run the new image. &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; on the VPS handles TLS termination and proxies traffic to the container.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[Local Machine]
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | git push origin master
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[GitLab.com]
&lt;&#x2F;span&gt;&lt;span&gt;  Repository stores all source: content&#x2F;, templates&#x2F;, sass&#x2F;, themes&#x2F;, config.toml
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | .gitlab-ci.yml triggers pipeline automatically
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      ├─ Stage 1: build-and-push-image
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ docker:dind runner
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ zola build  (inside Dockerfile, Stage 1: debian:bookworm-slim)
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ output copied into nginx:alpine image  (Stage 2)
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ image built and tagged: registry.gitlab.com&#x2F;USERNAME&#x2F;proj:&amp;lt;commit-sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ image pushed to GitLab Container Registry
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      └─ Stage 2: deploy-to-vps
&lt;&#x2F;span&gt;&lt;span&gt;           ├─ alpine runner with openssh-client
&lt;&#x2F;span&gt;&lt;span&gt;           └─ SSH into VPS → runs &#x2F;home&#x2F;mlvn&#x2F;deploy.sh &amp;lt;commit-sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;                |
&lt;&#x2F;span&gt;&lt;span&gt;                v
&lt;&#x2F;span&gt;&lt;span&gt;[DigitalOcean VPS — new Droplet]
&lt;&#x2F;span&gt;&lt;span&gt;  deploy.sh:
&lt;&#x2F;span&gt;&lt;span&gt;    podman pull registry.gitlab.com&#x2F;USERNAME&#x2F;proj:&amp;lt;sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    podman stop nskm-site  (old container)
&lt;&#x2F;span&gt;&lt;span&gt;    podman run -d --name nskm-site -p 8080:80 IMAGE:&amp;lt;sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Caddy on VPS host]
&lt;&#x2F;span&gt;&lt;span&gt;  Handles TLS (Let&amp;#39;s Encrypt, auto-renewed)
&lt;&#x2F;span&gt;&lt;span&gt;  Caddyfile: reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Visitor&amp;#39;s browser]
&lt;&#x2F;span&gt;&lt;span&gt;  https:&#x2F;&#x2F;nskm.xyz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Pros of the CI&#x2F;CD approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I just git push code, site deploys itself&lt;&#x2F;li&gt;
&lt;li&gt;Version controlled: full git history, every change is tracked and auditable&lt;&#x2F;li&gt;
&lt;li&gt;Rollback: any previous image tag can be redeployed in seconds&lt;&#x2F;li&gt;
&lt;li&gt;Immutable deploys: each deploy is a fresh container from a known image, no partial file transfers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Cons of the CI&#x2F;CD approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;More moving parts, more things that can break: GitLab, container registry, Docker&#x2F;Podman, Caddy, deploy script&lt;&#x2F;li&gt;
&lt;li&gt;Slower feedback loop: pipeline takes more minutes&lt;&#x2F;li&gt;
&lt;li&gt;Registry storage to manage: images accumulate (mitigated by cleanup policy)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;ci_down.webp&quot; alt=&quot;CI is down&quot; title=&quot;CI is down&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;gitlab-ci&quot;&gt;GitLab CI pipeline&lt;&#x2F;h2&gt;
&lt;p&gt;TODO: gitlab ci file ???&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gitlab-ci-config&quot;&gt;The GitLab CI configuration file: &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Nothing fancy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker:24.0.5-cli&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;services&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker:24.0.5-dind&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;variables&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_TLS_CERTDIR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;certs&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_TLS_VERIFY&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_CERT_PATH&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$DOCKER_TLS_CERTDIR&#x2F;client&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_DRIVER&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;overlay2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_BUILDKIT&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;IMAGE_NAME&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;registry.gitlab.com&#x2F;$CI_PROJECT_NAMESPACE&#x2F;$CI_PROJECT_NAME&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;IMAGE_TAG&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_SHORT_SHA&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stages&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;before_script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker login -u &amp;quot;$CI_REGISTRY_USER&amp;quot; -p &amp;quot;$CI_REGISTRY_PASSWORD&amp;quot; &amp;quot;$CI_REGISTRY&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker build&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--cache-from &amp;quot;${IMAGE_NAME}:latest&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--build-arg BUILDKIT_INLINE_CACHE=1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-t &amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-t &amp;quot;${IMAGE_NAME}:latest&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:#b5cea8;&quot;&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker push &amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker push &amp;quot;${IMAGE_NAME}:latest&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;deploy-to-vps&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;alpine:3.19&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;before_script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apk add --no-cache openssh-client&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eval $(ssh-agent -s)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;echo &amp;quot;$MLVN_SSH_PRIVATE_KEY&amp;quot; | tr -d &amp;#39;\r&amp;#39; | base64 -d | ssh-add -&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mkdir -p ~&#x2F;.ssh &amp;amp;&amp;amp; chmod 700 ~&#x2F;.ssh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;echo &amp;quot;$MLVN_SSH_KNOWN_HOST&amp;quot; &amp;gt;&amp;gt; ~&#x2F;.ssh&#x2F;known_hosts&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ssh -p 1234 mlvn@$MLVN_IP &amp;quot;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh ${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;needs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;https:&#x2F;&#x2F;nskm.xyz&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;gitlab-ci-vars&quot;&gt;Required GitLab CI&#x2F;CD variables&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Variable&lt;&#x2F;th&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Protected&lt;&#x2F;th&gt;&lt;th&gt;Masked&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_SSH_PRIVATE_KEY&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (private key content)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (new Droplet IP once known)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (new Droplet IP once known)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;All other needed variables (&lt;code&gt;CI_REGISTRY_USER&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY_PASSWORD&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY&lt;&#x2F;code&gt;, &lt;code&gt;CI_COMMIT_SHORT_SHA&lt;&#x2F;code&gt;, etc.) are injected automatically by GitLab.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gitlab-registry&quot;&gt;GitLab container registry&lt;&#x2F;h3&gt;
&lt;p&gt;Every GitLab project has a &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;&quot;&gt;registry&lt;&#x2F;a&gt; at &lt;code&gt;registry.gitlab.com&#x2F;USERNAME&#x2F;PROJECT&lt;&#x2F;code&gt;. This allows me to store, manage, and distribute my &lt;a href=&quot;https:&#x2F;&#x2F;opencontainers.org&#x2F;&quot;&gt;OCI&lt;&#x2F;a&gt; images, alongside the source code and the CI&#x2F;CD pipelines. The authentication from the pipeline to the registry is automatic: GitLab injects &lt;code&gt;CI_REGISTRY_USER&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY_PASSWORD&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY&lt;&#x2F;code&gt; environment variables into every pipeline.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;vps-authentication-to-pull-images&quot;&gt;VPS authentication to pull images&lt;&#x2F;h4&gt;
&lt;p&gt;The VPS serving my website need to be able to pull the container image to run it. And for being able to pull the image, it also need to authenticate itself to the container registry. This is where Gitlab deploy token enters the play.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;project&#x2F;deploy_tokens&#x2F;&quot;&gt;GitLab deploy token&lt;&#x2F;a&gt; is a non-user specific credential used to authenticate automated tasks, such as &lt;em&gt;a VPS&lt;&#x2F;em&gt;, to access GitLab resources &lt;em&gt;like registries&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I created one GitLab deploy token, I picked the &lt;code&gt;read_registry&lt;&#x2F;code&gt; scope, I stored the credentials in &lt;code&gt;~&#x2F;.config&#x2F;containers&#x2F;auth.json&lt;&#x2F;code&gt;. This file stores your base64 encoded credentials to facilitate future registry operation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ cat ~&#x2F;.config&#x2F;containers&#x2F;auth.json
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;auths&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:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&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:#d69d85;&quot;&gt;&amp;quot;auth&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;XZwczpnbGR0LUdQeEg2M3pjeWlcGxveS10nskmb2tlbi1tbHZuLo2QnBGeXo1eDR0Z2l0bGFiK2&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;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;container-registry-cleanup-policy&quot;&gt;Container registry cleanup policy&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;reduce_container_registry_storage&#x2F;&quot;&gt;Container registries&lt;&#x2F;a&gt; can grow in size if you don&#x27;t manage your registry usage. Retrieving the list of available tags or images becomes slower. Images could take up a large amount of storage space on the server. So I defined a cleanup policy to keep last 5 tags, run weekly, remove tags older than 14 days.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notification&quot;&gt;Notification mechanism:&lt;&#x2F;h3&gt;
&lt;p&gt;I decided, GitLab CI will SSHes directly into VPS. There was two other options. The first one being a webhook receiver on VPS, which required installing &amp;amp; managing a webhook daemon and opening an extra port. The second one being polling. Why ?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No extra service to install on VPS&lt;&#x2F;li&gt;
&lt;li&gt;No extra ports to open&lt;&#x2F;li&gt;
&lt;li&gt;Deploy action is visible in GitLab pipeline logs&lt;&#x2F;li&gt;
&lt;li&gt;SSH is already used and understood&lt;&#x2F;li&gt;
&lt;li&gt;No polling delay&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I generated a dedicated ED25519 key pair for GitLab CI, different from my personal key. I stored the private key in GitLab CI variable marked &lt;code&gt;Protected&lt;&#x2F;code&gt; + &lt;code&gt;Masked&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;container-image&quot;&gt;The Container image&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;dockerfile&quot;&gt;The multi-stage Container file&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;dockerfile&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-dockerfile &quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stage 1: Build static site with Zola
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;debian:bookworm-slim &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;AS &lt;&#x2F;span&gt;&lt;span&gt;builder
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;ARG &lt;&#x2F;span&gt;&lt;span&gt;ZOLA_VERSION=0.18.0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y --no-install-recommends \
&lt;&#x2F;span&gt;&lt;span&gt;    wget ca-certificates \
&lt;&#x2F;span&gt;&lt;span&gt;    jpegoptim optipng gifsicle libimage-exiftool-perl \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;wget -q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;releases&#x2F;download&#x2F;v${ZOLA_VERSION}&#x2F;zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; \
&lt;&#x2F;span&gt;&lt;span&gt;    -O &#x2F;tmp&#x2F;zola.tar.gz \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; tar -xzf &#x2F;tmp&#x2F;zola.tar.gz -C &#x2F;usr&#x2F;local&#x2F;bin&#x2F; \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; chmod +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;zola \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm &#x2F;tmp&#x2F;zola.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;site
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; config.toml .
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; themes&#x2F; themes&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; static&#x2F; static&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; templates&#x2F; templates&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; content&#x2F; content&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;zola build \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.xml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -o -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.html&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; | xargs sed -i -e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;lt;!--.*--&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;gt;&#x2F;d&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Strip metadata (EXIF, GPS, IPTC, ICC profiles) from all images
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;exiftool -all= -overwrite_original -recurse public
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Optimize images (lossless)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# For lossy JPEG (visually identical, ~60-80% smaller): add --max=85
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;find public -type f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span&gt; -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -o -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.jpeg&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\)&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r jpegoptim --strip-all \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r optipng -o2 -strip all \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.gif&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r gifsicle -O3 --batch
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stage 2: Serve with minimal Nginx
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;nginx:1.25-alpine &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;AS &lt;&#x2F;span&gt;&lt;span&gt;serve
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;rm -rf &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;site&#x2F;public&#x2F; &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; nginx.conf &#x2F;etc&#x2F;nginx&#x2F;conf.d&#x2F;default.conf
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;EXPOSE &lt;&#x2F;span&gt;&lt;span&gt;80
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;CMD &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nginx&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-g&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;daemon off;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;nginx-config&quot;&gt;The Nginx configuration file&lt;&#x2F;h3&gt;
&lt;p&gt;Why using Nginx inside the container and not Caddy ? Nginx inside the container serves HTTP only on port 80. SSL is handled by Caddy on the VPS host outside the container. Caddy&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;features&quot;&gt;killer features&lt;&#x2F;a&gt;, &lt;em&gt;you might want to sit down for this&lt;&#x2F;em&gt;, are completely wasted inside a container that only serves static files over plain HTTP to localhost. &lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;_&#x2F;nginx&quot;&gt;Nginx Alpine&lt;&#x2F;a&gt; is very small and purpose-built for this job.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;nsukami@IPD-DDSI5:~&#x2F;GIT&#x2F;nskm2$ podman images &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep nginx
&lt;&#x2F;span&gt;&lt;span&gt;docker.io&#x2F;library&#x2F;nginx                                                  1.29.5-alpine-slim  a68d27696acb  3 weeks ago    13.5 MB
&lt;&#x2F;span&gt;&lt;span&gt;docker.io&#x2F;library&#x2F;nginx                                                  1.25-alpine         501d84f5d064  22 months ago  50.1 MB
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;nginx&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-nginx &quot;&gt;&lt;code class=&quot;language-nginx&quot; data-lang=&quot;nginx&quot;&gt;&lt;span&gt;server {
&lt;&#x2F;span&gt;&lt;span&gt;    listen 80;
&lt;&#x2F;span&gt;&lt;span&gt;    root &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html;
&lt;&#x2F;span&gt;&lt;span&gt;    index index.html;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gzip on;
&lt;&#x2F;span&gt;&lt;span&gt;    gzip_types text&#x2F;plain text&#x2F;css application&#x2F;json application&#x2F;javascript
&lt;&#x2F;span&gt;&lt;span&gt;               text&#x2F;xml application&#x2F;xml text&#x2F;javascript image&#x2F;svg+xml;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|webp|mp4|pdf)$ {
&lt;&#x2F;span&gt;&lt;span&gt;        expires 1y;
&lt;&#x2F;span&gt;&lt;span&gt;        add_header Cache-Control &amp;quot;public, immutable&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    location &#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;        try_files $uri $uri&#x2F; $uri.html =404;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    error_page 404 &#x2F;404.html;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;vps-provisioning&quot;&gt;The VPS provisioning&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;droplet&quot;&gt;Droplet recommendation&lt;&#x2F;h3&gt;
&lt;p&gt;I am a proud DigitalOcean user since 2011. At that time, I was looking for ways to learn about a real server with a real IP address, the one that are publicly accessible. At that time, I had no credit card, &lt;em&gt;no money to be honest&lt;&#x2F;em&gt;. My first server on this platform was offered to me by a very good friend. He paid for the VPS and gave me the root credentials, then, asked me to correctly harden the server, the rest is history.&lt;&#x2F;p&gt;
&lt;p&gt;For this experiment, 1 vCPU, 1GB RAM, 25GB SSD, Ubuntu 24.04 LTS should be more than enough. Keep the old Droplet running (rsync deploys still work) while you set up the new one, update DNS to the new IP once it&#x27;s ready, then decommission the old one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;provisioning-steps&quot;&gt;Provisioning steps (in order)&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 1. Update packages
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get update &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get upgrade -y
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 2. Firewall
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y ufw
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 1234&#x2F;tcp   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# SSH on custom port
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 80&#x2F;tcp     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# HTTP (Caddy ACME challenge + redirect)
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 443&#x2F;tcp    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# HTTPS
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw enable
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 3. Install Podman
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get -y install podman
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 4. Install Caddy
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https
&lt;&#x2F;span&gt;&lt;span&gt;curl -1sLf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;gpg.key&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:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;sudo gpg --dearmor -o &#x2F;usr&#x2F;share&#x2F;keyrings&#x2F;caddy-stable-archive-keyring.gpg
&lt;&#x2F;span&gt;&lt;span&gt;curl -1sLf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;debian.deb.txt&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:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;sudo tee &#x2F;etc&#x2F;apt&#x2F;sources.list.d&#x2F;caddy-stable.list
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get update &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y caddy
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 5. Configure Caddy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# edit &#x2F;etc&#x2F;caddy&#x2F;Caddyfile with the following content:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#   nskm.xyz {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#       reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#   }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 6. enable and start the service
&lt;&#x2F;span&gt;&lt;span&gt;sudo systemctl enable caddy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo systemctl start caddy
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 7. Authenticate Podman to GitLab registry
&lt;&#x2F;span&gt;&lt;span&gt;podman login registry.gitlab.com -u DEPLOY_TOKEN_USER -p DEPLOY_TOKEN_VALUE
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;vps-hardening&quot;&gt;VPS security hardening&lt;&#x2F;h3&gt;
&lt;p&gt;There are &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials?q=%5Bsecurity%5D+harden&quot;&gt;lots of tutorials&lt;&#x2F;a&gt; explaining how you should harden the security of your server. I think, there is no need to discuss the matter here.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;doctl&quot;&gt;Going further: one-command provisioning with doctl&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.digitalocean.com&#x2F;reference&#x2F;doctl&#x2F;&quot;&gt;doctl&lt;&#x2F;a&gt; is DigitalOcean&#x27;s CLI tool that I&#x27;ve never used. &lt;a href=&quot;https:&#x2F;&#x2F;cloud-init.io&#x2F;&quot;&gt;Cloud-init&lt;&#x2F;a&gt; is a standard way to run scripts on first boot that I&#x27;ve never used too. I absolutely must find a way to use both tools more often.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A cloud-init script&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is essentially the provisioning steps from above, packed into a single file that runs automatically when the Droplet first boots. Create a file called &lt;code&gt;cloud-init.sh&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#cloud-config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&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;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ALL=(ALL) NOPASSWD:ALL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ssh_authorized_keys&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ssh-ed25519 AAAA... your-public-key-here&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;package_update&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;package_upgrade&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;packages&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;podman&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;fail2ban&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;unattended-upgrades&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;debian-keyring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;debian-archive-keyring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-transport-https&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;write_files&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;caddy&#x2F;Caddyfile&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      nskm.xyz {
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;fail2ban&#x2F;jail.d&#x2F;sshd.conf&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      [sshd]
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      enabled = true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      port    = 1234
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config.d&#x2F;hardening.conf&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PermitRootLogin no
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PasswordAuthentication no
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      Port 1234
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;permissions&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0755&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;owner&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mlvn:mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      #!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      set -euo pipefail
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      IMAGE=&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;proj&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      TAG=&amp;quot;${1:-latest}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      CONTAINER=&amp;quot;nskm-site&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PORT=8080
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      echo &amp;quot;Deploying ${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker pull &amp;quot;${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker stop &amp;quot;${CONTAINER}&amp;quot; 2&amp;gt;&#x2F;dev&#x2F;null || true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker rm &amp;quot;${CONTAINER}&amp;quot; 2&amp;gt;&#x2F;dev&#x2F;null || true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker run -d --name &amp;quot;${CONTAINER}&amp;quot; --restart unless-stopped -p &amp;quot;${PORT}:80&amp;quot; &amp;quot;${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker image prune -f
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      echo &amp;quot;Done: ${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runcmd&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Firewall
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 1234&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 80&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 443&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw --force enable&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:#608b4e;&quot;&gt;# Install Podman
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y podman&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:#608b4e;&quot;&gt;# Install Caddy
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;curl -1sLf &amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;gpg.key&amp;#39; | gpg --dearmor -o &#x2F;usr&#x2F;share&#x2F;keyrings&#x2F;caddy-stable-archive-keyring.gpg&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;curl -1sLf &amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;debian.deb.txt&amp;#39; | tee &#x2F;etc&#x2F;apt&#x2F;sources.list.d&#x2F;caddy-stable.list&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y caddy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl enable caddy &amp;amp;&amp;amp; systemctl start caddy&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:#608b4e;&quot;&gt;# Security
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl enable fail2ban --now&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl restart ssh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;dpkg-reconfigure --priority=low unattended-upgrades&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:#608b4e;&quot;&gt;# Enable linger for rootless containers (if using Podman later)
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;loginctl enable-linger mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Create the Droplet using the doctl command&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;doctl compute droplet create nskm-vps \
&lt;&#x2F;span&gt;&lt;span&gt;  --image ubuntu-24-04-x64 \
&lt;&#x2F;span&gt;&lt;span&gt;  --size s-1vcpu-1gb \
&lt;&#x2F;span&gt;&lt;span&gt;  --region ams3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --ssh-keys $(doctl compute ssh-key list --format ID --no-header &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;head -1) \
&lt;&#x2F;span&gt;&lt;span&gt;  --user-data-file .&#x2F;cloud-init.sh \
&lt;&#x2F;span&gt;&lt;span&gt;  --wait
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And voilà!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;deploy-script&quot;&gt;Deploy script: &lt;code&gt;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is the script that will be called by Gitlab whenever a new image is built:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;set -euo pipefail
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;IMAGE=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;nskm2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TAG=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;1:-&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;latest}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;nskm-site&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deploying ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker pull &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker stop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;docker rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;docker run -d --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; --restart unless-stopped -p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:80&amp;quot; &amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker image prune -f
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Done: ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;chmod +x &#x2F;home&#x2F;mlvn&#x2F;deploy.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;podman-critical&quot;&gt;Critical: rootless Podman and SSH session lifecycle&lt;&#x2F;h3&gt;
&lt;p&gt;During my various tests, I noticed some strange behaviour. The deploy log shows success and the health check passes, but the site returns 502 immediately after the CI job finishes:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ # Job succeeded....
&lt;&#x2F;span&gt;&lt;span&gt;$ ssh -p 1234 mlvn@$MLVN_IP &amp;quot;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh ${IMAGE_TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;Deploying registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fg2abf
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;Running health check...
&lt;&#x2F;span&gt;&lt;span&gt;Done: registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fg2abf is live
&lt;&#x2F;span&gt;&lt;span&gt;Job succeeded
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$ # Yet...
&lt;&#x2F;span&gt;&lt;span&gt;$ curl -I &amp;quot;http:&#x2F;&#x2F;1.2.3.4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;HTTP&#x2F;1.1 502 Bad Gateway
&lt;&#x2F;span&gt;&lt;span&gt;Server: Caddy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even more confusing...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;podman ps -a&lt;&#x2F;code&gt; shows the container in &lt;code&gt;Exited (0)&lt;&#x2F;code&gt; state, and &lt;code&gt;podman logs nskm-site&lt;&#x2F;code&gt; confirms it received SIGTERM seconds after the health check passed:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;22:03:54 — container starts
&lt;&#x2F;span&gt;&lt;span&gt;22:03:57 — health check hits it: &amp;quot;GET &#x2F; HTTP&#x2F;1.1&amp;quot; 200  ✓
&lt;&#x2F;span&gt;&lt;span&gt;22:04:07 — signal 15 (SIGTERM) received, exiting       ← WTF?!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;kanye_wtf.gif&quot; alt=&quot;wtf&quot; title=&quot;wtf&quot;&#x2F;&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lists.podman.io&#x2F;archives&#x2F;list&#x2F;podman@lists.podman.io&#x2F;thread&#x2F;CQTZAORZXW6UWDNAV5TAWAV6PTDJFW6V&#x2F;&quot;&gt;The problem&lt;&#x2F;a&gt;: When using rootless Podman (Podman running as a regular user, not root), containers are tied to the user&#x27;s login session. When a CI job SSHes into the VPS, runs &lt;code&gt;deploy.sh&lt;&#x2F;code&gt;, and disconnects, the SSH session ends and systemd cleans up the session, sending SIGTERM to all processes in it, including the running container.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;latest&#x2F;loginctl.html&quot;&gt;The solution&lt;&#x2F;a&gt;: enabling lingering for the user running the container:**&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;loginctl enable-linger mlvn  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# run once on the VPS
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This instructs systemd to keep the &lt;code&gt;mlvn&lt;&#x2F;code&gt; user session alive permanently, even after logout. Containers started by this user will survive SSH disconnection.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Verify:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;loginctl show-user mlvn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep Linger
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Expected output: Linger=yes
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;This must be run before the first real deploy.&lt;&#x2F;strong&gt; Without it, every CI deploy will appear to succeed but the site will go down immediately after the SSH session closes.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;ssl-tls&quot;&gt;SSL &amp;amp; Let&#x27;s Encrypt&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;caddy&quot;&gt;Decision: Caddy&lt;&#x2F;h3&gt;
&lt;p&gt;Caddy handles everything automatically with a single config line:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm.xyz {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In 3 lines, Caddy:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Obtains Let&#x27;s Encrypt cert on first request automatically&lt;&#x2F;li&gt;
&lt;li&gt;Renews before expiry (auto, no cron needed, no certbot)&lt;&#x2F;li&gt;
&lt;li&gt;Redirects HTTP → HTTPS automatically&lt;&#x2F;li&gt;
&lt;li&gt;Stores certs in &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;caddy&#x2F;.local&#x2F;share&#x2F;caddy&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I remember the time when I had to &lt;em&gt;get my geek on&lt;&#x2F;em&gt; and do eveything myself, &lt;em&gt;as a proud Linux user&lt;&#x2F;em&gt;: certbot install, cron job, renewal hooks, manual intervention when things break. &lt;em&gt;Phew&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;jpoesen.png&quot; alt=&quot;A very looooooong time ago&quot; title=&quot;A very looooooong time ago&quot;&#x2F;&gt;
&lt;br&gt;
&lt;h3 id=&quot;letsencrypt-ip&quot;&gt;Let&#x27;s Encrypt IP address certificates (January 2026)&lt;&#x2F;h3&gt;
&lt;p&gt;Amazing how few years ago, it was something you didn&#x27;t think about. Today, Let&#x27;s Encrypt now issues &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;2026&#x2F;01&#x2F;15&#x2F;6day-and-ip-general-availability&quot;&gt;certificates for raw IP addresses&lt;&#x2F;a&gt;. I was thinking about using it for the new VPS, before updating the DNS to the new IP address. Then I learned IP address certs are &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;2026&#x2F;01&#x2F;15&#x2F;6day-and-ip-general-availability&quot;&gt;short-lived certificates&lt;&#x2F;a&gt; — they are valid only for &lt;strong&gt;160 hours (≈6 days)&lt;&#x2F;strong&gt; instead of the usual 90 days. Not a problem in practice, just worth knowing.&lt;&#x2F;p&gt;
&lt;p&gt;Where this could be useful on this VPS ? Maybe ....&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;YOUR_VPS_IP {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:SOME_PORT
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;operations&quot;&gt;Operations&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;rollback&quot;&gt;Rollback procedure&lt;&#x2F;h3&gt;
&lt;p&gt;One of the reasons &lt;em&gt;(probably the main reason)&lt;&#x2F;em&gt; I moved to CI&#x2F;CD was the ability to rollback a deployment. With rsync, rolling back meant &quot;do you still have the old files somewhere?&quot;. With container images, every deploy is tagged with its commit SHA and stored in the GitLab registry.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Available image tags on the VPS:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ podman login registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Authenticating with existing credentials for registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Existing credentials are valid. Already logged in to registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$ podman images --format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{.Repository}}:{{.Tag}}  {{.CreatedAt}}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep nskm
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:6c08ce72  2026-03-03 06:59:24 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:latest  2026-03-01 21:46:30 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf  2026-03-01 21:46:30 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:9a326e8c  2026-03-01 21:30:53 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:005ba0d9  2026-03-01 17:21:40 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Roll back to a previous version:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ .&#x2F;deploy.sh b7fb2abf
&lt;&#x2F;span&gt;&lt;span&gt;Login in to the Gitlab container registry
&lt;&#x2F;span&gt;&lt;span&gt;Authenticating with existing credentials for registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Existing credentials are valid. Already logged in to registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Deploying registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf
&lt;&#x2F;span&gt;&lt;span&gt;Trying to pull registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf...
&lt;&#x2F;span&gt;&lt;span&gt;Getting image source signatures
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 5406ed7b06d9 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 4abcf2066143 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob fc21a1d387f5 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob e6ef242c1570 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 13fcfbc94648 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob d4bca490e609 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 8a3742a9529d skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 0d0c16747d2c skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob f7809d4c4360 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 3ee6c312ca9b skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob ed4f6e59d232 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying config 632bfe60dc done   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span&gt;Writing manifest to image destination
&lt;&#x2F;span&gt;&lt;span&gt;632bfe60dce5626a87db391496d017ed1dc7d5f805af81fa5936cbb0323c0099
&lt;&#x2F;span&gt;&lt;span&gt;nskm-site
&lt;&#x2F;span&gt;&lt;span&gt;nskm-site
&lt;&#x2F;span&gt;&lt;span&gt;ef7a0a78ee6b047b5fbb0c5b4e6622fff4769096d12ec21384c36149d000f669
&lt;&#x2F;span&gt;&lt;span&gt;Running health check...
&lt;&#x2F;span&gt;&lt;span&gt;Done: registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf is live
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it. The deploy script pulls the old image (already cached locally if it was recently used), stops the current container, and starts a new one based on the old image. The site is back to its previous state in seconds.&lt;&#x2F;p&gt;
&lt;p&gt;If the image has been pruned locally, Podman pulls it from the GitLab registry; as long as it&#x27;s within the cleanup policy window.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;image-scanning&quot;&gt;Container image security scanning&lt;&#x2F;h3&gt;
&lt;p&gt;Every container image inherits vulnerabilities from its base image. While &lt;code&gt;debian:bookworm-slim&lt;&#x2F;code&gt; and &lt;code&gt;nginx:1.25-alpine&lt;&#x2F;code&gt; are well-maintained, they still ship with system libraries that occasionally have known CVEs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy&lt;&#x2F;a&gt; is a free, open-source scanner that checks container images against vulnerability databases. Adding it as a CI stage between build and deploy means a vulnerable image never reaches the VPS.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;scan-image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;scan&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aquasec&#x2F;trivy:latest&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;entrypoint&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trivy image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--exit-code 1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--severity HIGH,CRITICAL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--no-progress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;needs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allow_failure&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;--exit-code 1&lt;&#x2F;code&gt; makes the pipeline fail if HIGH or CRITICAL vulnerabilities are found. &lt;code&gt;allow_failure: true&lt;&#x2F;code&gt; means the deploy can still proceed — it&#x27;s a warning, not a blocker. Remove &lt;code&gt;allow_failure&lt;&#x2F;code&gt; once you&#x27;re confident in your base images.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;monitoring&quot;&gt;Uptime monitoring&lt;&#x2F;h3&gt;
&lt;p&gt;The CI pipeline can succeed and the site can still go down — I learned that the hard way with the Podman linger issue. The pipeline reports success, you go to bed, and the site has been returning 502 for hours. Nobody notices until someone tries to visit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;uptimerobot.com&#x2F;&quot;&gt;UptimeRobot&lt;&#x2F;a&gt; pings your site every 5 minutes and notifies you when it&#x27;s unreachable. In this real, there is also &lt;a href=&quot;#&quot;&gt;Hetrix&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;StatusCake&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Odown&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Uptime Kuma&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Better Stack&lt;&#x2F;a&gt;. Never tried none of them.&lt;&#x2F;p&gt;
&lt;p&gt;This is just a way to close the &lt;a href=&quot;https:&#x2F;&#x2F;www.dynatrace.com&#x2F;news&#x2F;blog&#x2F;what-is-observability-2&#x2F;&quot;&gt;observability&lt;&#x2F;a&gt; gap: the CI watches the deploy process, and &lt;em&gt;something&lt;&#x2F;em&gt; watches the &lt;strong&gt;deployed result&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 350px&quot; src=&quot;&#x2F;images&#x2F;observability.gif&quot; alt=&quot;observing&quot; title=&quot;Observing&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;zero-downtime&quot;&gt;Zero-downtime deploys&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lpalmieri.com&#x2F;posts&#x2F;zero-downtime-deployments&#x2F;&quot;&gt;Zero downtime deployment&lt;&#x2F;a&gt; (ZDD) is the art of updating applications without interrupting service by running &lt;strong&gt;new&lt;&#x2F;strong&gt; and &lt;strong&gt;old&lt;&#x2F;strong&gt; versions simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;The current deploy script has a brief downtime window: stop old container, start new one. For a personal blog, nobody notices. But it&#x27;s a fun problem to solve and a useful pattern to know.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I did:&lt;&#x2F;strong&gt; run two containers on two ports (8080 and 8081). Caddy &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;reverse_proxy&quot;&gt;reverse proxies&lt;&#x2F;a&gt; to both. At any given time, only one is alive.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated Caddyfile:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm.xyz {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:8080 localhost:8081
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Caddy with multiple upstreams does &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;reverse_proxy#passive-health-checks&quot;&gt;passive health checking&lt;&#x2F;a&gt;, meaning, if one upstream doesn&#x27;t respond, it routes to the other. If a request hits a dead upstream, Caddy retries on the next one before returning an error.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated deploy script:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;set -euo pipefail
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;IMAGE=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;proj&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TAG=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;1:-&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;latest}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;podman pull &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Which port is currently in use?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;podman ps --format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{.Names}}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep -q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-8080&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    OLD_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8081&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    OLD_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8081&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deploying ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;} on port ${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Start new container on the free port
&lt;&#x2F;span&gt;&lt;span&gt;podman run -d --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;    --restart unless-stopped -p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:80&amp;quot; &amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Health check
&lt;&#x2F;span&gt;&lt;span&gt;sleep 2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if ! &lt;&#x2F;span&gt;&lt;span&gt;curl -sf --max-time 5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;localhost:${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Health check FAILED — old container still live on port ${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    podman rm -f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    exit 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stop old container (Caddy automatically routes to the new one)
&lt;&#x2F;span&gt;&lt;span&gt;podman stop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;podman rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;podman image prune -f
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Done: ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;} live on port ${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What happens during a deploy:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Time ──────────────────────────────────────────────────►
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Old container (:8080)  ████████████████████████████████████▓░░░░░░░░░░
&lt;&#x2F;span&gt;&lt;span&gt;New container (:8081)              ░░░░▓████████████████████████████████
&lt;&#x2F;span&gt;&lt;span&gt;Caddy routes to        ──8080────────────────────────────┐
&lt;&#x2F;span&gt;&lt;span&gt;                                                            └──8081───────
&lt;&#x2F;span&gt;&lt;span&gt;Health check                       ✓
&lt;&#x2F;span&gt;&lt;span&gt;                                          ▲
&lt;&#x2F;span&gt;&lt;span&gt;                                     old stopped here
&lt;&#x2F;span&gt;&lt;span&gt;                                     zero downtime
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both containers run simultaneously during the transition. Caddy&#x27;s health checking handles the routing. The deploy script only needs to know what is the port Podman is currently running on.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;more&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;The shift from manual rsync deployments to automated CI&#x2F;CD took few hours of research, mistakes, and refinement. The hardest part wasn&#x27;t the Docker setup or GitLab CI — it was that subtle Podman session lifecycle issue that made the site silently disappear after every successful deploy.&lt;&#x2F;p&gt;
&lt;p&gt;But now, deploying is automagic. My site has a full audit trail. I can rollback to any previous version in seconds. And, now that I&#x27;m looking at it, I&#x27;m no longer tethered to one computer.&lt;&#x2F;p&gt;
&lt;p&gt;The trade-offs are real: the pipeline takes longer and there are more moving parts. Yet, I would like to go even further, and make things even funnier: running a Pod inside the VPS, and inside the Pod, having 2 containers, one for the website, and another for, I don&#x27;t know, collect &amp;amp; ship the logs ?! We&#x27;ll see.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 350px&quot; src=&quot;&#x2F;images&#x2F;moving_parts.gif&quot; alt=&quot;Too many moving parts&quot; title=&quot;Too many moving parts&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Here is the big picture showing what has been done:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;+-------------+        git push           +-----------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;|             | ------------------------&amp;gt; |                GitLab.com               |
&lt;&#x2F;span&gt;&lt;span&gt;|             |                           |                                         |
&lt;&#x2F;span&gt;&lt;span&gt;|   Laptop    |    email on failure       |                                         |
&lt;&#x2F;span&gt;&lt;span&gt;|             | &amp;lt;------------------------ |  +-----------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;+-------------+                           |  |          CI&#x2F;CD Pipeline           |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  1. build-and-push-image          |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     docker build                  |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     docker push -----------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  2. scan-image (Trivy)            |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     checks for CVEs               |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  3. deploy-to-vps                 |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     SSH ---------------------------------+   |
&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;                                          |       GitLab Container Registry      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |                                      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:abc1234f                      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:def5678a                      | &amp;lt;--------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:latest                        |      |
&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;                                                       podman pull                      |
&lt;&#x2F;span&gt;&lt;span&gt;                                                            |                           |
&lt;&#x2F;span&gt;&lt;span&gt;                                                            v                           |
&lt;&#x2F;span&gt;&lt;span&gt;+--------------+    pings every 5 min     +--------------------------------------+      |
&lt;&#x2F;span&gt;&lt;span&gt;|              | ----------------------&amp;gt;  |          DigitalOcean VPS            |      |
&lt;&#x2F;span&gt;&lt;span&gt;|  UptimeRobot |                          |                                      | &amp;lt;----+
&lt;&#x2F;span&gt;&lt;span&gt;|              |  &amp;lt;-- site unreachable    |  +--------+    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;|  alerts via  |                          |  | Caddy  |    | Nginx container  |  |
&lt;&#x2F;span&gt;&lt;span&gt;|  email&#x2F;SMS   |                          |  | :443   +---&amp;gt;| :8080            |  |
&lt;&#x2F;span&gt;&lt;span&gt;+--------------+                          |  |        |    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  | TLS    |    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  | HTTPS  +---&amp;gt;| Nginx container  |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |        |    | :8081            |  |
&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;                                            HTTPS :443
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +------+-------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |   Visitor    |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |   Browser    |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +--------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you learned something, please &lt;em&gt;like, share and subscribe&lt;&#x2F;em&gt;. Here are some resources to deepen your understanding:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;devops&#x2F;comments&#x2F;1p8vyxi&#x2F;zero_downtime_deployments_without_kubernetes&#x2F;&quot;&gt;Zero downtime deploymets without K8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.podman.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;What is Podman&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;&quot;&gt;GitLab CI&#x2F;CD documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=yxNpIL2MqEY&quot;&gt;We use containers now. Here is why&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;certbot.eff.org&#x2F;&quot;&gt;Certbot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;&quot;&gt;Caddy documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=w_lLt4lLplE&quot;&gt;The intro to Docker I wish I had when I started&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;resources&#x2F;what-is-container-registry&#x2F;&quot;&gt;Container registries 101&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;how-it-works&#x2F;&quot;&gt;Let&#x27;s encrypt how it works&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=W3EoZpCr1O8&quot;&gt;Playing with Caddy server&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;status.gitlab.com&#x2F;&quot;&gt;Gitlab system status&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Vectors</title>
        <published>2026-02-26T00:00:00+00:00</published>
        <updated>2026-02-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/vctrs/"/>
        <id>https://nskm.xyz/posts/vctrs/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/vctrs/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;vectors.png&quot; alt=&quot;vectors&quot; title=&quot;vectors&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Opinions&lt;&#x2F;strong&gt;: The views expressed here are my own unless otherwise specified. They do not represent any employer, organization, or affiliated group.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code examples&lt;&#x2F;strong&gt;: All code examples are educational. Production use requires careful consideration of performance, security, and your specific data characteristics.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model choice&lt;&#x2F;strong&gt;: The &lt;code&gt;all-MiniLM-L6-v2&lt;&#x2F;code&gt; model is a practical default, but embedding model selection should depend on your domain. Consider fine-tuning for specialized use cases.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;This article is for&lt;&#x2F;strong&gt;: Django developers curious about semantic search and vector embeddings, or anyone wanting to understand how vectors fit alongside traditional structured data.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;**This article was written on a Framework laptop 16, &lt;em&gt;yeah&lt;&#x2F;em&gt;!
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;When I start a new &lt;a href=&quot;#&quot;&gt;Django&lt;&#x2F;a&gt; project, the instinct is immediate and familiar: open &lt;code&gt;models.py&lt;&#x2F;code&gt; and start writing &lt;a href=&quot;#&quot;&gt;classes&lt;&#x2F;a&gt;. I think about my entity, its attributes, its relationships, and I translate that mental model almost directly into Python. That&#x27;s great. It works. Since so many years. It&#x27;s readable. It&#x27;s what Django was built for. Amazing. Perfect. Flawless.&lt;&#x2F;p&gt;
&lt;p&gt;If you follow my amazing and colossal work, you know that since more that two years now, I&#x27;m working on a project in the public health sector. I&#x27;m handling lots and lots and lots of data. I have to answer interesting questions like... Yet, I&#x27;m still reprensenting my data using classes and attributes. Reflexes.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s another way to represent data that&#x27;s been quietly powering search engines, recommendation systems, and AI applications for years, it&#x27;s increasingly accessible to application developers like me. I should learn to use it more often. Instead of describing data as a collection of named attributes, I can describe it as a &lt;strong&gt;point in a high-dimensional space&lt;&#x2F;strong&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Vector_(mathematics_and_physics)&quot;&gt;vector&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This article walks through what that actually means, when it matters, and how to implement both approaches side by side in a real Django project. To increase your chances of understanding, it is recommended that you listen to this &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=amBBO4PqJKo&quot;&gt;track&lt;&#x2F;a&gt; while reading the article. Enjoy!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#classical-approach&quot;&gt;The classical approach&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#vector-approach&quot;&gt;The vector approach&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#why-not-ai&quot;&gt;Why this is not just for AI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#both-approaches&quot;&gt;Both approaches in Django&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#going-further&quot;&gt;Going further&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#broader-landscape&quot;&gt;Representation models&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#how-to-practice&quot;&gt;How to practice&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;classical-approach&quot;&gt;The classical approach: data as structure&lt;&#x2F;h2&gt;
&lt;p&gt;When you model a medical facility in a &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;surveillance platform&lt;&#x2F;a&gt;, you probably write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;HealthFacility(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    region = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    facility_type = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# hospital, clinic, health_post
&lt;&#x2F;span&gt;&lt;span&gt;    capacity = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    services = models.ManyToManyField(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Service&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is &lt;strong&gt;structured representation&lt;&#x2F;strong&gt;. Data lives in named slots. Querying it means matching those slots exactly:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Find clinics in Dakar with pediatric services
&lt;&#x2F;span&gt;&lt;span&gt;HealthFacility.objects.filter(
&lt;&#x2F;span&gt;&lt;span&gt;    region=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Dakar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    facility_type=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clinic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    services__name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pediatrics&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is powerful for what it is. You know exactly what you&#x27;re looking for, the schema enforces consistency, and &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;&quot;&gt;SQL&lt;&#x2F;a&gt; is extraordinarily good at these kinds of exact, predicate-based lookups.&lt;&#x2F;p&gt;
&lt;p&gt;The limitation reveals itself the moment your questions become fuzzy. What if you want facilities that are &lt;em&gt;similar&lt;&#x2F;em&gt; to a given one — without being able to define exactly what &quot;similar&quot; means? What if a user types &quot;district hospital with maternal care near the coast&quot; and you need to find the best match? Predicate-based filtering breaks down because similarity isn&#x27;t a predicate. It&#x27;s a geometry problem.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;vector-approach&quot;&gt;The vector approach: data as position&lt;&#x2F;h2&gt;
&lt;p&gt;A vector is simply an ordered list of numbers:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[0.82, 0.14, 0.67, 0.03, 0.91, ...]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea is that you can encode the &lt;em&gt;meaning&lt;&#x2F;em&gt; or &lt;em&gt;characteristics&lt;&#x2F;em&gt; of any piece of data as a point in a high-dimensional space, such that &lt;strong&gt;things which are semantically similar end up close together&lt;&#x2F;strong&gt;, and things that are different end up far apart.&lt;&#x2F;p&gt;
&lt;p&gt;This is not hand-crafted feature engineering &lt;em&gt;(though it can be)&lt;&#x2F;em&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;spaces&#x2F;mteb&#x2F;leaderboard&quot;&gt;Modern embedding models&lt;&#x2F;a&gt; — neural networks trained on massive datasets — can take a sentence, a document, even an image, and produce a dense vector that captures its semantic content. The model has learned, from context, what concepts relate to each other. &quot;Maternal health clinic&quot; and &quot;obstetric care center&quot; will produce vectors that are very close. &quot;Warehouse&quot; will be far away.&lt;&#x2F;p&gt;
&lt;p&gt;The distance between two vectors is typically measured with &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cosine_similarity&quot;&gt;cosine similarity&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;similarity = cos(θ) = (A · B) &#x2F; (||A|| × ||B||)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A value of 1 means identical direction &lt;em&gt;(semantically equivalent)&lt;&#x2F;em&gt;. A value of 0 means orthogonal &lt;em&gt;(unrelated)&lt;&#x2F;em&gt;. This single number replaces the entire predicate matching logic.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;why-not-ai&quot;&gt;Why this is not just for AI projects&lt;&#x2F;h2&gt;
&lt;p&gt;You might think: &quot;I don&#x27;t need semantic search. I need to store patient records.&quot; That&#x27;s fair. This is exactly how I&#x27;ve done it on the &lt;a href=&quot;https:&#x2F;&#x2F;rh.pasteur.sn&#x2F;en&#x2F;research-and-public-health&#x2F;epidemiology-clinical-research-and-data-science&#x2F;fever-surveillance-syndromic-sentinel-surveillance-senegal-4s-network&quot;&gt;4S project&lt;&#x2F;a&gt;. But I&#x27;m more and more facing these new types of scenarios:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Duplicate detection.&lt;&#x2F;strong&gt; Two users register &quot;Hôpital Principal de Dakar&quot; and &quot;hopital principal dakar&quot;. Exact matching fails. Vector similarity catches them as near-duplicates.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation.&lt;&#x2F;strong&gt; &quot;Users who viewed this report also found these relevant.&quot; You don&#x27;t need a collaborative filtering setup — you can just find the reports whose vectors are closest to the one currently being read.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Free-text search that actually works.&lt;&#x2F;strong&gt; Users don&#x27;t search with your field names. They type natural language. Vectors let you match that intent.... &lt;em&gt;This one stung me very badly recently.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Clustering without labels.&lt;&#x2F;strong&gt; You have 10,000 epidemiological case reports. You want to discover natural groupings without writing filtering rules. Find neighborhoods in vector space.... We are working in this particular topic. I look at how we are implementing this feature and I am already disgusted by the direction we are taking. &lt;em&gt;Marvelous&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anomaly detection.&lt;&#x2F;strong&gt; A new weekly report has a vector that is very far from all historical ones. Flag it for review.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;both-approaches&quot;&gt;Both approaches in Django: a concrete example&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s build a very small project that models epidemiological reports using both approaches. We&#x27;ll use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;current&#x2F;extend.html&quot;&gt;PostgreSQL extension&lt;&#x2F;a&gt;, so vectors live right next to our traditional Django models. No separate &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Vector_database&quot;&gt;vector databases&lt;&#x2F;a&gt;, no need for new infrastructure if you&#x27;re already on the amazing &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;Postgres&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;pip install django pgvector sentence-transformers psycopg2-binary  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# easy peasy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enable the extension in a Django migration:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;VectorExtension
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Migration(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;migrations.Migration&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    operations = [
&lt;&#x2F;span&gt;&lt;span&gt;        VectorExtension(),
&lt;&#x2F;span&gt;&lt;span&gt;    ]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-traditional-model&quot;&gt;The traditional model&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;models.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;VectorField
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;EpiReport(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Classical structured representation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Every piece of information lives in a named, typed field.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    region = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    disease = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    week = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    year = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    case_count = models.IntegerField(default=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    severity = models.CharField(
&lt;&#x2F;span&gt;&lt;span&gt;        max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        choices=[(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;low&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Low&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;moderate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Moderate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;high&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;High&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    summary = models.TextField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The vector representation lives alongside the structured one.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 384 dimensions is the output size of the model we&amp;#39;ll use.
&lt;&#x2F;span&gt;&lt;span&gt;    embedding = VectorField(dimensions=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;384&lt;&#x2F;span&gt;&lt;span&gt;, null=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;, blank=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&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:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        indexes = [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Traditional index for structured queries
&lt;&#x2F;span&gt;&lt;span&gt;            models.Index(fields=[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&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 style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__str__(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{self.title}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{self.region}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, W&lt;&#x2F;span&gt;&lt;span&gt;{self.week}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;{self.year}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;)&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that both representations coexist in the same table. This is intentional — we&#x27;re not replacing one with the other. We&#x27;re giving ourselves two different query interfaces into the same data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;generating-the-embedding&quot;&gt;Generating the embedding&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;embeddings.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;sentence_transformers &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;SentenceTransformer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# All-MiniLM-L6-v2 is small (80MB), fast, and produces 384-dim vectors.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# It runs on CPU without issue, which matters in resource-constrained environments.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# See here: https:&#x2F;&#x2F;huggingface.co&#x2F;sentence-transformers&#x2F;all-MiniLM-L6-v2
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_model = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &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:#569cd6;&quot;&gt;global &lt;&#x2F;span&gt;&lt;span&gt;_model
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;_model &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        _model = SentenceTransformer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;all-MiniLM-L6-v2&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;_model
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;embed_report(report: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;EpiReport&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; list[float]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Convert a report&amp;#39;s semantic content into a vector.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    The text we embed is a natural language description of the report,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    so the model can capture the meaning, not just the keywords.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    text = (
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{report.title}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Disease: &lt;&#x2F;span&gt;&lt;span&gt;{report.disease}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Region: &lt;&#x2F;span&gt;&lt;span&gt;{report.region}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Severity: &lt;&#x2F;span&gt;&lt;span&gt;{report.severity}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{report.summary}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;model.encode(text).tolist()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-two-query-styles-side-by-side&quot;&gt;The two query styles, side by side&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;queries.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;CosineDistance
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;EpiReport
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;embeddings &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &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:#608b4e;&quot;&gt;# ── Approach 1: Structured Query ────────────────────────────────────────────
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_high_severity_reports(region: str, disease: str, year: int):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Classical Django ORM query.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Fast, precise, requires you to know exactly what you want.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;EpiReport.objects.filter(
&lt;&#x2F;span&gt;&lt;span&gt;        region=region,
&lt;&#x2F;span&gt;&lt;span&gt;        disease=disease,
&lt;&#x2F;span&gt;&lt;span&gt;        year=year,
&lt;&#x2F;span&gt;&lt;span&gt;        severity=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;high&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ).order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-week&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:#608b4e;&quot;&gt;# ── Approach 2: Semantic Vector Query ───────────────────────────────────────
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;find_similar_reports(query: str, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Vector similarity search.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    The query is natural language. No schema knowledge required.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Returns the most semantically similar reports.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    query_vector = model.encode(query).tolist()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, query_vector))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;find_similar_to_report(report: EpiReport, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Given an existing report, find others that are semantically similar.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Useful for &amp;quot;related reports&amp;quot; features or duplicate detection.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .exclude(pk=report.pk)
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, report.embedding))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;wiring-it-into-views&quot;&gt;Wiring it into views&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.http &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;EpiReport
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;queries &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_high_severity_reports, find_similar_reports
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;structured_search(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Traditional form-based search.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    reports = get_high_severity_reports(
&lt;&#x2F;span&gt;&lt;span&gt;        region=request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        disease=request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        year=int(request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2024&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse({
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;approach&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;structured&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:#d69d85;&quot;&gt;&amp;quot;results&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: list(reports.values(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;severity&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;semantic_search(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Free-text semantic search.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    query = request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;q&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    reports = find_similar_reports(query, top_k=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse({
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;approach&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;vector&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:#d69d85;&quot;&gt;&amp;quot;query&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: query,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;results&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:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.title,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.region,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.disease,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;similarity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: round(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;- r.distance, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;),  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# convert distance to similarity
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;reports
&lt;&#x2F;span&gt;&lt;span&gt;        ]
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now try these two requests:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;GET &#x2F;search&#x2F;structured&#x2F;?region=Dakar&amp;amp;disease=cholera&amp;amp;year=2024
&lt;&#x2F;span&gt;&lt;span&gt;GET &#x2F;search&#x2F;semantic&#x2F;?q=waterborne disease outbreaks in coastal areas
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The structured search finds exactly what you specified. The semantic search finds what you &lt;em&gt;meant&lt;&#x2F;em&gt;, even if those exact words don&#x27;t appear anywhere in your data. The world is beautiful.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;when-to-use&quot;&gt;When to use which&lt;&#x2F;h2&gt;
&lt;p&gt;On top of my tiny experience, and as a software engineer who has never used this technique on &lt;em&gt;on production&lt;&#x2F;em&gt;, I would say the right answer for most systems is both. And pgvector makes that even more practical without adding infrastructure complexity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lean on structured queries&lt;&#x2F;strong&gt; when you need exactness: filtering by date range, counting cases, producing regulatory reports, joining across tables. SQL is unbeatable here.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lean on vector queries&lt;&#x2F;strong&gt; when you need semantic understanding: search boxes, recommendation engines, duplicate detection, anomaly flagging, clustering, or any time a user&#x27;s intent can&#x27;t be reduced to a dropdown value.&lt;&#x2F;p&gt;
&lt;p&gt;Even more interesting, &lt;strong&gt;hybrid search&lt;&#x2F;strong&gt;: use structured filters to narrow the candidate set, then rank the survivors by vector similarity:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;hybrid_search(region: str, query: str, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Filter structurally, then rank semantically.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    This is typically the most useful approach in production.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    query_vector = model.encode(query).tolist()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .filter(region=region)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# hard filter: only this region
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, query_vector))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going further&lt;&#x2F;h2&gt;
&lt;p&gt;Once you&#x27;ve internalized the two-lens model, here&#x27;s where to take it next:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-fine-tune-your-own-embedding-model-on-domain-data&quot;&gt;1. Fine-tune your own embedding model on domain data&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;all-MiniLM-L6-v2&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;&quot;&gt;model&lt;&#x2F;a&gt; was trained on general English text. It has no idea that &quot;paludisme&quot; and &quot;malaria&quot; are the same thing, or that &quot;cas suspects&quot; and &quot;suspected cases&quot; are equivalent in my context. Training a domain-specific embedding model on my own epidemiological corpus — even with a small dataset using contrastive learning — would make similarity search dramatically more meaningful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-retrieval-augmented-generation-rag-on-top-of-our-vector-store&quot;&gt;2. Retrieval-augmented generation (RAG) on top of our vector store&lt;&#x2F;h3&gt;
&lt;p&gt;Once we have a vector store of reports, we&#x27;re one step away from a system that can &lt;em&gt;answer questions&lt;&#x2F;em&gt; about your data in natural language. A user asks: &lt;em&gt;&quot;What were the major respiratory disease trends in Guinea-Bissau in 2023?&quot;&lt;&#x2F;em&gt; — our system retrieves the most relevant reports by vector similarity, then feeds them as context to an &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Large_language_model&quot;&gt;LLM&lt;&#x2F;a&gt; that synthesizes a coherent answer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-vectors-for-anomaly-detection-in-surveillance-data&quot;&gt;3. Vectors for anomaly detection in surveillance data&lt;&#x2F;h3&gt;
&lt;p&gt;Every week a new batch of case reports comes in. &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#engineers&quot;&gt;We&lt;&#x2F;a&gt; can embed each report and compare it to the historical distribution of vectors for that region and disease. A report that lands far from the cluster is a statistical anomaly, potentially a real &lt;a href=&quot;https:&#x2F;&#x2F;www.who.int&#x2F;activities&#x2F;epidemic-and-pandemic-monitoring&quot;&gt;outbreak signal&lt;&#x2F;a&gt;. This turns our vector store into a passive early-warning system without writing any explicit outbreak-detection rules.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-multimodal-embeddings&quot;&gt;4. Multimodal embeddings&lt;&#x2F;h3&gt;
&lt;p&gt;Text isn&#x27;t the only thing we can embed. We can embed laboratory results, genomic sequences, geographic coordinates combined with case counts, even scanned paper forms via vision models. The moment we have multiple modalities in the same vector space, we can do cross-modal search: &lt;em&gt;find reports whose geographic spread pattern resembles this map image.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;placeholder image for brain explosion&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-the-theory-underneath-why-vector-spaces-work&quot;&gt;5. The theory underneath: why vector spaces work&lt;&#x2F;h3&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;broader-landscape&quot;&gt;Representation models: other ways to represent data&lt;&#x2F;h2&gt;
&lt;p&gt;Structured attributes and vectors are two lenses. And there are other ways to represent data:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot;&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Representation&lt;&#x2F;th&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Best question it answers&lt;&#x2F;th&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Tools&lt;&#x2F;th&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Class + attributes&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What does this thing have?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Django ORM, PostgreSQL&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Vector&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What is this thing like?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;pgvector, sentence-transformers&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Graph&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How does this thing connect?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Neo4j, networkx&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Event stream&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How did this thing become what it is?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Kafka, EventStoreDB&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Logic &#x2F; facts&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What can we conclude about this thing?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Prolog, Datalog, RDF&#x2F;OWL&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Probability&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How certain are we about this thing?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;PyMC, Stan&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Spatial&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Where is this thing, relative to what?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;PostGIS, GeoDjango&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Tensor&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How does this vary across multiple dimensions?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;NumPy, PyTorch, Xarray&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;how-to-practice&quot;&gt;How to practice&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need production data to start experimenting with vectors and embeddings:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Local development:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.trychroma.com&#x2F;&quot;&gt;Chroma&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Lightweight vector database that runs locally or in Docker.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector in Docker&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A local PostgreSQL with pgvector extension in seconds.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;docs&#x2F;pretrained_models.html&quot;&gt;Sentence Transformers Models&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Experiment with domain-specific models beyond all-MiniLM-L6-v2.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Learning resources:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;models&quot;&gt;Hugging Face Hub&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: 100k+ pre-trained models. Read papers, compare benchmark results.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;learn&quot;&gt;Embedding Models Course&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Free, practical introduction to embeddings.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector Documentation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: All indexing strategies and similarity operators explained.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;As a Django engineer, my mental model of &quot;data as class with attributes&quot; is solid and won&#x27;t stop serving &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;images&#x2F;Nsukami_Patrick.pdf&quot;&gt;me&lt;&#x2F;a&gt;. But it&#x27;s worth internalizing that it&#x27;s one of at least two valid representations. I should definitely start to think of my data as having a &lt;em&gt;position&lt;&#x2F;em&gt; in semantic space, a whole class of problems (search, similarity, anomaly, clustering) will become natural rather than bespoke.&lt;&#x2F;p&gt;
&lt;p&gt;Here we are, we wanted a banana but we received a gorilla holding the banana and the entire jungle. Here are some links to help you &lt;em&gt;(and me, let&#x27;s be honest)&lt;&#x2F;em&gt; go further and tame the beast:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;dev_kiran&#x2F;embeddings-the-hidden-power-behind-ai-search-21eb&quot;&gt;The hidden power behind AI &amp;amp; search&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;docs&#x2F;training&#x2F;overview.html&quot;&gt;Fine-tuning sentence transformers&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;vickiboykis.com&#x2F;what_are_embeddings&#x2F;&quot;&gt;Vector database comparison&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lilianweng.github.io&#x2F;posts&#x2F;2021-05-31-contrastive&#x2F;&quot;&gt;Contrastive learning explained&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2005.11401&quot;&gt;Retrieval-Augmented Generation (RAG)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector#performance&quot;&gt;pgvector performance tuning&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;~EWD&#x2F;transcriptions&#x2F;EWD06xx&#x2F;EWD667.html&quot;&gt;On the foolishness of &quot;natural language programming&quot;&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you found this article useful, &lt;em&gt;please like, share and subscribe&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;while-i-still-have-your-attention&quot;&gt;While I still have your attention&lt;&#x2F;h2&gt;
&lt;p&gt;The Norwegian Consumer Council is an independent, governmentally funded organisation that advocates for consumer’s rights. It should be easy for consumers to make sustainable choices every day. Consumers have the right to be protected against exploitation – both financially and digitally. To ensure this, we work to provide easy access to information, enforceable rights, and sufficient redress options when something goes wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Digital products and services keep getting worse. In the new report Breaking Free: Pathways to a fair technological future, the Norwegian Consumer Council has delved into &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=T4Upf_B9RLQ&quot;&gt;enshittification&lt;&#x2F;a&gt; and how to resist it. The report shows how this phenomenon affects both consumers and society at large, but that it is possible to &lt;a href=&quot;https:&#x2F;&#x2F;www.forbrukerradet.no&#x2F;breakingfree&quot;&gt;turn the tide.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Geez&lt;&#x2F;em&gt;, I would have loved to see African leaders do the same....&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Recap)</title>
        <published>2026-02-12T00:00:00+00:00</published>
        <updated>2026-02-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-recap/"/>
        <id>https://nskm.xyz/posts/aws-recap/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-recap/">&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;proud_of_you.gif&quot; alt=&quot;Proud of myself&quot; title=&quot;Proud of myself&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers:&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Structural truth about intensive training formats: you can cover a lot of ground in a week, but covering ground is not the same as owning it. There is a fundamental difference between &lt;em&gt;understanding&lt;&#x2F;em&gt; the concepts and &lt;em&gt;having debugged a deployment issue at 11pm before a production deployment&lt;&#x2F;em&gt;. The gap between &quot;I understand this&quot; and &quot;I can do this under pressure&quot; is filled only by practice — and eight days of excellent training doesn&#x27;t close it.&lt;&#x2F;p&gt;
&lt;p&gt;10 days of training, a lot of diagrams drawn on whiteboards, 5 instructors who clearly knew their material. I would like to thank them very much; I have learnt a great deal thanks to them.&lt;&#x2F;p&gt;
&lt;p&gt;With this article, I would like to take a step back to look at what we built, what was, &lt;em&gt;imho&lt;&#x2F;em&gt;, missing and what is the next step.... &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=75wmW7xjyog&quot;&gt;Music&lt;&#x2F;a&gt; please!&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#the-platform-we-built&quot;&gt;The platform we built&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#why-in-this-order&quot;&gt;Why in this order&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#day-7-the-piece-thats-missing&quot;&gt;Ansible: the piece that&#x27;s missing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#what-we-didnt-cover&quot;&gt;What we didn&#x27;t cover&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#where-to-go-from-here&quot;&gt;Where to go from here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-platform-we-built&quot;&gt;The platform we built&lt;&#x2F;h2&gt;
&lt;p&gt;This 10 days training series actually produced a concrete thing: how to build Django REST APIs handling patient analyses and clinical consultation data, running on a K8s cluster on AWS, secured at every layer, deployable in any environment in minutes, and fully observable.&lt;&#x2F;p&gt;
&lt;p&gt;Here is what that means in practice:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;private VPC&lt;&#x2F;strong&gt; in a region with public subnets for load balancers and private subnets for everything else&lt;&#x2F;li&gt;
&lt;li&gt;An &lt;strong&gt;EKS cluster&lt;&#x2F;strong&gt; provisioned with managed node groups, with etcd encrypted at rest using a KMS key&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;IAM roles&lt;&#x2F;strong&gt; for every component that needs AWS access, &lt;strong&gt;IRSA or EKS Pod Identity&lt;&#x2F;strong&gt; for pods&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC&lt;&#x2F;strong&gt; scoped to namespaces: the genomics team can only touch the genomics namespace, the clinical trials team theirs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Network policies&lt;&#x2F;strong&gt; enforcing zero-trust between pods: no pod talks to another unless explicitly allowed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt; stored in AWS Secrets Manager, synced into Kubernetes at runtime by the External Secrets Operator&lt;&#x2F;li&gt;
&lt;li&gt;The entire infrastructure &lt;strong&gt;provisioned by Terraform&lt;&#x2F;strong&gt; — reproducible in any environment&lt;&#x2F;li&gt;
&lt;li&gt;The Django Rest APIs &lt;strong&gt;packaged as a Helm charts&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The charts stored in &lt;strong&gt;ECR alongside the Docker images&lt;&#x2F;strong&gt;, accessible to any teammate with the right IAM permissions&lt;&#x2F;li&gt;
&lt;li&gt;Platform &lt;strong&gt;instrumented with OpenTelemetry&lt;&#x2F;strong&gt;: metrics sent to &lt;strong&gt;Prometheus&lt;&#x2F;strong&gt;, logs to &lt;strong&gt;Loki&lt;&#x2F;strong&gt;, traces to &lt;strong&gt;Jaeger&lt;&#x2F;strong&gt;, all visualised in &lt;strong&gt;Grafana&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;SLOs&lt;&#x2F;strong&gt; defined for the Rest APIs, with Alertmanager firing when the error budget burns too fast&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-in-this-order&quot;&gt;What we built, why in this order&lt;&#x2F;h2&gt;
&lt;p&gt;Layers on layers on layers. Each layer depended on the one before it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Foundations&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — VPC, compute, storage, regions. Before anything else, you need to understand the environment your workloads will run in. Network topology is a first-class architectural decision.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;Identity and access&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — IAM, OIDC, KMS, CloudTrail. IAM roles and encryption are established &lt;em&gt;before&lt;&#x2F;em&gt; the cluster exists, because the cluster will inherit them from day one. It&#x27;s difficult to retroactively secure a system that was built without security in mind.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Orchestration&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Kubernetes, EKS, pods, deployments, services. To run workloads at scale, self-heal them, and expose them, without managing individual servers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Workload security&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — RBAC, network policies, pod security, secrets management. You have a running cluster. Now lock down what runs inside it. The defaults are permissive by design; the hardening is your responsibility.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Automation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Terraform, Helm. You have built &amp;amp; secured a cluster you understand. Now make it reproducible. The goal is to never click through the console again — for infrastructure or for deployments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;&quot;&gt;Observability&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Prometheus, Loki, Jaeger, OpenTelemetry, SLOs. The platform runs, is secured, and is automated. Now make it visible. You cannot maintain what you cannot see.&lt;&#x2F;p&gt;
&lt;p&gt;Mental model: &lt;strong&gt;build → orchestrate → secure → automate → observe&lt;&#x2F;strong&gt;. Each verb assumes the previous one is done. You cannot automate what you have not secured. And you do not observe what you have not deployed. &lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-7-the-piece-thats-missing&quot;&gt;Ansible: the piece that&#x27;s missing&lt;&#x2F;h2&gt;
&lt;p&gt;Somewhere during the training, we covered &lt;strong&gt;Ansible&lt;&#x2F;strong&gt;. I chose to not talk about it as part of this series.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, Ansible is useful and complementary to Terraform, Helm &amp;amp; Kubernetes, but not strictly essential. If you are using fully managed Kubernetes services (like AWS EKS or GKE) where the cloud provider manages the underlying node configuration, the need for Ansible is reduced.&lt;&#x2F;p&gt;
&lt;p&gt;On Kubernetes, the configuration management layer is largely handled by Helm values, ConfigMaps, and Secrets. Ansible&#x27;s strengths shine on EC2 instances, bastion hosts, and hybrid environments — which were not the primary focus of this training.&lt;&#x2F;p&gt;
&lt;p&gt;In all the cases, I&#x27;m not saying Ansible is worthless, it is absolutely worth learning. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;&quot;&gt;official documentation&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;www.ansiblefordevops.com&#x2F;&quot;&gt;Ansible for DevOps book&lt;&#x2F;a&gt; by Jeff Geerling are the right starting points.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-we-didnt-cover&quot;&gt;What we didn&#x27;t cover&lt;&#x2F;h2&gt;
&lt;p&gt;While I agree the instructors gave the best they could, while I agree we cannot cover everything in 10 days, the following topics are the ones I wish were addressed:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CI&#x2F;CD pipelines&lt;&#x2F;strong&gt; — how does a git push become a Docker image in ECR and a Helm upgrade on the cluster? I know 1 or 2 things about this topic but I wish the instructors had said a few words about that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;GitOps&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;argoproj.github.io&#x2F;cd&#x2F;&quot;&gt;ArgoCD&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;&quot;&gt;Flux&lt;&#x2F;a&gt; take Helm one step further: Git becomes the single source of truth, and the cluster continuously reconciles itself against what&#x27;s in the repository. This is how most mature platform teams deploy today.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Service mesh&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;&quot;&gt;Istio&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;linkerd.io&#x2F;&quot;&gt;Linkerd&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;cilium.io&#x2F;&quot;&gt;Cilium&lt;&#x2F;a&gt; add mTLS between services, fine-grained traffic management, and advanced observability at the network layer. Once your platform has dozens of services, a service mesh stops being optional.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Backup and restore&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;velero.io&#x2F;&quot;&gt;Velero&lt;&#x2F;a&gt; backs up Kubernetes resources and persistent volumes. What happens when someone deletes the wrong namespace in production?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Multi-region and disaster recovery&lt;&#x2F;strong&gt; — what happens when &lt;code&gt;eu-west-3&lt;&#x2F;code&gt; has an incident? For a platform handling patient data, this is a compliance question as much as a technical one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Image scanning in CI&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;snyk.io&#x2F;&quot;&gt;Snyk&lt;&#x2F;a&gt; scan Docker images for known vulnerabilities before they ever reach the cluster. Security in the build pipeline, not just at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here&lt;&#x2F;h2&gt;
&lt;p&gt;Then, explore &lt;strong&gt;ArgoCD&lt;&#x2F;strong&gt;. Point it at an Helm chart repository in ECR, and let it manage deployments declaratively. That&#x27;s the missing link between Day 6 and a production-grade deployment workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, set up the observability stack from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;&quot;&gt;Day 8&lt;&#x2F;a&gt; and use it to actually find out why&#x2F;when something broke. Today, I&#x27;ll be honest, if something break, The only thing I have to help me sort this out are the &lt;a href=&quot;https:&#x2F;&#x2F;i.programmerhumor.io&#x2F;2025&#x2F;11&#x2F;6d58f6fc8886c2da6ee0215f5a2e00207595c36ef43031d9e9ec33741120dcc3.jpg&quot;&gt;logs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;writing.gif&quot; alt=&quot;Planning the next step&quot; title=&quot;Planning the next step&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Ten days of excellent content, delivered by people who clearly knew what they were talking about, thanks a million to them. I know the vocabulary, I still need to pratice, a lot, to own the skills. Writing these articles was the first step in that direction. Now &lt;em&gt;I need a credit card.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;You know the drill.... see ya o&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CI&#x2F;CD and GitOps:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;actions&quot;&gt;GitHub Actions documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;argo-cd.readthedocs.io&#x2F;&quot;&gt;ArgoCD documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;docs&#x2F;&quot;&gt;Flux documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MeU5_k9ssrs&quot;&gt;GitOps with ArgoCD — tutorial&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Service mesh:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;latest&#x2F;docs&#x2F;&quot;&gt;Istio documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;linkerd.io&#x2F;docs&#x2F;&quot;&gt;Linkerd documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.cilium.io&#x2F;&quot;&gt;Cilium documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Cost and autoscaling:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kubecost.com&#x2F;&quot;&gt;Kubecost&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;karpenter.sh&#x2F;docs&#x2F;&quot;&gt;Karpenter documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Backup and resilience:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;velero.io&#x2F;docs&#x2F;&quot;&gt;Velero documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Going deeper on what was covered:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; — the authoritative reference for everything in Days 4 and 5&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;table-of-contents&#x2F;&quot;&gt;Google SRE book&lt;&#x2F;a&gt; — the canonical text behind the SLI&#x2F;SLO&#x2F;SLA framework from Day 8&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ansiblefordevops.com&#x2F;&quot;&gt;Ansible for DevOps&lt;&#x2F;a&gt; — Jeff Geerling&#x27;s book, the right starting point for Day 7&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terraformbook.com&#x2F;&quot;&gt;The Terraform Book&lt;&#x2F;a&gt; — for going deeper on Day 6&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;modern_infrastructure.webp&quot; alt=&quot;Modern infrastructure&quot; title=&quot;Modern infrastructure&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 8)</title>
        <published>2026-02-11T00:00:00+00:00</published>
        <updated>2026-02-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-8/"/>
        <id>https://nskm.xyz/posts/aws-8/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-8/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;observability2.gif&quot; alt=&quot;Me, observing&quot; title=&quot;Me observing&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;. The examples are intentionally simplified for clarity. All tools featured here are free and open-source software — they run identically on EKS, GKE, bare metal, or your laptop.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A special thank you to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&#x2F;&quot;&gt;Mame Astou&lt;&#x2F;a&gt; aka &quot;Madame La Directrice&quot; for taking the time to review this article.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;The genomics API is running. &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Terraform provisioned the cluster&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#helm-kubernetes-package-manager&quot;&gt;Helm deployed the application&lt;&#x2F;a&gt;. From the outside, everything looks fine.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Then, a researcher reports that their variant analysis job submitted two hours ago still hasn&#x27;t returned results. You check Kubernetes: the pods are running. You check the load balancer: it&#x27;s healthy. The deployment logs show no errors. But &lt;em&gt;something&lt;&#x2F;em&gt; is wrong, and you have absolutely no idea where to start looking.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the moment you realise your system is &lt;strong&gt;blind&lt;&#x2F;strong&gt;. You built the infrastructure. You secured it. You automated its deployment. And then you flew it into production with no instruments.&lt;&#x2F;p&gt;
&lt;p&gt;This article is about fixing that. Not by adding monitoring as an afterthought, but by building the kind of visibility that lets you answer three questions before your users even notice a problem: &lt;strong&gt;what is happening, why is it happening, and where exactly is it happening?&lt;&#x2F;strong&gt; No worries, I&#x27;m not there yet. Lord knows how much 4s misses observability &amp;amp; monitoring :\&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#observability-vs-monitoring&quot;&gt;Observability vs monitoring&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#the-four-pillars&quot;&gt;The four pillars&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#the-tooling-landscape&quot;&gt;The tooling landscape&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#opentelemetry-the-collection-standard&quot;&gt;OpenTelemetry: the collection standard&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#sli-slo-sla-from-data-to-accountability&quot;&gt;SLI, SLO, SLA: from data to accountability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observability-vs-monitoring&quot;&gt;Observability vs monitoring&lt;&#x2F;h2&gt;
&lt;p&gt;These two words are often used interchangeably. They shouldn&#x27;t be.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Monitoring&lt;&#x2F;strong&gt; is about watching &lt;em&gt;known&lt;&#x2F;em&gt; failure modes. You define thresholds — CPU above 80%, error rate above 1% — and you alert when they&#x27;re crossed. It answers the question: &lt;em&gt;&quot;is this thing I already know about happening?&quot;&lt;&#x2F;em&gt; Monitoring is reactive: you first have to know what can go wrong before you can monitor for it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Observability&lt;&#x2F;strong&gt; is about understanding &lt;em&gt;unknown&lt;&#x2F;em&gt; failure modes from the outside. A system is observable if you can ask arbitrary questions about its internal state — without having predicted those questions in advance. It answers: &lt;em&gt;&quot;why is this behaving the way it is?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In practice, you need both. Monitoring te dit &quot;quelque chose est cassé&quot;. Observability te permet de répondre à &quot;pourquoi est-ce cassé, exactement, pour qui, depuis quand, et dans quel contexte&quot; — même pour des pannes que tu n&#x27;avais pas anticipées.&lt;&#x2F;p&gt;
&lt;p&gt;In a K8s cluster, failures are often not the ones you predicted. A genomic analysis pipeline stalls not because of high CPU, but because a database connection pool is exhausted by a single slow query in one namespace — and your monitoring threshold was on the wrong metric entirely. Observability gives you the tools to discover that. Monitoring alone doesn&#x27;t.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;observability_diagram.svg&quot; alt=&quot;observability&quot; title=&quot;observability&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;monitoring_diagram.svg&quot; alt=&quot;monitoring&quot; title=&quot;monitoring&quot;&#x2F;&gt;  
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-four-pillars&quot;&gt;The four pillars&lt;&#x2F;h2&gt;
&lt;p&gt;Cloud-native observability is built on four pillars. Together, they give you a complete picture of a running system.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;logs-what-happened&quot;&gt;Logs — what happened&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;logs&#x2F;&quot;&gt;Logs&lt;&#x2F;a&gt; are timestamped records of discrete events: a request came in, a query failed, a job completed. They are the most familiar signal and the easiest to produce — every Django app already writes logs.&lt;&#x2F;p&gt;
&lt;p&gt;On Kubernetes, logs have a structural challenge: pods are ephemeral. When a pod crashes and restarts, its logs disappear. You need a &lt;strong&gt;log aggregation layer&lt;&#x2F;strong&gt; that collects logs from all pods, across all nodes, and stores them centrally before they vanish.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;What exactly happened at 14:32:07 in the genomics namespace?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;metrics-how-much&quot;&gt;Metrics — how much&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;metrics&#x2F;&quot;&gt;Metrics&lt;&#x2F;a&gt; are numeric measurements sampled over time: request rate, error rate, latency percentiles, CPU usage, memory consumption, active database connections. They are cheap to store, fast to query, and ideal for alerting and dashboards.&lt;&#x2F;p&gt;
&lt;p&gt;Metrics don&#x27;t tell you &lt;em&gt;why&lt;&#x2F;em&gt; something is slow — but they tell you &lt;em&gt;that&lt;&#x2F;em&gt; it is slow and &lt;em&gt;when&lt;&#x2F;em&gt; it started.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;How many analysis requests failed in the last hour, and is that number growing?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;traces-the-full-journey&quot;&gt;Traces — the full journey&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;traces&#x2F;&quot;&gt;trace&lt;&#x2F;a&gt; follows a single request through every service it touches. In a microservices or multi-component architecture, a single API call might touch a Django view, a Celery task, a PostgreSQL query, and an S3 upload. A trace connects all of these into a single timeline, with durations for each step.&lt;&#x2F;p&gt;
&lt;p&gt;Traces are the pillar that answers the question logs and metrics can&#x27;t: &lt;em&gt;&quot;the request was slow — but which part of it was slow?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;The variant analysis request took 4.2 seconds — 3.8 seconds of which was a single database query in the pipeline.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kubernetes-events-what-the-cluster-decided&quot;&gt;Kubernetes events — what the cluster decided&lt;&#x2F;h3&gt;
&lt;p&gt;Kubernetes &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;kubernetes-api&#x2F;cluster-resources&#x2F;event-v1&#x2F;&quot;&gt;emits events&lt;&#x2F;a&gt; for everything it does: pod scheduled, pod evicted, image pull failed, node pressure detected, HPA scaled up. These events are not logs (they come from the control plane, not the application) and not metrics (they are discrete, not continuous). They are a fourth pillar that explains &lt;em&gt;cluster-level&lt;&#x2F;em&gt; behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;The pod restarted three times because the node ran out of memory — not because the application crashed.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tooling-landscape&quot;&gt;The tooling landscape&lt;&#x2F;h2&gt;
&lt;p&gt;Two paths exist for implementing this stack on Kubernetes.&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Signal&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS-native&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Open source&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Logs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Logs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Loki + Promtail&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Metrics&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Metrics&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prometheus + node-exporter&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Traces&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS X-Ray&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Jaeger&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Visualisation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Dashboards&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Grafana&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Instrumentation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS Distro for OpenTelemetry&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;OpenTelemetry&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Alerting&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Alarms&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prometheus Alertmanager&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;We are going with the &lt;strong&gt;open-source stack&lt;&#x2F;strong&gt;. These tools run identically on EKS, GKE, bare metal, or your laptop. They have no vendor lock-in, no per-metric pricing, and a massive community behind each of them. If the genomics platform ever moves off AWS, the observability layer moves with it unchanged.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-the-pieces-fit-together&quot;&gt;How the pieces fit together&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Django app
&lt;&#x2F;span&gt;&lt;span&gt;  └─ OTel SDK (auto-instrumentation)
&lt;&#x2F;span&gt;&lt;span&gt;       └─ OTel Collector
&lt;&#x2F;span&gt;&lt;span&gt;            ├─ metrics ──→ Prometheus ──→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;            ├─ logs ─────→ Loki ─────────→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;            └─ traces ───→ Jaeger ────────→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;                                    Alertmanager ──→ PagerDuty &#x2F; Slack
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A single &lt;strong&gt;OTel Collector&lt;&#x2F;strong&gt; acts as the central routing layer — your application sends all three signal types to one endpoint, and the collector fans them out to the right backends. Grafana sits on top of all three, giving you a unified view. This architecture means your application code only knows about one destination: the collector.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deploying-the-stack-with-helm&quot;&gt;Deploying the stack with Helm&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;From Day 6&lt;&#x2F;a&gt;, you already know how to use Helm. The entire observability stack is available as Helm charts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;helm repo add prometheus-community https:&#x2F;&#x2F;prometheus-community.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add grafana https:&#x2F;&#x2F;grafana.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add jaegertracing https:&#x2F;&#x2F;jaegertracing.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add open-telemetry https:&#x2F;&#x2F;open-telemetry.github.io&#x2F;opentelemetry-helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo update
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Prometheus + Grafana + Alertmanager — all in one chart
&lt;&#x2F;span&gt;&lt;span&gt;helm install kube-prometheus-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  prometheus-community&#x2F;kube-prometheus-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Loki + Promtail (log collection from all pods)
&lt;&#x2F;span&gt;&lt;span&gt;helm install loki grafana&#x2F;loki-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --set promtail.enabled=true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Jaeger (distributed tracing backend)
&lt;&#x2F;span&gt;&lt;span&gt;helm install jaeger jaegertracing&#x2F;jaeger \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# OpenTelemetry Collector (the routing layer)
&lt;&#x2F;span&gt;&lt;span&gt;helm install otel-collector \
&lt;&#x2F;span&gt;&lt;span&gt;  open-telemetry&#x2F;opentelemetry-collector \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --values otel-collector-values.yaml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;opentelemetry-the-collection-standard&quot;&gt;OpenTelemetry: the collection standard&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; (OTel) is a CNCF project that provides a single, vendor-neutral standard for producing and collecting observability data. Before OTel, you needed separate SDKs for Prometheus, Jaeger, and your logging library — each with different APIs and configuration. OTel unifies them: one SDK, one wire protocol, one collector.&lt;&#x2F;p&gt;
&lt;p&gt;It has two parts: the &lt;strong&gt;SDK&lt;&#x2F;strong&gt; (what you add to your application to produce telemetry) and the &lt;strong&gt;Collector&lt;&#x2F;strong&gt; (the agent that receives, processes, and exports it).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-otel-collector-central-routing&quot;&gt;The OTel Collector: central routing&lt;&#x2F;h3&gt;
&lt;p&gt;The collector is configured as a pipeline: receivers → processors → exporters. Here is the configuration for our stack (&lt;code&gt;otel-collector-values.yaml&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocols&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;grpc&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;0.0.0.0:4317&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;0.0.0.0:4318&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;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;: {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limit_mib&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;512
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;prometheus&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0.0.0.0:8889&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;loki&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;http:&#x2F;&#x2F;loki:3100&#x2F;loki&#x2F;api&#x2F;v1&#x2F;push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;jaeger&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;jaeger-collector:14250&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tls&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;insecure&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pipelines&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metrics&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prometheus&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;logs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;loki&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;traces&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;jaeger&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Three pipelines, three backends — your application only talks to port 4317.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;instrumenting-the-django-api&quot;&gt;Instrumenting the Django API&lt;&#x2F;h3&gt;
&lt;p&gt;The genomics API needs two things: a way to produce telemetry (the OTel SDK) and a way to expose metrics for Prometheus to scrape (the &lt;code&gt;django-prometheus&lt;&#x2F;code&gt; package).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Dependencies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;pip install \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-sdk \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-instrumentation-django \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-instrumentation-psycopg2 \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-exporter-otlp-proto-grpc \
&lt;&#x2F;span&gt;&lt;span&gt;  django-prometheus
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Auto-instrumentation setup&lt;&#x2F;strong&gt; — the right place to call this is &lt;code&gt;AppConfig.ready()&lt;&#x2F;code&gt; in your app&#x27;s &lt;code&gt;apps.py&lt;&#x2F;code&gt;, which runs exactly once on startup regardless of whether you&#x27;re using &lt;code&gt;manage.py&lt;&#x2F;code&gt;, a WSGI server, or an ASGI server:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;trace
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.sdk.trace &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;TracerProvider
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.sdk.trace.export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;BatchSpanProcessor
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.exporter.otlp.proto.grpc.trace_exporter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;OTLPSpanExporter
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.instrumentation.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;DjangoInstrumentor
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.instrumentation.psycopg2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Psycopg2Instrumentor
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;configure_tracing():
&lt;&#x2F;span&gt;&lt;span&gt;    provider = TracerProvider()
&lt;&#x2F;span&gt;&lt;span&gt;    exporter = OTLPSpanExporter(
&lt;&#x2F;span&gt;&lt;span&gt;        endpoint=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;otel-collector.monitoring:4317&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        insecure=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    provider.add_span_processor(BatchSpanProcessor(exporter))
&lt;&#x2F;span&gt;&lt;span&gt;    trace.set_tracer_provider(provider)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Auto-instrument Django HTTP requests and PostgreSQL queries
&lt;&#x2F;span&gt;&lt;span&gt;    DjangoInstrumentor().instrument()
&lt;&#x2F;span&gt;&lt;span&gt;    Psycopg2Instrumentor().instrument()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# yourapp&#x2F;apps.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.apps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;AppConfig
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;YourAppConfig(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;AppConfig&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;yourapp&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;ready(self):
&lt;&#x2F;span&gt;&lt;span&gt;        configure_tracing()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this in place, every HTTP request and every database query is automatically traced — no manual instrumentation needed for the infrastructure layer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Custom spans for business logic&lt;&#x2F;strong&gt; — the above covers HTTP and database calls automatically. For domain-specific visibility into your own code, add manual spans:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# analysis&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;trace
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;tracer = trace.get_tracer(__name__)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;run_variant_analysis(request, patient_id):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;tracer.start_as_current_span(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;variant-analysis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;span:
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;patient.id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, patient_id)
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;variant-calling&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        result = VariantCallingPipeline.run(patient_id)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.variants_found&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, result.variant_count)
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.duration_ms&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, result.duration_ms)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse(result.to_dict())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when an analysis is slow, the trace shows exactly where the time went: Django view setup, PostgreSQL query, pipeline execution, response serialisation — each as a separate span with its own duration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;exposing-metrics-for-prometheus&quot;&gt;Exposing metrics for Prometheus&lt;&#x2F;h3&gt;
&lt;p&gt;Add &lt;code&gt;django-prometheus&lt;&#x2F;code&gt; to &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt; and wire up the metrics endpoint:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# settings.py
&lt;&#x2F;span&gt;&lt;span&gt;INSTALLED_APPS = [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus&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;span&gt;MIDDLEWARE = [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.middleware.PrometheusBeforeMiddleware&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:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.middleware.PrometheusAfterMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# urls.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;path, include
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.urls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)),  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# exposes &#x2F;metrics
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then tell Prometheus to scrape it with a &lt;code&gt;ServiceMonitor&lt;&#x2F;code&gt; (from the &lt;code&gt;kube-prometheus-stack&lt;&#x2F;code&gt; CRDs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;monitoring.coreos.com&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceMonitor&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;monitoring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespaceSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchNames&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;metrics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;interval&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;30s&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Prometheus now automatically discovers and scrapes the genomics API every 30 seconds. No manual configuration when pods are rescheduled.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sli-slo-sla-from-data-to-accountability&quot;&gt;SLI, SLO, SLA: from data to accountability&lt;&#x2F;h2&gt;
&lt;p&gt;Collecting telemetry is pointless without defining what &lt;em&gt;good&lt;&#x2F;em&gt; looks like. &lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;&quot;&gt;SLI, SLO, and SLA&lt;&#x2F;a&gt; are the framework for turning raw observability data into meaningful commitments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#indicators-o8seIAcZ&quot;&gt;SLI (Service Level Indicator)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — a measurement. A specific, quantifiable signal that reflects the user experience:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;The percentage of analysis API requests that return in under 2 seconds.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#objectives-g0s1tdzt&quot;&gt;SLO (Service Level Objective)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the target you set for that indicator:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;99% of analysis requests should return in under 2 seconds, measured over a rolling 30-day window.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#agreements-ub9SGXig&quot;&gt;SLA (Service Level Agreement)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the formal commitment to external parties, with consequences:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;If availability drops below 99.5% in any calendar month, affected institutions receive a service credit.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The gap between your SLO (99%) and 100% is your &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;embracing-risk&#x2F;#id-n9ITyhxZ&quot;&gt;error budget&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the room you have to take risks, deploy changes, and absorb incidents without breaching your commitment. If you have a 1% error budget over 30 days, that&#x27;s about 7 hours of degraded service you can afford. Spend it wisely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;measuring-the-sli-in-prometheus&quot;&gt;Measuring the SLI in Prometheus&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api.sli&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;record&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;job:genomics_api_p99_latency_seconds&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;expr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      histogram_quantile(0.99,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_requests_latency_seconds_by_view_method_bucket{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          view=&amp;quot;run_variant_analysis&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[5m])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;alerting-when-the-error-budget-burns-too-fast&quot;&gt;Alerting when the error budget burns too fast&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api.slo&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alert&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;AnalysisAPIErrorBudgetBurn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;expr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      (
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_responses_total_by_status_view_method_total{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          status=~&amp;quot;5..&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[1h])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        &#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_responses_total_by_status_view_method_total{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[1h])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      ) &amp;gt; 0.01
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;5m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;severity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;warning&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;team&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-platform&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Genomics API error rate above SLO threshold&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;description&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        Error rate is {{ $value | humanizePercentage }}.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        At this rate, the monthly error budget will be exhausted in
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        {{ printf &amp;quot;%.1f&amp;quot; (div 0.01 $value | mul 720) }} hours.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This alert doesn&#x27;t just tell you &lt;em&gt;that&lt;&#x2F;em&gt; the error rate is high — it tells you how quickly you are burning through your error budget, so you can decide whether to roll back immediately or investigate first.&lt;&#x2F;p&gt;
&lt;p&gt;A good alerting rule alerts on &lt;strong&gt;user impact&lt;&#x2F;strong&gt;, not on infrastructure symptoms. &quot;Error budget burning at 10x&quot; is more actionable than &quot;CPU at 78%&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;A deployed system that you can&#x27;t observe is a system you don&#x27;t fully control. Logs tell you what happened. Metrics tell you how much and how often. Traces tell you where exactly things went wrong. Kubernetes events tell you what the cluster itself was doing. Together, they answer the question that every production incident eventually raises: &lt;em&gt;&quot;what on earth is going on in there?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The open-source stack — Prometheus, Grafana, Loki, Jaeger, OpenTelemetry — gives you all of this without vendor lock-in. It runs on EKS today, on bare metal tomorrow, on a laptop for local debugging when you need it. The investment in learning these tools pays dividends regardless of which cloud you&#x27;re on.&lt;&#x2F;p&gt;
&lt;p&gt;And SLI&#x2F;SLO&#x2F;SLA takes that data one step further: it turns raw signals into a shared language between the people who build the system and the people who depend on it. Error budgets make the trade-off between reliability and velocity explicit, instead of leaving it as a permanent source of tension.&lt;&#x2F;p&gt;
&lt;p&gt;The platform is now provisioned, secured, deployed, and observable. That&#x27;s a complete stack — and the knowledge to rebuild it anywhere.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;&quot;&gt;OpenTelemetry documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry-python.readthedocs.io&#x2F;&quot;&gt;OpenTelemetry Python SDK&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;introduction&#x2F;overview&#x2F;&quot;&gt;Prometheus documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;&quot;&gt;Grafana documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;loki&#x2F;latest&#x2F;&quot;&gt;Loki documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.jaegertracing.io&#x2F;docs&#x2F;&quot;&gt;Jaeger documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;alerting&#x2F;latest&#x2F;alertmanager&#x2F;&quot;&gt;Prometheus Alertmanager&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prometheus-community&#x2F;helm-charts&#x2F;tree&#x2F;main&#x2F;charts&#x2F;kube-prometheus-stack&quot;&gt;kube-prometheus-stack Helm chart&lt;&#x2F;a&gt; — Prometheus + Grafana + Alertmanager in one chart&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;korfuri&#x2F;django-prometheus&quot;&gt;django-prometheus&lt;&#x2F;a&gt; — Prometheus metrics for Django&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;opentelemetry-instrumentation-django&#x2F;&quot;&gt;opentelemetry-instrumentation-django&lt;&#x2F;a&gt; — auto-instrumentation for Django&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;&quot;&gt;Google SRE book — SLI&#x2F;SLO&#x2F;SLA chapter&lt;&#x2F;a&gt; — the canonical reference&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=r8UvWSX3KA8&quot;&gt;OpenTelemetry explained in 10 minutes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=QoDqxm7ybLc&quot;&gt;Prometheus &amp;amp; Grafana on Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=EW9GMAWsyQU&quot;&gt;Distributed tracing with Jaeger&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tEylFyxbDLE&quot;&gt;SLOs, SLAs, and Error Budgets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 6)</title>
        <published>2026-02-09T00:00:00+00:00</published>
        <updated>2026-02-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-6/"/>
        <id>https://nskm.xyz/posts/aws-6/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-6/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;helm.gif&quot; alt=&quot;Helm&quot; title=&quot;Helm&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;. The examples are intentionally simplified for clarity. Before using these patterns in production, consult the &lt;a href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;terraform&#x2F;docs&quot;&gt;Terraform documentation&lt;&#x2F;a&gt;, the &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;&quot;&gt;Helm documentation&lt;&#x2F;a&gt;, and your platform team.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;&quot;We need to set up a new environment for the epidemiology team. Can you have something running by yesterday?&quot;&lt;&#x2F;em&gt; That question is why this article exists: &lt;em&gt;how to easily repeat, redo, reiterate, duplicate, replicate, recreate, remake, reduplicate, the infrastructure we just built?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The previous episodes were focused on the theory: &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;VPCs and compute&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;IAM and encryption&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Kubernetes and EKS&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;cluster security&lt;&#x2F;a&gt;. A colleague who missed the training would get the cluster up by hand: click through the console, type commands, copy-paste YAML files, and call it done. And it would &lt;em&gt;work&lt;&#x2F;em&gt;. Until he had to do it again for staging, for recette and again for production, and then a third time months later for a deployment in another country.&lt;&#x2F;p&gt;
&lt;p&gt;Deploying &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;4s&lt;&#x2F;a&gt; for a new lab for a new country inside West Africa is something we&#x27;ve done many time in the last couple of months. Hopefully, deploying 4s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=avbNOjCOHJE&quot;&gt;will be done&lt;&#x2F;a&gt; for all the countries in Africa. Let me present to you 2 tools to solve that problem at two different layers: &lt;strong&gt;Terraform&lt;&#x2F;strong&gt; for provisioning the infrastructure, &lt;strong&gt;Helm&lt;&#x2F;strong&gt; for deploying the applications that run on it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#the-problem-reproducibility-at-two-layers&quot;&gt;The problem: reproducibility at two layers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#terraform-infrastructure-as-code&quot;&gt;Terraform: infrastructure as code&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#helm-kubernetes-package-manager&quot;&gt;Helm: Kubernetes package manager&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#where-does-the-chart-live-chart-registries&quot;&gt;Where does the chart live? Chart registries&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#putting-it-together-one-pipeline&quot;&gt;Putting it together&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-reproducibility-at-two-layers&quot;&gt;The problem: reproducibility at two layers&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine you&#x27;ve just finished reading &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Day 5&lt;&#x2F;a&gt;. You know how to secure an EKS cluster. Now you need to actually create one and deploy a Django REST API onto it.&lt;&#x2F;p&gt;
&lt;p&gt;You could do it manually, click through the EKS console, create a node group, write a few dozen YAML manifests, copy-paste the right &lt;code&gt;kubectl apply&lt;&#x2F;code&gt; commands. But we could do better. We should be able to easily redo what we&#x27;ve done.&lt;&#x2F;p&gt;
&lt;p&gt;Before we even get to the issue of reproducibility, we want to record, keep and preserve what has been done, if only so that we can review it later or go back and read through what has been achieved. As for me, throughout the workshop, I didn’t just type in commands; I wrote Bash scripts....&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Environment Variables
&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;eu-west-1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_NAME=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;ptrck-foundation-training&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ACCOUNT_ID=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;546732826958&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ID of the EKS Admin role
&lt;&#x2F;span&gt;&lt;span&gt;ROLE_ARN=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:iam::${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;ACCOUNT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:role&#x2F;EKSAdminRole&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ARN of the EKS Admin role
&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_ARN=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:eks:${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;ACCOUNT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:cluster&#x2F;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;CLUSTER_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&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:#608b4e;&quot;&gt;# I need to create this ECR repository
&lt;&#x2F;span&gt;&lt;span&gt;ECR_REPO=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;ecr-repo-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_NS=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;demo-ns-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_DEPLOYMENT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;demo-dply-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_CONTAINER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;app-ptrck&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:#608b4e;&quot;&gt;# Helper function to print things with some separation
&lt;&#x2F;span&gt;&lt;span&gt;section() {
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;=====&amp;gt; $&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Configure AWS CLI credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Identity &amp;amp; role assume
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Verify identity&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws sts get-caller-identity
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Verify role exists&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam get-role --role-name EKSAdminRole
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List all roles in account (if you have permissions)&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-roles \
&lt;&#x2F;span&gt;&lt;span&gt;  --query &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Roles[].RoleName&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --output text
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List user Policies&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-user-policies --user-name $(aws sts get-caller-identity --query &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Arn&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; --output text &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;cut -d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -f 6)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List attached policies&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_USER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; sts get-caller-identity&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; --query &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;#39;Arn&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; --output&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; text &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;cut -d&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; 6)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-attached-user-policies --user-name $CURRENT_USER
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Check current default region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure get region
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(Re)configure AWS CLI credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Assume EKS admin role &amp;amp; retrieve the token&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws sts assume-role \
&lt;&#x2F;span&gt;&lt;span&gt;    --role-session-name iam-eks-admin-role \
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# was working nice until sunday 7PM ?!
&lt;&#x2F;span&gt;&lt;span&gt;    --role-arn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;ROLE_ARN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;    --duration-seconds 43200
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Configure the &amp;#39;iam-eks-admin-role&amp;#39; profile with the temporary credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure --profile iam-eks-admin-role
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;What are the available roles ?&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-roles
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;What are the available policies?&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-policies
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Check if there is a K8s cluster available
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List all EKS clusters&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws eks list-clusters
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List clusters in my region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws eks list-clusters --region &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;At this point, there is no clusters available whaaaaaa ?! lol&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Let&amp;#39;s create our K8s cluster&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;eksctl create cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --region &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes 3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --node-type t2.micro \
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# --with-oidc: no need to separately call eksctl utils associate-iam-oidc-provider
&lt;&#x2F;span&gt;&lt;span&gt;  --with-oidc \
&lt;&#x2F;span&gt;&lt;span&gt;  --enable-auto-mode
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the &lt;strong&gt;reproducibility problem&lt;&#x2F;strong&gt;, and it lives at two distinct layers:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure layer&lt;&#x2F;strong&gt;: &lt;em&gt;Who created the VPC? What are the exact subnet CIDRs? Which KMS key encrypts etcd?&lt;&#x2F;em&gt; If the answer lives in someone&#x27;s memory or a Confluence page, you have a problem.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Application layer&lt;&#x2F;strong&gt;: &lt;em&gt;Which version of the Django app is running in staging? How do I roll back if the new release breaks something?&lt;&#x2F;em&gt; If the answer is &quot;look at the kubectl commands in the README&quot;, you have a different problem.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Terraform&lt;&#x2F;strong&gt; solves the first. &lt;strong&gt;Helm&lt;&#x2F;strong&gt; solves the second.&lt;&#x2F;p&gt;
&lt;p&gt;Bash scripts are fine for exploration and one-off tasks, but they fall short once you need state tracking, idempotence, error handling, drift detection, and dependency management — which is exactly what infrastructure provisioning requires.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terraform-infrastructure-as-code&quot;&gt;Terraform: infrastructure as code&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;a-brief-history&quot;&gt;A brief history&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.terraform.io&#x2F;&quot;&gt;Terraform&lt;&#x2F;a&gt; was created by &lt;a href=&quot;https:&#x2F;&#x2F;www.hashicorp.com&#x2F;&quot;&gt;HashiCorp&lt;&#x2F;a&gt; and first released in &lt;strong&gt;2014&lt;&#x2F;strong&gt;. The problem it solved: AWS had CloudFormation, GCP had Deployment Manager, Azure had ARM templates — but if you used more than one cloud, you had three completely different tools, three syntaxes, three mental models. Terraform &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;927&#x2F;&quot;&gt;unified them&lt;&#x2F;a&gt; under a single declarative language: &lt;strong&gt;HCL&lt;&#x2F;strong&gt; (HashiCorp Configuration Language).&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;standards.png&quot; alt=&quot;Standards&quot; title=&quot;Standards&quot;&#x2F;&gt;
&lt;p&gt;Core idea: &lt;em&gt;describe the desired state of your infrastructure, and Terraform figures out how to get there&lt;&#x2F;em&gt;. It maintains a &lt;strong&gt;state file&lt;&#x2F;strong&gt; tracking what it has created, so it can calculate the diff between current state and desired state on every run.&lt;&#x2F;p&gt;
&lt;p&gt;One important note: &lt;em&gt;as a free software advocate&lt;&#x2F;em&gt;, I should talk about the Terraform fork called &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentofu.org&#x2F;&quot;&gt;OpenTofu&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. OpenTofu is &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;projects&#x2F;opentofu&#x2F;&quot;&gt;CNCF&lt;&#x2F;a&gt; project, API-compatible with Terraform — same HCL, same providers, same workflow, &lt;em&gt;same everything&lt;&#x2F;em&gt;. For most teams, the choice between them is a licensing and governance question. The examples below work identically on both. &lt;em&gt;I hope.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternatives-why-terraform&quot;&gt;Alternatives &amp;amp; why Terraform&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Tool&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Approach&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;When to prefer it&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS CloudFormation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-native, JSON&#x2F;YAML templates&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-only shops that want native integration and no external tooling&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS CDK&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;TypeScript&#x2F;Python constructs that compile to CloudFormation&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Developer-heavy teams who want real programming languages for infrastructure&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pulumi&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Multi-cloud, uses Python&#x2F;TypeScript&#x2F;Go directly&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Teams that find HCL limiting and want full programming language expressiveness&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ansible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Procedural YAML playbooks&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Configuration management and server setup; less suited for cloud resource provisioning&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;OpenTofu&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Terraform fork, identical syntax&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Teams that want open-source governance and no BSL licensing constraints&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Why we chose Terraform? It&#x27;s multi-cloud (we&#x27;re on AWS now, but that may change, lol), it has &lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;browse&#x2F;providers&quot;&gt;over 4000 providers&lt;&#x2F;a&gt;, it has a mature module ecosystem, and it&#x27;s the most widely adopted IaC tool in the industry.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;provisioning-an-eks-cluster&quot;&gt;Provisioning an EKS cluster&lt;&#x2F;h3&gt;
&lt;p&gt;The goal: reproduce the EKS cluster from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Day 4&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Day 5&lt;&#x2F;a&gt; — VPC, private subnets, encrypted etcd, managed node group — using Terraform. Every time. Identically.&lt;&#x2F;p&gt;
&lt;p&gt;Project structure:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;infra&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── main.tf           # providers, backend, modules
&lt;&#x2F;span&gt;&lt;span&gt;├── variables.tf      # input variables
&lt;&#x2F;span&gt;&lt;span&gt;├── outputs.tf        # cluster name, endpoint (consumed by Helm later)
&lt;&#x2F;span&gt;&lt;span&gt;└── terraform.tfvars  # environment-specific values (not committed to Git)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;main.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — the core:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;terraform {
&lt;&#x2F;span&gt;&lt;span&gt;  required_providers {
&lt;&#x2F;span&gt;&lt;span&gt;    aws = {
&lt;&#x2F;span&gt;&lt;span&gt;      source  = &amp;quot;hashicorp&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      version = &amp;quot;~&amp;gt; 5.0&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;  # Remote state: shared, locked, versioned
&lt;&#x2F;span&gt;&lt;span&gt;  backend &amp;quot;s3&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;    bucket         = &amp;quot;genomics-platform-tfstate&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    key            = &amp;quot;eks&#x2F;terraform.tfstate&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    region         = &amp;quot;eu-west-3&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    dynamodb_table = &amp;quot;terraform-locks&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    encrypt        = true
&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;provider &amp;quot;aws&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  region = var.region
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# KMS key for etcd encryption (Day 5 best practice)
&lt;&#x2F;span&gt;&lt;span&gt;resource &amp;quot;aws_kms_key&amp;quot; &amp;quot;eks&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description             = &amp;quot;EKS secrets encryption&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  deletion_window_in_days = 7
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# VPC: private subnets for nodes, public subnets for load balancers
&lt;&#x2F;span&gt;&lt;span&gt;module &amp;quot;vpc&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  source  = &amp;quot;terraform-aws-modules&#x2F;vpc&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  version = &amp;quot;~&amp;gt; 5.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  name = &amp;quot;${var.cluster_name}-vpc&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  cidr = &amp;quot;10.0.0.0&#x2F;16&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  azs             = [&amp;quot;${var.region}a&amp;quot;, &amp;quot;${var.region}b&amp;quot;, &amp;quot;${var.region}c&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;  private_subnets = [&amp;quot;10.0.1.0&#x2F;24&amp;quot;, &amp;quot;10.0.2.0&#x2F;24&amp;quot;, &amp;quot;10.0.3.0&#x2F;24&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;  public_subnets  = [&amp;quot;10.0.101.0&#x2F;24&amp;quot;, &amp;quot;10.0.102.0&#x2F;24&amp;quot;, &amp;quot;10.0.103.0&#x2F;24&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  enable_nat_gateway = true
&lt;&#x2F;span&gt;&lt;span&gt;  single_nat_gateway = true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  tags = {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;kubernetes.io&#x2F;cluster&#x2F;${var.cluster_name}&amp;quot; = &amp;quot;shared&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    Environment                                 = var.environment
&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;# EKS cluster
&lt;&#x2F;span&gt;&lt;span&gt;module &amp;quot;eks&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  source  = &amp;quot;terraform-aws-modules&#x2F;eks&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  version = &amp;quot;~&amp;gt; 20.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_name    = var.cluster_name
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_version = &amp;quot;1.30&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  vpc_id     = module.vpc.vpc_id
&lt;&#x2F;span&gt;&lt;span&gt;  subnet_ids = module.vpc.private_subnets
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  # Private endpoint only (Day 5 best practice)
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_endpoint_public_access = false
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  # etcd encryption with the KMS key above
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_encryption_config = {
&lt;&#x2F;span&gt;&lt;span&gt;    resources        = [&amp;quot;secrets&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;    provider_key_arn = aws_kms_key.eks.arn
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  eks_managed_node_groups = {
&lt;&#x2F;span&gt;&lt;span&gt;    genomics = {
&lt;&#x2F;span&gt;&lt;span&gt;      instance_types = [&amp;quot;m5.large&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;      min_size       = 2
&lt;&#x2F;span&gt;&lt;span&gt;      max_size       = 10
&lt;&#x2F;span&gt;&lt;span&gt;      desired_size   = 3
&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;variables.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;variable &amp;quot;region&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;AWS region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;  default     = &amp;quot;eu-west-3&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;variable &amp;quot;cluster_name&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;EKS cluster name&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;variable &amp;quot;environment&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;Deployment environment (dev, staging, prod)&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;outputs.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — what other tools will need:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;output &amp;quot;cluster_name&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  value = module.eks.cluster_name
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;output &amp;quot;cluster_endpoint&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  value = module.eks.cluster_endpoint
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Deploy it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;terraform init          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# download providers and modules
&lt;&#x2F;span&gt;&lt;span&gt;terraform plan          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# preview what will be created
&lt;&#x2F;span&gt;&lt;span&gt;terraform apply         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create the infrastructure
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Voilà.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;helm-kubernetes-package-manager&quot;&gt;Helm: Kubernetes package manager&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;a-brief-history-1&quot;&gt;A brief history&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;&quot;&gt;Helm&lt;&#x2F;a&gt; was first presented at &lt;strong&gt;KubeCon 2015&lt;&#x2F;strong&gt; by the team at &lt;a href=&quot;https:&#x2F;&#x2F;deis.com&#x2F;&quot;&gt;Deis&lt;&#x2F;a&gt; (notably &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;technosophos&quot;&gt;Matt Butcher&lt;&#x2F;a&gt;). The problem it solved: writing raw Kubernetes manifests for a real application means dozens of YAML files, lots of copy-paste across environments, no concept of versioning, and no clean way to roll back. Helm introduced the &lt;strong&gt;chart&lt;&#x2F;strong&gt; — a package of Kubernetes manifests with templating and versioning built in.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;strong&gt;2016&lt;&#x2F;strong&gt;, Google and Deis merged their Kubernetes packaging work, and Helm was donated to the Kubernetes project. It became a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;projects&#x2F;helm&#x2F;&quot;&gt;CNCF graduated project&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; in 2020 — the same tier as Kubernetes, Prometheus, and Envoy.&lt;&#x2F;p&gt;
&lt;p&gt;Helm 2 (the first widely adopted version) required a server-side component called &lt;strong&gt;Tiller&lt;&#x2F;strong&gt; running inside the cluster. Tiller had broad cluster-admin permissions and became a well-known security liability. &lt;strong&gt;Helm 3&lt;&#x2F;strong&gt; (released in 2019) removed Tiller entirely — all operations now happen client-side, and permissions come from your own kubeconfig. Simpler and significantly more secure.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternatives-why-helm&quot;&gt;Alternatives &amp;amp; why Helm&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Tool&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Approach&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;When to prefer it&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Kustomize&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Overlay-based patching, built into kubectl&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple apps where you want no templating and native kubectl support&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Plain manifests&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Raw YAML + &lt;code&gt;kubectl apply&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Very small projects, learning environments, one-off deployments&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Skaffold&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Dev-focused workflow: build + push + deploy&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Inner-loop development with fast local iteration cycles&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Carvel &#x2F; ytt&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Structured YAML templating&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;VMware&#x2F;Tanzu ecosystems&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;We chose Helm because: versioned releases let you see exactly what is running in each namespace with &lt;code&gt;helm list&lt;&#x2F;code&gt;, atomic upgrades roll back automatically on failure, &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;hooks&lt;&#x2F;a&gt; let you run jobs before or after install (crucial for Django migrations — more on this below), and &lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;ArtifactHub&lt;&#x2F;a&gt; hosts thousands of ready-made charts for databases, ingress controllers, monitoring stacks, and more. When you need to install cert-manager or the AWS Load Balancer Controller into your cluster, it&#x27;s a one-liner.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;packaging-a-django-rest-api&quot;&gt;Packaging a Django REST API&lt;&#x2F;h3&gt;
&lt;p&gt;Our syndromic surveillance platform is a Django REST API that processes public health data. Here&#x27;s how to package it as a Helm chart.&lt;&#x2F;p&gt;
&lt;p&gt;Chart structure:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;syndromic-surveillance-api&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── Chart.yaml            # chart metadata
&lt;&#x2F;span&gt;&lt;span&gt;├── values.yaml           # default configuration values
&lt;&#x2F;span&gt;&lt;span&gt;└── templates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    ├── _helpers.tpl      # reusable template snippets
&lt;&#x2F;span&gt;&lt;span&gt;    ├── deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;    ├── service.yaml
&lt;&#x2F;span&gt;&lt;span&gt;    └── migrate-job.yaml  # Django migration hook
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Chart.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;syndromic-surveillance-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;description&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Django REST API for genomic data processing&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;application&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.1.0       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# chart version — bump when the chart itself changes
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;appVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;1.0.0&amp;quot;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# application version — overridden at deploy time
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;values.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — the defaults, overridable per environment:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicaCount&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;syndromic-surveillance-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pullPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;IfNotPresent&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tag&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# overridden at deploy time: --set image.tag=v1.2.3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterIP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;500m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;512Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;100m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;256Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DJANGO_SETTINGS_MODULE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;config.settings.production&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DB_HOST&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rds.syndromic-surveillance-platform.internal&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DB_NAME&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;syndromic-surveillance&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;templates&#x2F;deployment.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.fullname&amp;quot; .&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.labels&amp;quot; . | nindent 4&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Values.replicaCount&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.selectorLabels&amp;quot; . | nindent 6&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.selectorLabels&amp;quot; . | nindent 8&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Day 5 best practice
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;range $key&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val := .Values.env&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$key&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val | quote&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;toYaml .Values.resources | nindent 10&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;readinessProbe&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;httpGet&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;healthz&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;initialDelaySeconds&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;periodSeconds&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When, 2 years ago, I was first getting to grips with K8s, I remember using side containers to apply Django database migrations. Nowadays, I use “init containers” to do Django database migrations. And whilst doing some research on Helm, specifically to write &lt;em&gt;this article&lt;&#x2F;em&gt;, I was very surprised to discover that this thing exists. A &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;pre-upgrade hook&lt;&#x2F;a&gt; that runs &lt;code&gt;manage.py migrate&lt;&#x2F;code&gt; &lt;em&gt;before&lt;&#x2F;em&gt; any new pods are started:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;templates&#x2F;migrate-job.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — I really need to try this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.fullname&amp;quot; .&lt;&#x2F;span&gt;&lt;span&gt; }}&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-migrate&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;helm.sh&#x2F;hook&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;pre-install,pre-upgrade&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;helm.sh&#x2F;hook-delete-policy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;before-hook-creation&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;restartPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Never&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;migrate&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;manage.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;migrate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;--noinput&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;range $key&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val := .Values.env&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$key&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val | quote&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Deploy it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# First deploy
&lt;&#x2F;span&gt;&lt;span&gt;helm install syndromic-surveillance-api .&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.0.0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Upgrade to a new version
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade syndromic-surveillance-api .&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.2.3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Something broke — roll back to the previous release
&lt;&#x2F;span&gt;&lt;span&gt;helm rollback syndromic-surveillance-api -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# See what is currently running
&lt;&#x2F;span&gt;&lt;span&gt;helm list -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;where-does-the-chart-live-chart-registries&quot;&gt;Where does the chart live? Chart registries&lt;&#x2F;h2&gt;
&lt;p&gt;So far the chart lives in a local &lt;code&gt;.&#x2F;syndromic-surveillance-api&#x2F;&lt;&#x2F;code&gt; directory. That works on your machine. It doesn&#x27;t work for your teammates, your CI pipeline, or your staging environment.&lt;&#x2F;p&gt;
&lt;p&gt;Just like Docker images have registries (Docker Hub, ECR...), Helm charts have registries too.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;OCI registries — the recommended modern approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since Helm 3.8 (2022), charts can be &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;blog&#x2F;storing-charts-in-oci&#x2F;&quot;&gt;stored as OCI artifacts&lt;&#x2F;a&gt;. This means the &lt;em&gt;same registry you already use for containers images&lt;&#x2F;em&gt; can store your charts. On AWS, a single ECR repository holds both:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# package and push the chart
&lt;&#x2F;span&gt;&lt;span&gt;helm package .&#x2F;syndromic-surveillance-api
&lt;&#x2F;span&gt;&lt;span&gt;helm push syndromic-surveillance-api-0.1.0.tgz \
&lt;&#x2F;span&gt;&lt;span&gt;  oci:&#x2F;&#x2F;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;charts
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# teammates pull and install directly from ECR
&lt;&#x2F;span&gt;&lt;span&gt;helm install syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  oci:&#x2F;&#x2F;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;charts&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --version 0.1.0 \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What I recommend&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to not talk about &lt;strong&gt;classic Helm repositories&lt;&#x2F;strong&gt; &amp;amp; &lt;strong&gt;public Helm registries&lt;&#x2F;strong&gt;. Since we are learning about the AWS cloud, just use ECR with OCI. You are already paying for it, IAM controls access (the same permissions model from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;Day 2-3&lt;&#x2F;a&gt;), no extra infrastructure to maintain, and it works for both Docker images and Helm charts. Your teammates authenticate once via &lt;code&gt;aws ecr get-login-password&lt;&#x2F;code&gt; and pull charts the same way they pull images.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-together-one-pipeline&quot;&gt;Putting it together: one pipeline&lt;&#x2F;h2&gt;
&lt;p&gt;Terraform provisions the platform. Helm deploys the application. Here is the full sequence, end to end:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 1. Provision the EKS cluster
&lt;&#x2F;span&gt;&lt;span&gt;cd infra&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;terraform init
&lt;&#x2F;span&gt;&lt;span&gt;terraform apply \
&lt;&#x2F;span&gt;&lt;span&gt;  -var=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cluster_name=syndromic-surveillance-platform&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  -var=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;environment=staging&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 2. Configure kubectl to talk to the new cluster
&lt;&#x2F;span&gt;&lt;span&gt;aws eks update-kubeconfig \
&lt;&#x2F;span&gt;&lt;span&gt;  --region eu-west-3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --name syndromic-surveillance-platform
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 3. Verify the nodes are ready
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get nodes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 4. Deploy the Django API
&lt;&#x2F;span&gt;&lt;span&gt;cd ..&#x2F;syndromic-surveillance-api&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade --install syndromic-surveillance-api . \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.0.0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 5. Verify
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;span&gt;helm list -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Five steps. New environment, new cluster, application running. The same sequence works for dev, staging, and prod — with a different &lt;code&gt;environment&lt;&#x2F;code&gt; variable and &lt;code&gt;image.tag&lt;&#x2F;code&gt; each time.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Two tools, one principle: &lt;em&gt;write once, run anywhere&lt;&#x2F;em&gt;. &lt;em&gt;(I’ve got some old memories coming back to me, lol – it was the Javaboyz who used to talk like that way back then in 1995).&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Infrastructure and deployments should be like code: version-controlled, peer-reviewed, auditable, and repeatable. There is no alternative, we should adopt this way of working.&lt;&#x2F;p&gt;
&lt;p&gt;The learning curve is real. HCL takes time to learn. Helm templates can grow verbose. But the payoff is worth it every single time. As always, the subject is huge and cannot be covered in one tiny article. Here are some links you can use to learn more:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;terraform&#x2F;docs&quot;&gt;Terraform documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentofu.org&#x2F;docs&#x2F;&quot;&gt;OpenTofu documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;providers&#x2F;hashicorp&#x2F;aws&#x2F;latest&#x2F;docs&quot;&gt;Terraform AWS provider&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;modules&#x2F;terraform-aws-modules&#x2F;eks&#x2F;aws&#x2F;latest&quot;&gt;terraform-aws-modules&#x2F;eks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;&quot;&gt;Helm documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;Helm chart hooks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;ArtifactHub — public Helm chart repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chartmuseum.com&#x2F;&quot;&gt;ChartMuseum — self-hosted Helm chart repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;registries&#x2F;&quot;&gt;Helm OCI support documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aquasecurity.github.io&#x2F;tfsec&#x2F;&quot;&gt;tfsec&lt;&#x2F;a&gt; — static analysis for Terraform security misconfigurations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.infracost.io&#x2F;&quot;&gt;Infracost&lt;&#x2F;a&gt; — cost estimation for Terraform plans before you apply them&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;norwoodj&#x2F;helm-docs&quot;&gt;helm-docs&lt;&#x2F;a&gt; — auto-generate documentation for Helm charts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;helm&#x2F;chart-testing&quot;&gt;chart-testing&lt;&#x2F;a&gt; — lint and test Helm charts in CI&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fy8SHvNZGeE&quot;&gt;What&#x27;s Helm?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tomUWcQ0P3k&quot;&gt;Terraform in 100 seconds&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=7xngnjfIlK4&quot;&gt;Complete Terraform course&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=-ykwb1d0DXU&quot;&gt;Helm and Kubernetes tutorial&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MNt2HGxClZ0&quot;&gt;Terraform EKS cluster from scratch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 5)</title>
        <published>2026-02-06T00:00:00+00:00</published>
        <updated>2026-02-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-5/"/>
        <id>https://nskm.xyz/posts/aws-5/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-5/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;get_out.gif&quot; alt=&quot;Security checkpoint&quot; title=&quot;Security checkpoint&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;, not a production hardening guide. Before securing a real EKS cluster, consult the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; and involve your security teams.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Today&#x27;s topic feels like the natural conclusion of the entire week. We spent Day 1 building the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;foundation&lt;&#x2F;a&gt;: regions, VPCs, compute, storage. Days 2-3 were about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;who can do what and how to prove it&lt;&#x2F;a&gt;: IAM, OIDC, encryption, audit. Day 4 introduced &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;K8s and EKS&lt;&#x2F;a&gt;: the orchestration layer. Now we answer the question that matters most: &lt;strong&gt;how do you make sure nobody breaks into the thing you just built?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Security in K8s is not a feature you turn on. It&#x27;s a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=_GgfLZoLuGY&quot;&gt;layer&lt;&#x2F;a&gt; you build, piece by piece. And the uncomfortable truth is: K8s, out of the box, is &lt;em&gt;not&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.tigera.io&#x2F;blog&#x2F;kubernetes-is-powerful-but-not-secure-at-least-not-by-default&#x2F;&quot;&gt;secure&lt;&#x2F;a&gt;. It gives you the &lt;em&gt;mechanisms&lt;&#x2F;em&gt; — but the defaults are permissive, and the responsibility is yours.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s talk about what that means.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#k8s-security-concepts-traditional-infrastructure&quot;&gt;K8s security concepts → traditional infrastructure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#how-secure-is-k8s-by-default&quot;&gt;How secure is K8s by default?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#authentication-who-are-you&quot;&gt;Authentication: who are you?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#authorization-what-can-you-do&quot;&gt;Authorization: what can you do?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#network-security&quot;&gt;Network security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#pod-security&quot;&gt;Pod security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#secrets-management&quot;&gt;Secrets management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#resource-quotas-limitranges&quot;&gt;Resource quotas &amp;amp; LimitRanges&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#audit-observability&quot;&gt;Audit &amp;amp; observability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#best-practices-checklist&quot;&gt;Best practices checklist&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;k8s-security-concepts-traditional-infrastructure&quot;&gt;K8s security concepts → traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been securing Linux servers, you already know these concepts. K8s just applies them at orchestration scale:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8s Security Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What&#x27;s Different?&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;RBAC (Roles &amp; RoleBindings)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Linux users, groups, sudo, &lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Scoped to namespaces or cluster-wide; applies to API verbs (get, create, delete), not file permissions&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Service Accounts&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;System users (&lt;code&gt;www-data&lt;&#x2F;code&gt;, &lt;code&gt;postgres&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Identity for pods, not humans; auto-mounted tokens; can map to cloud IAM roles&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Network Policies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt;, firewall rules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative YAML; enforced by the CNI plugin; scoped by pod labels and namespaces&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pod Security Admission&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AppArmor, SELinux, seccomp profiles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-level enforcement of what containers can do (run as root, mount host paths, etc.)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;shadow&lt;&#x2F;code&gt;, SSH keys, environment variables&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Stored in etcd; base64-encoded (not encrypted!) by default; can integrate with external vaults&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Resource Quotas&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;ulimit&lt;&#x2F;code&gt;, cgroups, disk quotas&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Applied per namespace; limits CPU, memory, pod count, storage claims&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Audit Logging&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;var&#x2F;log&#x2F;auth.log&lt;&#x2F;code&gt;, syslog&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;API server records every request; configurable verbosity levels; integrates with cloud logging&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Namespaces&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;chroot, Linux namespaces, separate VMs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Logical isolation only — not a security boundary by themselves without RBAC + Network Policies&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The mental model is: &lt;strong&gt;K8s security = Linux security concepts, applied declaratively, at the API level, across a fleet of containers.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-secure-is-k8s-by-default&quot;&gt;How secure is K8s by default?&lt;&#x2F;h2&gt;
&lt;p&gt;The short answer: &lt;strong&gt;not very&lt;&#x2F;strong&gt;. You have to actively tighten things.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-you-get-out-of-the-box&quot;&gt;What you get out of the box&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API server authentication&lt;&#x2F;strong&gt;: The API server requires authentication — anonymous requests are rejected for most operations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Namespaces&lt;&#x2F;strong&gt;: Logical separation exists from the start (&lt;code&gt;default&lt;&#x2F;code&gt;, &lt;code&gt;kube-system&lt;&#x2F;code&gt;, &lt;code&gt;kube-public&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;etcd is only accessible from the control plane&lt;&#x2F;strong&gt;: In a properly set up cluster, etcd isn&#x27;t exposed to worker nodes or external networks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC is enabled&lt;&#x2F;strong&gt;: The authorization mode includes RBAC (in modern K8s versions)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;what-is-not-secure-by-default&quot;&gt;What is NOT secure by default&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;No network policies enforced.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; By default, every pod can talk to every other pod in the cluster. Your frontend pod can reach your database pod. Your staging namespace can reach your production namespace. It&#x27;s like running all your servers in the same network segment with no firewall.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;secret&#x2F;&quot;&gt;Secrets are not encrypted at rest.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; K8s Secrets are stored as base64-encoded values in etcd. Base64 is &lt;em&gt;encoding&lt;&#x2F;em&gt;, not &lt;em&gt;encryption&lt;&#x2F;em&gt;. Anyone with access to etcd can read every secret in your cluster. This is like storing passwords in a text file and calling it security.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;security-context&#x2F;&quot;&gt;Containers run as root by default.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; Unless you explicitly specify a security context, your container process runs as UID 0 — the same root as on the underlying node. A container escape vulnerability becomes a root-level compromise of the node.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;configure-service-account&#x2F;&quot;&gt;Default service accounts are overly permissive.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; Every namespace gets a &lt;code&gt;default&lt;&#x2F;code&gt; service account that is automatically mounted into every pod. In many setups, this service account has more permissions than needed — and pods that don&#x27;t need API access still get a token.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;debug&#x2F;debug-cluster&#x2F;audit&#x2F;&quot;&gt;No audit logging enabled by default.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; The API server &lt;em&gt;can&lt;&#x2F;em&gt; log every request, but audit logging is not configured out of the box. Without it, you have no record of who did what in your cluster.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-eks-twist&quot;&gt;The EKS twist&lt;&#x2F;h3&gt;
&lt;p&gt;AWS tightens some things for you when you use EKS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;etcd encryption at rest&lt;&#x2F;strong&gt; is available (you enable it with a KMS key — it&#x27;s not automatic, but it&#x27;s a one-click option)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The control plane is managed&lt;&#x2F;strong&gt;: You can&#x27;t SSH into it, and AWS handles patching — reducing your attack surface&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;API server endpoint access&lt;&#x2F;strong&gt; can be restricted to your VPC (private endpoint)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;EKS control plane logging&lt;&#x2F;strong&gt; can be sent to CloudWatch (but you have to enable it)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What remains your responsibility: network policies, pod security, RBAC configuration, secrets management, image scanning, and everything at the workload level. AWS secures the &lt;em&gt;infrastructure&lt;&#x2F;em&gt;; you secure the &lt;em&gt;workloads&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication-who-are-you&quot;&gt;Authentication: who are you?&lt;&#x2F;h2&gt;
&lt;p&gt;Before K8s can decide what you&#x27;re allowed to do, it needs to know &lt;em&gt;who you are&lt;&#x2F;em&gt;. There are two types of identities in K8s: human users and service accounts.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-service-accounts&quot;&gt;K8s Service Accounts&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;service-accounts&#x2F;&quot;&gt;Service Account&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an identity for processes running inside pods. Unlike human users (which K8s doesn&#x27;t manage directly), service accounts are native K8s objects:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceAccount&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Every namespace has a &lt;code&gt;default&lt;&#x2F;code&gt; service account. Every pod that doesn&#x27;t specify a service account gets the &lt;code&gt;default&lt;&#x2F;code&gt; one, along with a mounted token at &lt;code&gt;&#x2F;var&#x2F;run&#x2F;secrets&#x2F;kubernetes.io&#x2F;serviceaccount&#x2F;token&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Best practice&lt;&#x2F;strong&gt;: Create dedicated service accounts for each workload and disable auto-mounting of tokens for pods that don&#x27;t need API access:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceAccount&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-processor&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;automountServiceAccountToken&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;aws-iam-integration-with-eks&quot;&gt;AWS IAM integration with EKS&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, human authentication flows through AWS IAM. When you run &lt;code&gt;kubectl&lt;&#x2F;code&gt; against an EKS cluster, this is what happens:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;You authenticate to AWS&lt;&#x2F;strong&gt; (IAM user, role, or SSO)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;aws eks get-token&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; generates a token based on your IAM identity&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The EKS API server&lt;&#x2F;strong&gt; validates this token against the AWS IAM authenticator&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Your IAM identity is mapped&lt;&#x2F;strong&gt; to a K8s user&#x2F;group via the &lt;code&gt;aws-auth&lt;&#x2F;code&gt; ConfigMap or &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;access-entries.html&quot;&gt;EKS access entries&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC takes over&lt;&#x2F;strong&gt; — K8s decides what this user can do&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For pods that need to call AWS services (S3, DynamoDB, SQS), EKS offers two mechanisms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;iam-roles-for-service-accounts.html&quot;&gt;IRSA (IAM Roles for Service Accounts)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: We covered this in the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;previous article&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;pod-identities.html&quot;&gt;EKS Pod Identity&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A newer mechanism that achieves the same thing without needing to configure an OIDC provider yourself.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both eliminate the need to store AWS credentials as K8s Secrets. Temporary credentials are injected automatically and rotated by AWS.&lt;&#x2F;p&gt;
&lt;p&gt;The identity chain looks like this: &lt;strong&gt;AWS IAM&lt;&#x2F;strong&gt; (authenticates the human or CI system) → &lt;strong&gt;K8s RBAC&lt;&#x2F;strong&gt; (authorizes what they can do inside the cluster) → &lt;strong&gt;IRSA&#x2F;Pod Identity&lt;&#x2F;strong&gt; (gives pods AWS permissions without static credentials).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authorization-what-can-you-do&quot;&gt;Authorization: what can you do?&lt;&#x2F;h2&gt;
&lt;p&gt;Authentication tells K8s &lt;em&gt;who&lt;&#x2F;em&gt; you are. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;access-authn-authz&#x2F;rbac&#x2F;&quot;&gt;RBAC (Role-Based Access Control)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; tells K8s &lt;em&gt;what&lt;&#x2F;em&gt; you&#x27;re allowed to do. It&#x27;s the &lt;code&gt;sudo&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; of the K8s world — except it operates on API verbs and resources instead of commands and files.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-four-rbac-objects&quot;&gt;The four RBAC objects&lt;&#x2F;h3&gt;
&lt;p&gt;RBAC uses four objects, organized in two pairs:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Object&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Scope&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Role&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Namespace&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Defines &lt;em&gt;what&lt;&#x2F;em&gt; actions are allowed on &lt;em&gt;which&lt;&#x2F;em&gt; resources within a namespace&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;RoleBinding&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Namespace&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Binds a Role to a user, group, or service account&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ClusterRole&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-wide&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Same as Role, but applies across all namespaces&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ClusterRoleBinding&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-wide&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Binds a ClusterRole to a user, group, or service account&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;practical-example-biomedical-research-context&quot;&gt;Practical example: biomedical research context&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine a research cluster with two teams: one running genomic analysis pipelines, another managing a clinical trial data platform. You want each team to only access their own namespace:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Role: genomics researchers can manage pods, services, and jobs in their namespace
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Role&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-developer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pods&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;services&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;configmaps&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;watch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;batch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;jobs&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cronjobs&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;watch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;secrets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Can read secrets but not create&#x2F;modify them
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# RoleBinding: attach this role to the genomics team group
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;RoleBinding&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-team-binding&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;subjects&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Group&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-team&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;roleRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Role&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-developer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The clinical trials team gets a similar setup in their own namespace — and &lt;em&gt;cannot&lt;&#x2F;em&gt; see or touch anything in the &lt;code&gt;genomics&lt;&#x2F;code&gt; namespace. This is the same principle as giving each department its own Linux user group with permissions scoped to specific directories — except here the &quot;directories&quot; are K8s namespaces and the &quot;permissions&quot; are API operations.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;network-security&quot;&gt;Network security&lt;&#x2F;h2&gt;
&lt;p&gt;By default, K8s is a flat network: every pod can talk to every other pod. This is convenient for development but a disaster for security. This is like every server in a data center on the same VLAN with no firewall.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network-policies&quot;&gt;Network Policies&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;Network Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are the &lt;code&gt;iptables&lt;&#x2F;code&gt; of the K8s world. They let you control which pods can communicate with which other pods.&lt;&#x2F;p&gt;
&lt;p&gt;A Network Policy selects pods using labels and defines allowed ingress (incoming) and&#x2F;or egress (outgoing) traffic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Default deny all ingress traffic in the namespace
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NetworkPolicy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default-deny-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;: {}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Applies to ALL pods in this namespace
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;policyTypes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This single manifest changes everything: now no pod in &lt;code&gt;clinical-trials&lt;&#x2F;code&gt; can receive traffic unless explicitly allowed. This is the &quot;default deny&quot; approach, like configuring a firewall to block everything, then opening specific ports.&lt;&#x2F;p&gt;
&lt;p&gt;Now allow specific traffic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Allow only the web frontend to talk to the API server
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NetworkPolicy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;allow-frontend-to-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trials-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;policyTypes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ingress&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trials-frontend&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;TCP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Important caveat&lt;&#x2F;strong&gt;: Network Policies only work if your CNI plugin supports them. Calico, Cilium, and Weave support them. The default AWS VPC CNI &lt;em&gt;does not&lt;&#x2F;em&gt; enforce Network Policies natively — you need to install &lt;a href=&quot;https:&#x2F;&#x2F;docs.tigera.io&#x2F;calico&#x2F;latest&#x2F;getting-started&#x2F;kubernetes&#x2F;managed-public-cloud&#x2F;eks&quot;&gt;Calico&lt;&#x2F;a&gt; or enable the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;cni-network-policy.html&quot;&gt;AWS Network Policy Controller&lt;&#x2F;a&gt; (available since EKS v1.25 with VPC CNI v1.14+).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;security-groups-for-pods-eks-specific&quot;&gt;Security Groups for Pods (EKS-specific)&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, you can also apply &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;security-groups-for-pods.html&quot;&gt;Security Groups directly to pods&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. This bridges the K8s and AWS networking worlds: your pods get the same Security Group enforcement as EC2 instances.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful when you need your pods to interact with AWS resources that use Security Groups for access control (like RDS databases). Instead of opening the database to the entire node&#x27;s Security Group, you assign a specific Security Group to only the pods that need database access.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comparison-network-policies-vs-security-groups-vs-nacls&quot;&gt;Comparison: Network Policies vs Security Groups vs NACLs&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Feature&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8s Network Policies&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Security Groups&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS NACLs&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pod-to-pod within cluster&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;ENI-level (instance or pod)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Subnet-level&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Stateful?&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Depends on CNI&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Yes (return traffic auto-allowed)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (must allow both directions)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Default behavior&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Allow all (until a policy is applied)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Deny all inbound, allow all outbound&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Allow all (default NACL)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Selection method&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pod labels, namespace selectors&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Attached to ENIs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Applied to subnets&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Aware of K8s concepts?&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Yes (pods, namespaces, labels)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (IP addresses and ports only)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (IP ranges and ports only)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Intra-cluster segmentation&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Controlling access to AWS resources&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Subnet-level guardrails&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;In practice, you use &lt;strong&gt;all three layers together&lt;&#x2F;strong&gt;. Network Policies for pod-to-pod rules, Security Groups for pod-to-AWS-resource rules, and NACLs as a coarse subnet-level safety net. Defense in depth.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;eks_security_groups_pod_mapping.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pod-security&quot;&gt;Pod security&lt;&#x2F;h2&gt;
&lt;p&gt;Even if your network is locked down, a compromised container running as root with full Linux capabilities is a serious problem. Pod security is about restricting &lt;em&gt;what containers can do&lt;&#x2F;em&gt; on the node.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pod-security-standards-pod-security-admission-psa&quot;&gt;Pod Security Standards &amp;amp; Pod Security Admission (PSA)&lt;&#x2F;h3&gt;
&lt;p&gt;K8s defines three &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-standards&#x2F;&quot;&gt;Pod Security Standards&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — profiles that describe increasing levels of restriction:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Profile&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Description&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use case&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Privileged&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Unrestricted. No security checks.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;System-level workloads (CNI plugins, logging agents)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Baseline&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prevents known privilege escalations. Blocks hostNetwork, hostPID, privileged containers.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most application workloads&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Restricted&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Heavily restricted. Must run as non-root, drop all capabilities, read-only root filesystem.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Security-sensitive workloads&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-admission&#x2F;&quot;&gt;Pod Security Admission (PSA)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; enforces these standards at the namespace level using labels:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Namespace&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;enforce&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;warn&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;audit&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this configuration, any pod in &lt;code&gt;clinical-trials&lt;&#x2F;code&gt; that violates the &lt;code&gt;restricted&lt;&#x2F;code&gt; profile will be rejected. The &lt;code&gt;warn&lt;&#x2F;code&gt; and &lt;code&gt;audit&lt;&#x2F;code&gt; modes give you visibility before you enforce.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;securitycontext&quot;&gt;SecurityContext&lt;&#x2F;h3&gt;
&lt;p&gt;For fine-grained control, every pod and container can specify a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;security-context&#x2F;&quot;&gt;SecurityContext&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;secure-analysis-job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;fsGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2000
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analyzer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research-tools:v3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allowPrivilegeEscalation&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;readOnlyRootFilesystem&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;capabilities&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ALL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;data&#x2F;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;emptyDir&lt;&#x2F;span&gt;&lt;span&gt;: {}
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analysis-results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This pod: runs as a non-root user (UID 1000), cannot escalate privileges, has a read-only root filesystem (with writable &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;data&#x2F;results&lt;&#x2F;code&gt; mounts), and drops all Linux capabilities. A compromised container in this configuration can do &lt;em&gt;very&lt;&#x2F;em&gt; little damage.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;workload-isolation-via-scheduling-constraints&quot;&gt;Workload isolation via scheduling constraints&lt;&#x2F;h3&gt;
&lt;p&gt;For sensitive workloads that should not share nodes with untrusted workloads, you can use &lt;strong&gt;taints and tolerations&lt;&#x2F;strong&gt; along with &lt;strong&gt;node affinity&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Taint a node group for sensitive workloads only
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# kubectl taint nodes -l workload=sensitive sensitive=true:NoSchedule
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Pod that tolerates the taint and prefers sensitive nodes
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tolerations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sensitive&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;operator&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Equal&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;NoSchedule&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;affinity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;nodeAffinity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;nodeSelectorTerms&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchExpressions&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;operator&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;In&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;sensitive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not full multi-tenancy (K8s isn&#x27;t designed for hostile multi-tenancy), but it ensures that your genomic analysis pipelines don&#x27;t share hardware with less trusted workloads.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;secrets-management&quot;&gt;Secrets management&lt;&#x2F;h2&gt;
&lt;p&gt;Every application has secrets: database passwords, API keys, TLS certificates. How you manage them in K8s matters &lt;em&gt;a lot&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-secrets-and-why-they-re-not-really-secret&quot;&gt;K8s Secrets (and why they&#x27;re not really secret)&lt;&#x2F;h3&gt;
&lt;p&gt;K8s has a built-in Secret object:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Secret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Opaque&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;cG9zdGdyZXM=&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64 of &amp;quot;postgres&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;c3VwZXJzZWNyZXQ=&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64 of &amp;quot;supersecret&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem: this is base64 &lt;em&gt;encoding&lt;&#x2F;em&gt;, not encryption. Run &lt;code&gt;echo c3VwZXJzZWNyZXQ= | base64 -d&lt;&#x2F;code&gt; and you get &lt;code&gt;supersecret&lt;&#x2F;code&gt;. Anyone with &lt;code&gt;kubectl get secret -o yaml&lt;&#x2F;code&gt; access can read all your secrets. And in etcd, they&#x27;re stored in plain text (well, base64).&lt;&#x2F;p&gt;
&lt;p&gt;K8s Secrets are useful as &lt;em&gt;a delivery mechanism&lt;&#x2F;em&gt; (mounting credentials into pods), but they are &lt;strong&gt;not a secret store&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;encryption-at-rest-with-kms&quot;&gt;Encryption at rest with KMS&lt;&#x2F;h3&gt;
&lt;p&gt;The minimum you should do: enable &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;administer-cluster&#x2F;encrypt-data&#x2F;&quot;&gt;encryption at rest for etcd&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. In EKS, this is straightforward — you provide a KMS key when creating or updating the cluster:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws eks create-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --encryption-config &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;[{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;resources&amp;quot;: [&amp;quot;secrets&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;provider&amp;quot;: {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;keyArn&amp;quot;: &amp;quot;arn:aws:kms:eu-west-3:123456789012:key&#x2F;your-kms-key-id&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;  }]&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now secrets are encrypted in etcd using your KMS key. This protects against someone gaining access to the underlying storage — but anyone with RBAC permissions to &lt;code&gt;get secrets&lt;&#x2F;code&gt; can still read them through the API.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;external-secret-stores&quot;&gt;External secret stores&lt;&#x2F;h3&gt;
&lt;p&gt;For production, you should integrate with a dedicated secret management solution:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;secrets-manager&#x2F;&quot;&gt;AWS Secrets Manager&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; or &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;systems-manager&#x2F;latest&#x2F;userguide&#x2F;systems-manager-parameter-store.html&quot;&gt;AWS Systems Manager Parameter Store&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Store secrets in AWS, fetch them into K8s at runtime. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;secretsmanager&#x2F;latest&#x2F;userguide&#x2F;integrating_csi_driver.html&quot;&gt;AWS Secrets Store CSI Driver&lt;&#x2F;a&gt; mounts AWS secrets as volumes in your pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A K8s operator that syncs secrets from external stores (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager) into K8s Secret objects. You define an &lt;code&gt;ExternalSecret&lt;&#x2F;code&gt; resource, and the operator keeps the K8s Secret in sync:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;external-secrets.io&#x2F;v1beta1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ExternalSecret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;refreshInterval&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;1h&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretStoreRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws-secrets-manager&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterSecretStore&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretKey&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;remoteRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&#x2F;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;property&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretKey&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;remoteRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&#x2F;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;property&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sealed-secrets.netlify.app&#x2F;&quot;&gt;Sealed Secrets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Encrypts secrets so they can be safely stored in Git. A controller in the cluster decrypts them. Useful for GitOps workflows where you want everything in version control but can&#x27;t commit plain secrets.&lt;&#x2F;p&gt;
&lt;p&gt;The pattern is: &lt;strong&gt;secrets live in a dedicated, encrypted, access-controlled store&lt;&#x2F;strong&gt; (AWS Secrets Manager, Vault); &lt;strong&gt;K8s fetches them at runtime&lt;&#x2F;strong&gt; (via CSI driver or operator); &lt;strong&gt;RBAC limits who can access them&lt;&#x2F;strong&gt; within the cluster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resource-quotas-limitranges&quot;&gt;Resource quotas &amp;amp; LimitRanges&lt;&#x2F;h2&gt;
&lt;p&gt;This is the security concern people forget: &lt;strong&gt;resource abuse&lt;&#x2F;strong&gt;. A single runaway pod consuming all CPU or memory on a node is a denial-of-service attack — even if it&#x27;s accidental. In a shared cluster (multiple teams, multiple namespaces), resource guardrails are essential.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;resourcequotas&quot;&gt;ResourceQuotas&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;policy&#x2F;resource-quotas&#x2F;&quot;&gt;ResourceQuota&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; sets hard limits on what a namespace can consume:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ResourceQuota&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research-quota&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;hard&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests.cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;20&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests.memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;40Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits.cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;40&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits.memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;80Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pods&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;50&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentvolumeclaims&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;10&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;services.loadbalancers&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This ensures the genomics team can&#x27;t accidentally (or intentionally) starve the clinical trials team of resources. It&#x27;s the K8s equivalent of disk quotas and &lt;code&gt;ulimit&lt;&#x2F;code&gt; — applied at the namespace level.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;limitranges&quot;&gt;LimitRanges&lt;&#x2F;h3&gt;
&lt;p&gt;While ResourceQuotas cap the &lt;em&gt;total&lt;&#x2F;em&gt; for a namespace, &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;policy&#x2F;limit-range&#x2F;&quot;&gt;LimitRanges&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; set &lt;em&gt;per-pod&lt;&#x2F;em&gt; defaults and limits:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LimitRange&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default-limits&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;500m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;256Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;defaultRequest&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;100m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;128Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;50m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;64Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Container&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If a developer deploys a pod without specifying resource requests&#x2F;limits, LimitRange fills in the defaults. If they request more than the max, the pod is rejected. This prevents the classic &quot;someone deployed a pod with no limits and it ate the entire node&quot; scenario.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;audit-observability&quot;&gt;Audit &amp;amp; observability&lt;&#x2F;h2&gt;
&lt;p&gt;You can&#x27;t secure what you can&#x27;t see. Audit logging answers the question: &lt;strong&gt;who did what, when, and from where?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-audit-logging&quot;&gt;K8s audit logging&lt;&#x2F;h3&gt;
&lt;p&gt;The K8s API server can log every request it receives. Audit events are categorized by stage:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RequestReceived&lt;&#x2F;strong&gt;: The request was received but not yet processed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ResponseStarted&lt;&#x2F;strong&gt;: Response headers sent, body not yet (for long-running requests like &lt;code&gt;watch&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ResponseComplete&lt;&#x2F;strong&gt;: The full response was sent&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Panic&lt;&#x2F;strong&gt;: Something went very wrong&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And by level:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;None&lt;&#x2F;strong&gt;: Don&#x27;t log&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Metadata&lt;&#x2F;strong&gt;: Log request metadata (user, timestamp, resource, verb) but not body&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Request&lt;&#x2F;strong&gt;: Log metadata + request body&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RequestResponse&lt;&#x2F;strong&gt;: Log everything (metadata + request body + response body)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;An audit policy defines what to log for different resources:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;audit.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Policy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log all changes to secrets at the RequestResponse level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;RequestResponse&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;group&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;secrets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log pod changes at the Request level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;group&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pods&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;patch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log everything else at Metadata level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Metadata&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;eks-control-plane-logging-cloudwatch&quot;&gt;EKS control plane logging → CloudWatch&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, you don&#x27;t configure the audit policy directly (the control plane is managed). Instead, you enable &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;control-plane-logs.html&quot;&gt;EKS control plane logging&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; which sends logs to CloudWatch:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws eks update-cluster-config \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --logging &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;clusterLogging&amp;quot;: [{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;types&amp;quot;: [&amp;quot;api&amp;quot;, &amp;quot;audit&amp;quot;, &amp;quot;authenticator&amp;quot;, &amp;quot;controllerManager&amp;quot;, &amp;quot;scheduler&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;enabled&amp;quot;: true
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    }]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;  }&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The five log types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;api&lt;&#x2F;strong&gt;: API server request logs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;audit&lt;&#x2F;strong&gt;: K8s audit logs (who did what)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;authenticator&lt;&#x2F;strong&gt;: IAM authentication events&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;controllerManager&lt;&#x2F;strong&gt;: Controller decisions (scaling, reconciliation)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;scheduler&lt;&#x2F;strong&gt;: Pod placement decisions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;connecting-to-cloudtrail&quot;&gt;Connecting to CloudTrail&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s where the AWS training series comes full circle. &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail&lt;&#x2F;a&gt; records AWS API calls — &lt;code&gt;CreateCluster&lt;&#x2F;code&gt;, &lt;code&gt;UpdateNodegroup&lt;&#x2F;code&gt;, &lt;code&gt;AssociateEncryptionConfig&lt;&#x2F;code&gt;. CloudWatch Logs receives K8s-level audit events — &lt;code&gt;kubectl apply&lt;&#x2F;code&gt;, &lt;code&gt;kubectl delete&lt;&#x2F;code&gt;, &lt;code&gt;kubectl exec&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Together, they give you the full picture:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CloudTrail&lt;&#x2F;strong&gt;: &quot;Who created the cluster? Who changed the node group? Who modified IAM roles?&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;CloudWatch (K8s audit logs)&lt;&#x2F;strong&gt;: &quot;Who deployed this pod? Who accessed this secret? Who exec&#x27;d into that container?&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a biomedical research environment handling sensitive patient data, this level of traceability isn&#x27;t optional — it&#x27;s often a compliance requirement (HIPAA, GDPR).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;best-practices-checklist&quot;&gt;Best practices checklist&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s what &quot;secure by default&quot; should look like, organized by layer:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Identity &amp;amp; Access&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Apply least-privilege RBAC: namespace-scoped Roles over ClusterRoles&lt;&#x2F;li&gt;
&lt;li&gt;Create dedicated Service Accounts per workload; disable auto-mount for pods that don&#x27;t need API access&lt;&#x2F;li&gt;
&lt;li&gt;Use IRSA or EKS Pod Identity for AWS access — never store AWS credentials as K8s Secrets&lt;&#x2F;li&gt;
&lt;li&gt;Audit RoleBindings and ClusterRoleBindings regularly&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Apply default-deny NetworkPolicies to every namespace&lt;&#x2F;li&gt;
&lt;li&gt;Segment namespaces by trust level (production vs staging, team A vs team B)&lt;&#x2F;li&gt;
&lt;li&gt;Use Security Groups for Pods when controlling access to AWS resources&lt;&#x2F;li&gt;
&lt;li&gt;Restrict API server endpoint access (private endpoint in EKS)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Pods&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enforce Pod Security Standards (at least &lt;code&gt;baseline&lt;&#x2F;code&gt;, ideally &lt;code&gt;restricted&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Run containers as non-root, with read-only root filesystem&lt;&#x2F;li&gt;
&lt;li&gt;Drop all Linux capabilities, add back only what&#x27;s needed&lt;&#x2F;li&gt;
&lt;li&gt;Use taints&#x2F;tolerations to isolate sensitive workloads on dedicated nodes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enable etcd encryption at rest (KMS key in EKS)&lt;&#x2F;li&gt;
&lt;li&gt;Use an external secret store (AWS Secrets Manager, Vault) — not raw K8s Secrets&lt;&#x2F;li&gt;
&lt;li&gt;Rotate secrets automatically; never commit secrets to Git in plain text&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Audit &amp;amp; Observability&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enable all EKS control plane log types (api, audit, authenticator, controllerManager, scheduler)&lt;&#x2F;li&gt;
&lt;li&gt;Set up alerts for privilege escalation attempts, &lt;code&gt;kubectl exec&lt;&#x2F;code&gt; into production pods, secret access patterns&lt;&#x2F;li&gt;
&lt;li&gt;Cross-reference K8s audit logs with CloudTrail for full traceability&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Supply Chain&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Scan container images for vulnerabilities (Trivy, Snyk, ECR image scanning)&lt;&#x2F;li&gt;
&lt;li&gt;Use trusted base images from verified registries&lt;&#x2F;li&gt;
&lt;li&gt;Sign and verify container images (cosign, Notation)&lt;&#x2F;li&gt;
&lt;li&gt;Pin image tags to digests (&lt;code&gt;image: my-app@sha256:abc123...&lt;&#x2F;code&gt; instead of &lt;code&gt;image: my-app:latest&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a comprehensive, opinionated, and up-to-date reference, see the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;security&#x2F;docs&#x2F;&quot;&gt;AWS EKS Best Practices Guide&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Security consists of a series of layers that are stacked on top of one another. K8s gives you all the layers: RBAC, Network Policies, Pod Security Admission, audit logging, Secrets encryption. But it doesn&#x27;t stack them on for you. &lt;strong&gt;The defaults are permissive by design&lt;&#x2F;strong&gt;, because K8s optimizes for getting things running.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve got a terrible headache, I&#x27;ve learnt a lot of new concepts this week, but I can tell I haven&#x27;t quite got the hang of them yet. In the mean time, here are resources for you to go further:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;&quot;&gt;K8s security documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;security&#x2F;docs&#x2F;&quot;&gt;AWS EKS best practices guide - Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-standards&#x2F;&quot;&gt;Pod Security Standards&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;Network Policies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;access-authn-authz&#x2F;rbac&#x2F;&quot;&gt;RBAC documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy - container image scanner&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sealed-secrets.netlify.app&#x2F;&quot;&gt;Sealed Secrets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.tigera.io&#x2F;calico&#x2F;latest&#x2F;getting-started&#x2F;kubernetes&#x2F;managed-public-cloud&#x2F;eks&quot;&gt;Calico Network Policies for EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aquasecurity&#x2F;kube-bench&quot;&gt;kube-bench - CIS K8s Benchmark checker&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;falco.org&#x2F;&quot;&gt;Falco - runtime security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=oBf5lrmquYI&quot;&gt;K8s security best practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=jvhKOAB3Jfk&quot;&gt;RBAC explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=G3R24JSlGjY&quot;&gt;Understand RBAC in k8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dTKGkOiVFfA&quot;&gt;Network Policies explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=HRU0aCkhgwg&quot;&gt;7 k8s security best practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;headache.jpg&quot; alt=&quot;Too much concepts to digest&quot; title=&quot;Too much concepts to digest&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 4)</title>
        <published>2026-02-05T00:00:00+00:00</published>
        <updated>2026-02-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-4/"/>
        <id>https://nskm.xyz/posts/aws-4/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-4/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;albator84.webp&quot; alt=&quot;Come on maaan, I was obliged&quot; title=&quot;Come on maaan, I was obliged&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;My employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The interactions between EKS and the broader AWS ecosystem can only be fully understood through &lt;em&gt;real &amp;amp; serious&lt;&#x2F;em&gt; practice. AWS offers a &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;free&#x2F;&quot;&gt;free tier&lt;&#x2F;a&gt; with limited resources. Start small, monitor your costs, and don&#x27;t leave clusters running when you&#x27;re done.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;, &lt;em&gt;in case you missed it&lt;&#x2F;em&gt;, not a production deployment guide. Everything was intentionally simplified here for clarity. Before running EKS in production, please consult the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; and involve your security&#x2F;infrastructure teams.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A special thank you to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt; for taking the time to re-read this article and for his honest, sharp feedback — he is the one who pointed out that it read more like a Kubernetes tutorial than an EKS article. That observation directly led to the hands-on EKS examples being added. Thanks a million to him.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;This is the day 4 of the training course. The most exhausting part isn&#x27;t the training itself. The most exhausting part is that I have to leave the house earlier than usual in the hope of arriving on time (as someone who usually arrive at work at 10am).&lt;&#x2F;p&gt;
&lt;p&gt;Today will be easier than yesterday, &lt;em&gt;I hope&lt;&#x2F;em&gt;, because I’m not starting from scratch; I already know a thing or two about Kubernetes. I more or less know how to write some manifests files and use them to deploy my Django projects. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=v3oK0yMZzgo&quot;&gt;go&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The name Kubernetes originates from Ancient Greek: κυβερνήτης, romanized: kubernḗtēs, meaning pilot, steersman, navigator, and the etymological root of cybernetics. Kubernetes is often abbreviated as K8s, counting the eight letters between the K and the s (a numeronym).&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-concepts-traditional-infrastructure&quot;&gt;K8S concepts → traditional infrastructure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#why-containers&quot;&gt;Why containers?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#kubernetes-fundamentals&quot;&gt;Kubernetes fundamentals&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-architecture&quot;&gt;K8S architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-core-objects&quot;&gt;K8S core objects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-configuration-tooling&quot;&gt;K8S configuration &amp;amp; tooling&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#enter-eks&quot;&gt;Enter EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#eks-networking-iam-integration&quot;&gt;EKS networking &amp;amp; IAM integration&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#practical-example&quot;&gt;Practical example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#eks-vs-alternatives&quot;&gt;EKS vs. alternatives&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;k8s-concepts-traditional-infrastructure&quot;&gt;K8S concepts → traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been managing Linux servers and containers, you already know most of these concepts. Kubernetes just orchestrates them at scale with different names:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8S Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What&#x27;s Different?&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Cluster&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A set of servers you SSH into&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Managed as a single unit, self-healing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Control Plane&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your Ansible&#x2F;Puppet master server&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manages scheduling, state, API; you don&#x27;t run workloads on it&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Worker Node&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A Linux server running your apps&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;K8S schedules pods onto it automatically&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pod&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A process or &lt;code&gt;systemd&lt;&#x2F;code&gt; unit&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ephemeral, gets its own IP, holds containers&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Deployment&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; service + rolling restart script&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative desired state, automatic rollback, self-healing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;StatefulSet&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manually managed database instances&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ordered startup, stable network identity, persistent storage per replica&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;DaemonSet&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A service enabled on every server (&lt;code&gt;systemctl enable&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ensures one pod per node, useful for log collectors, monitoring agents&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Service&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;DNS entry + &lt;code&gt;iptables&lt;&#x2F;code&gt; rules &#x2F; HAProxy&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Stable endpoint for ephemeral pods, built-in load balancing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ingress&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Nginx or HAProxy reverse proxy config&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative HTTP&#x2F;HTTPS routing, TLS termination, path-based rules&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ConfigMap&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;export, .env file, configuration files in &#x2F;etc&#x2F;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Decoupled from the container image, injectable as env vars or mounted files&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Secret&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;gpg&lt;&#x2F;code&gt;-encrypted files, &lt;code&gt;pass&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Base64 encoded (not encrypted by default!), injectable like ConfigMaps&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Volume&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt;, NFS mount, LVM&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Lifecycle tied to pod (ephemeral) or independent (PersistentVolume)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Namespace&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Linux users&#x2F;groups, separate directories&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Logical cluster partitioning, resource quotas, access control boundaries&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;kubectl&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;ssh&lt;&#x2F;code&gt; + &lt;code&gt;systemctl&lt;&#x2F;code&gt; + &lt;code&gt;journalctl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Single CLI to manage everything in the cluster&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Helm&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;apt&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;dnf&lt;&#x2F;code&gt; package manager&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Templated K8S manifests, versioned releases, rollback support&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;kubeconfig&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Defines which clusters you can talk to and with which credentials&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: You give up simplicity (one server, one config file, one &lt;code&gt;systemctl restart&lt;&#x2F;code&gt;) in exchange for automatic scaling, self-healing, and declarative infrastructure. Whether that&#x27;s worth it depends on whether you&#x27;re running 2 containers or 200. And if you understood everything in the table above, you can stop here, I&#x27;m serious :\&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;want-to-know-more-okay&quot;&gt;Want to know more ? Okay&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;why-containers&quot;&gt;Why containers?&lt;&#x2F;h3&gt;
&lt;p&gt;Before Kubernetes, there were containers. Before containers, there was the classic problem: &lt;em&gt;&quot;it works on my machine.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You write a Python script that processes epidemiological data. It runs perfectly on your laptop with Python 3.11, pandas 2.1, and that one obscure C library you installed six months ago and forgot about. You hand it to a colleague. It breaks. Different Python version, missing library, wrong OS. You spend half a day debugging environment issues instead of doing actual work.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Containers &lt;em&gt;promise&lt;&#x2F;em&gt; to solve this.&lt;&#x2F;strong&gt; A container packages your application &lt;em&gt;and&lt;&#x2F;em&gt; its entire runtime environment (OS libraries, Python version, dependencies) into a single, portable image. If it runs in the container on your laptop, it runs the same way on a server in Bamako, in Luanda, or on your colleague&#x27;s machine. No surprises*.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Without containers:              With containers:
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+          +-----------------------+
&lt;&#x2F;span&gt;&lt;span&gt;| App A (Python 3.9)  |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| App B (Python 3.11) |          | | Container A       | |
&lt;&#x2F;span&gt;&lt;span&gt;| App C (Java 17)     |          | | Python 3.9 + App  | |
&lt;&#x2F;span&gt;&lt;span&gt;| Conflicting deps!   |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| Shared OS libraries |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| &amp;quot;Who installed      |          | | Container B       | |
&lt;&#x2F;span&gt;&lt;span&gt;|  what?&amp;quot;             |          | | Python 3.11 + App | |
&lt;&#x2F;span&gt;&lt;span&gt;|                     |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| One bare-metal      |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| server              |          | | Container C       | |
&lt;&#x2F;span&gt;&lt;span&gt;|                     |          | | Java 17 + App     | |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;                                 | Isolated, no          |
&lt;&#x2F;span&gt;&lt;span&gt;                                 | conflicts             |
&lt;&#x2F;span&gt;&lt;span&gt;                                 +-----------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;So why do you need Kubernetes?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Containers solve the packaging problem. But in production, new questions appear:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You have 15 containers across 6 servers, how do you know which server has capacity for a new one?&lt;&#x2F;li&gt;
&lt;li&gt;A server crashes at 2am, who restarts the containers that were running on it?&lt;&#x2F;li&gt;
&lt;li&gt;Traffic spikes on Monday morning, how do you spin up more copies of your web app?&lt;&#x2F;li&gt;
&lt;li&gt;You push a bad update, how do you roll back quickly?&lt;&#x2F;li&gt;
&lt;li&gt;Your containers need to talk to each other, who manages the networking and service discovery?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You &lt;em&gt;could&lt;&#x2F;em&gt; solve all of this with bash scripts, cron jobs, and Ansible playbooks. People did, for years. It worked, until it didn&#x27;t — usually at the worst possible moment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes (K8S)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an open-source platform created at Google by &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;jbeda&quot;&gt;Joe Beda&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;brendan-burns-487aa590&quot;&gt;Brendan Burns&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;craigmcluckie&quot;&gt;Craig McLuckie&lt;&#x2F;a&gt;. Announced in &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;blog&#x2F;products&#x2F;containers-kubernetes&#x2F;from-google-to-the-world-the-kubernetes-origin-story&quot;&gt;June 2014&lt;&#x2F;a&gt;, it grew out of Google&#x27;s internal cluster manager &lt;a href=&quot;https:&#x2F;&#x2F;research.google&#x2F;pubs&#x2F;large-scale-cluster-management-at-google-with-borg&#x2F;&quot;&gt;Borg&lt;&#x2F;a&gt;, which had been orchestrating containers at massive scale for over a decade. Inspired by Docker&#x27;s rise, the three founders saw the need for something that could orchestrate &lt;em&gt;many&lt;&#x2F;em&gt; containers across &lt;em&gt;many&lt;&#x2F;em&gt; machines. Google &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;reports&#x2F;kubernetes-project-journey-report&#x2F;&quot;&gt;donated Kubernetes to the CNCF&lt;&#x2F;a&gt; in 2015, and it quickly became the industry standard.&lt;&#x2F;p&gt;
&lt;p&gt;You tell K8S &lt;em&gt;what&lt;&#x2F;em&gt; you want (3 replicas of my app, exposed on port 443, with 2GB of RAM each), and it figures out &lt;em&gt;how&lt;&#x2F;em&gt; to make it happen. If something breaks, K8S fixes it automatically. &lt;em&gt;That&#x27;s the pitch&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;kubernetes-fundamentals&quot;&gt;Kubernetes fundamentals&lt;&#x2F;h3&gt;
&lt;p&gt;Kubernetes operates on one core principle: &lt;strong&gt;declarative configuration&lt;&#x2F;strong&gt;. Instead of telling the system &lt;em&gt;how&lt;&#x2F;em&gt; to do things step by step (imperative), you describe &lt;em&gt;what&lt;&#x2F;em&gt; you want the end state to look like, and K8s figures out how to get there.&lt;&#x2F;p&gt;
&lt;p&gt;On a traditional Linux server, you might do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Imperative: you tell the system every step
&lt;&#x2F;span&gt;&lt;span&gt;podman run -d --name webapp -p 8080:80 my-app:v2
&lt;&#x2F;span&gt;&lt;span&gt;podman stop webapp-old
&lt;&#x2F;span&gt;&lt;span&gt;podman rm webapp-old
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With Kubernetes, you write a manifest:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Declarative: you describe the desired state
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You apply it (&lt;code&gt;kubectl apply -f webapp.yaml&lt;&#x2F;code&gt;), and K8s handles the rest: scheduling pods on nodes with available resources, rolling out the new version, terminating old pods, restarting anything that crashes. You described &lt;em&gt;what&lt;&#x2F;em&gt; you want — 3 replicas of &lt;code&gt;my-app:v2&lt;&#x2F;code&gt; on port 80 — and K8S continuously works to make reality match your description. This is called the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;architecture&#x2F;controller&#x2F;&quot;&gt;reconciliation loop&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: K8s constantly compares the desired state (your manifest) with the actual state (what&#x27;s running), and corrects any drift.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Nota Bene:&lt;&#x2F;strong&gt; Every K8s object — Pods, Services, Deployments — is just a piece of desired state that a controller is responsible for reconciling.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-architecture&quot;&gt;K8s architecture&lt;&#x2F;h3&gt;
&lt;p&gt;A Kubernetes cluster is split into two layers: the &lt;strong&gt;control plane&lt;&#x2F;strong&gt; that makes decisions, and the &lt;strong&gt;worker nodes&lt;&#x2F;strong&gt; that run your actual workloads.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;                            +--------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                            |                            K8S CLUSTER                       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      +-----------------------------+                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |       CONTROL PLANE         |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |                             |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Scheduler |  |API      |  |&amp;lt;-- kubectl talks here   |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |          |  |Server   |  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Controller|  | etcd    |  |&amp;lt;-- cluster state lives  |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Manager   |  |  (kv)   |  |        here             |
&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;                            |           instructs  | | reports back                        |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                      v |                                     |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  +-------------+    +-------------+    +-------------+       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | WORKER 1    |    | WORKER 2    |    | WORKER 3    |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  |             |    |             |    |             |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |kubelet  | |    | |kubelet  | |    | |kubelet  | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |kube     | |    | |kube     | |    | |kube     | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |proxy    | |    | |proxy    | |    | |proxy    | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |container| |    | |container| |    | |container| |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |runtime  | |    | |runtime  | |    | |runtime  | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |Pod A    | |    | |Pod C    | |    | |Pod E    | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |Pod B    | |    | |Pod D    | |    | |         | |       |
&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#control-plane-components&quot;&gt;Control Plane&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (also called master nodes) — the brain of the cluster. It doesn&#x27;t run your applications; it manages everything else:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Component&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Role&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-apiserver&quot;&gt;API Server&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Front door for all cluster operations. Every &lt;code&gt;kubectl&lt;&#x2F;code&gt; command, every internal component, talks through it&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The SSH daemon + a REST API on your server&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#etcd&quot;&gt;etcd&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Distributed key-value store holding the entire cluster state&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your &lt;code&gt;&#x2F;etc&lt;&#x2F;code&gt; directory + a database, replicated&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-scheduler&quot;&gt;Scheduler&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Decides which worker node should run a new pod based on resource availability and constraints&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You, manually picking which server to deploy to&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-controller-manager&quot;&gt;Controller Manager&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Runs the reconciliation loops — watches desired state vs actual state and corrects drift&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your Ansible playbooks running on a schedule&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The control plane requires fewer resources than worker nodes but is &lt;em&gt;far more critical&lt;&#x2F;em&gt;. In production, you run at least 2 control plane nodes (one primary, one for recovery) so the cluster survives a node failure.&lt;&#x2F;p&gt;
 &lt;br&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#node-components&quot;&gt;Worker Nodes&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are where the heavy lifting happens: we are talking about bigger machines, more CPU, more RAM, hosting all your application pods. They&#x27;re also more expendable than control plane nodes, if a worker dies, the scheduler simply reschedules its pods onto surviving nodes. Each worker node has three main components:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Component&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Description&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kubelet&quot;&gt;Kubelet&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;An agent running on each node. It receives pod specifications from the API Server, ensures the containers described in those specs are running and healthy, and reports status back. Think of it as a local &lt;code&gt;systemd&lt;&#x2F;code&gt; that takes orders from the control plane.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-proxy&quot;&gt;Kube-proxy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A network component on each node that maintains network rules, enabling communication to and from your pods. It&#x27;s what makes Services work — routing traffic to the right pod regardless of which node it&#x27;s on.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;setup&#x2F;production-environment&#x2F;container-runtimes&#x2F;&quot;&gt;Container runtime&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The software that actually runs containers. K8s supports &lt;a href=&quot;https:&#x2F;&#x2F;containerd.io&#x2F;&quot;&gt;containerd&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;cri-o.io&#x2F;&quot;&gt;CRI-O&lt;&#x2F;a&gt;, and any runtime implementing the &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;architecture&#x2F;cri&#x2F;&quot;&gt;Container Runtime Interface (CRI)&lt;&#x2F;a&gt;. Docker was the original default but was &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;blog&#x2F;2022&#x2F;02&#x2F;17&#x2F;dockershim-faq&#x2F;&quot;&gt;deprecated as a runtime in K8s 1.24&lt;&#x2F;a&gt;.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;k8s-core-objects&quot;&gt;K8s core objects&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you understand the architecture, let&#x27;s walk through the objects you&#x27;ll actually work with \o&#x2F;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pods&quot;&gt;Pods&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;pods&#x2F;&quot;&gt;Pod&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the smallest deployable unit in Kubernetes. It&#x27;s an abstraction over one or more containers, usually running a single application. Each pod gets its own IP address and can hold sidecar containers (supporting processes like log shippers or proxies).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;red_hat_enterprise_linux&#x2F;8&#x2F;html&#x2F;building_running_and_managing_containers&#x2F;assembly_working-with-pods_building-running-and-managing-containers&quot;&gt;Pods&lt;&#x2F;a&gt; are &lt;strong&gt;ephemeral&lt;&#x2F;strong&gt; — they&#x27;re designed to be disposable. If a pod dies, it&#x27;s gone. K8s creates a new one to replace it, with a different IP. This is why you never talk to pods directly in production.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx:1.25&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, a pod is roughly equivalent to a running process or a &lt;code&gt;systemd&lt;&#x2F;code&gt; unit. The difference? K8s manages the pod&#x27;s lifecycle automatically.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;services&quot;&gt;Services&lt;&#x2F;h4&gt;
&lt;p&gt;Since pods are ephemeral, you need a stable endpoint to reach them. That&#x27;s what a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;&quot;&gt;Service&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; provides — a permanent IP address and DNS name that load-balances across a set of pods. If a pod dies and gets replaced, the Service keeps working.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Types of Services:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Scope&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use Case&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#type-clusterip&quot;&gt;ClusterIP&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (default)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Internal cluster IP&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Backend services that don&#x27;t need external access&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#type-nodeport&quot;&gt;NodePort&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Exposes on each node&#x27;s IP at a static port&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Quick external access for testing (not recommended for production)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#loadbalancer&quot;&gt;LoadBalancer&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cloud provider&#x27;s load balancer&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Production external access (on AWS, creates an ELB&#x2F;ALB)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#externalname&quot;&gt;ExternalName&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;DNS CNAME mapping&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pointing to external services (&lt;code&gt;database.example.com&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Matches pods with this label
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;targetPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LoadBalancer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Think of a Service as your &lt;code&gt;iptables&lt;&#x2F;code&gt; rules + HAProxy + DNS entry, all managed declaratively.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ingress&quot;&gt;Ingress&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;&quot;&gt;Service&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; can expose your app, but what if you have 10 services and want them all behind a single domain with path-based routing? That&#x27;s what &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;ingress&#x2F;&quot;&gt;Ingress&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; does — HTTP&#x2F;HTTPS routing with TLS termination and name-based virtual hosting.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;api-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;ingress-controllers&#x2F;&quot;&gt;Ingress Controller&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (like &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.github.io&#x2F;ingress-nginx&#x2F;&quot;&gt;Nginx Ingress Controller&lt;&#x2F;a&gt; or AWS&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes-sigs.github.io&#x2F;aws-load-balancer-controller&#x2F;&quot;&gt;ALB Ingress Controller&lt;&#x2F;a&gt;) is required to implement the rules. On a single Linux server, this is just Nginx or HAProxy configured as a reverse proxy.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;configmaps&quot;&gt;ConfigMaps&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;configmap&#x2F;&quot;&gt;ConfigMap&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; stores configuration data separately from your container image. You can inject it as environment variables or mount it as files in a pod. This decouples config from code — no rebuilding images just to change a database URL.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ConfigMap&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;app-config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DATABASE_URL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;postgres:&#x2F;&#x2F;db.example.com:5432&#x2F;mydb&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;LOG_LEVEL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;info&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reference it in a pod:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;envFrom&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;configMapRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;app-config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, this is just files in &lt;code&gt;&#x2F;etc&#x2F;myapp&#x2F;&lt;&#x2F;code&gt;. K8s makes them version-controlled and injectable.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;secrets&quot;&gt;Secrets&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;secret&#x2F;&quot;&gt;Secrets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; work exactly like ConfigMaps, but they&#x27;re intended for sensitive data (passwords, API keys). They&#x27;re stored base64-encoded, &lt;strong&gt;not encrypted by default&lt;&#x2F;strong&gt; in etcd. For real encryption at rest, enable &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;administer-cluster&#x2F;encrypt-data&#x2F;&quot;&gt;etcd encryption&lt;&#x2F;a&gt; or use external secret managers like &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;secretsmanager&#x2F;latest&#x2F;userguide&#x2F;intro.html&quot;&gt;AWS Secrets Manager&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Secret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Opaque&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;YWRtaW4=&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64(&amp;quot;admin&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;cGFzc3dvcmQ=&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64(&amp;quot;password&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a Linux server, this is like files encrypted with &lt;code&gt;gpg&lt;&#x2F;code&gt; or managed by &lt;code&gt;pass&lt;&#x2F;code&gt;. The K8s equivalent just integrates better with the pod lifecycle.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;volumes&quot;&gt;Volumes&lt;&#x2F;h4&gt;
&lt;p&gt;Containers are stateless by default — data disappears when they restart. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;volumes&#x2F;&quot;&gt;Volumes&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; attach storage to pods so data persists. K8s supports many volume types: local disks, NFS, cloud provider block storage (AWS EBS, Azure Disk), and more.&lt;&#x2F;p&gt;
&lt;p&gt;For truly persistent storage that outlives a pod, use a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;&quot;&gt;PersistentVolume (PV)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; and &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;#persistentvolumeclaims&quot;&gt;PersistentVolumeClaim (PVC)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;PersistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-pvc&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ReadWriteOnce&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;10Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres:16&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-volume&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-volume&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-pvc&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a single Linux machine, this is just mounting &lt;code&gt;&#x2F;mnt&#x2F;data&lt;&#x2F;code&gt; or an NFS share. K8s abstracts it so you can move workloads across nodes without reconfiguring mount points.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;deployments&quot;&gt;Deployments&lt;&#x2F;h4&gt;
&lt;p&gt;You rarely create pods directly. Instead, you use a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;deployment&#x2F;&quot;&gt;Deployment&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — a blueprint for stateless applications. It manages scaling, replica counts, rolling updates, and rollbacks.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Common operations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f deployment.yaml           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create or update
&lt;&#x2F;span&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Scale to 5 pods
&lt;&#x2F;span&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp webapp=my-app:v3  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rolling update
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout undo deployment&#x2F;webapp     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rollback to previous version
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout status deployment&#x2F;webapp   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Watch rollout progress
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, this is &lt;code&gt;systemd&lt;&#x2F;code&gt; units + a rolling restart script managed by &lt;a href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;&quot;&gt;Ansible&lt;&#x2F;a&gt;. K8s does it declaratively, with automatic health checks and rollback on failure.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;statefulsets&quot;&gt;StatefulSets&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;statefulset&#x2F;&quot;&gt;StatefulSets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are for stateful applications like databases. Unlike Deployments, they provide:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stable network identities&lt;&#x2F;strong&gt; (pod names like &lt;code&gt;db-0&lt;&#x2F;code&gt;, &lt;code&gt;db-1&lt;&#x2F;code&gt;, &lt;code&gt;db-2&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ordered startup and shutdown&lt;&#x2F;strong&gt; (db-0 starts before db-1)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Persistent storage per pod&lt;&#x2F;strong&gt; (each pod gets its own PVC)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;StatefulSet&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;serviceName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres:16&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeClaimTemplates&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadWriteOnce&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;20Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From my online research, many teams prefer to run databases &lt;em&gt;outside&lt;&#x2F;em&gt; K8s (RDS, managed PostgreSQL) and only use K8s for stateless workloads. I guess nobody wants to resolve an issue requiring expertise in Postgresql AND Kubernetes layers. &lt;em&gt;If you run your database inside k8s using a StatefulSet, please, let me know what are the good, the bad &amp;amp; the ugly.&lt;&#x2F;em&gt;..... { °_°} &lt;em&gt;Someone&#x27;s whispering in my ear that I should take a look at &lt;a href=&quot;https:&#x2F;&#x2F;cloudnative-pg.io&#x2F;&quot;&gt;CloudnativePG&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daemonsets&quot;&gt;DaemonSets&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;daemonset&#x2F;&quot;&gt;DaemonSet&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; ensures a copy of a pod runs on every node (or selected nodes). Useful for cluster-wide services like: log collectors (Fluentd, Filebeat), monitoring agents (Prometheus Node Exporter, Datadog agent), network plugins (Calico, Cilium).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;DaemonSet&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prom&#x2F;node-exporter:latest&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional infrastructure, this is like running &lt;code&gt;systemctl enable monitoring-agent&lt;&#x2F;code&gt; on every server. K8s does it automatically, including on new nodes as they join the cluster.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-configuration-tooling&quot;&gt;K8s configuration &amp;amp; tooling&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we know the objects, how do we actually work with them?&lt;&#x2F;p&gt;
&lt;h4 id=&quot;kubectl-the-k8s-cli&quot;&gt;kubectl — the K8s CLI&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;kubectl&#x2F;&quot;&gt;kubectl&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the official command-line interface (CLI) to interact with and manage Kubernetes clusters. It&#x27;s the equivalent of &lt;code&gt;ssh&lt;&#x2F;code&gt; + &lt;code&gt;systemctl&lt;&#x2F;code&gt; + &lt;code&gt;podman&lt;&#x2F;code&gt; all rolled into one.&lt;&#x2F;p&gt;
&lt;p&gt;Common commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# View resources
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List all pods in current namespace
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -n kube-system           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List pods in kube-system namespace
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -A                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List pods across all namespaces
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get deployments,services,ingress  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Multiple resource types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Describe details
&lt;&#x2F;span&gt;&lt;span&gt;kubectl describe pod my-pod               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Full details, events, status
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# View logs
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod -f                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Follow logs (like tail -f)
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod --previous            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Logs from crashed container
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Apply manifests
&lt;&#x2F;span&gt;&lt;span&gt;kubectl apply -f deployment.yaml          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create&#x2F;update from file
&lt;&#x2F;span&gt;&lt;span&gt;kubectl apply -f .&#x2F;manifests&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Apply all YAML in directory
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete -f deployment.yaml         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Delete resources
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Direct manipulation (less common, prefer apply)
&lt;&#x2F;span&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5
&lt;&#x2F;span&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp webapp=my-app:v3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Debugging
&lt;&#x2F;span&gt;&lt;span&gt;kubectl exec -it my-pod&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;bin&#x2F;bash      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shell into running pod
&lt;&#x2F;span&gt;&lt;span&gt;kubectl port-forward pod&#x2F;my-pod 8080:80   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Forward local port to pod
&lt;&#x2F;span&gt;&lt;span&gt;kubectl top nodes                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Resource usage per node
&lt;&#x2F;span&gt;&lt;span&gt;kubectl top pods                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Resource usage per pod
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;kubeconfig-cluster-credentials&quot;&gt;kubeconfig — cluster credentials&lt;&#x2F;h4&gt;
&lt;p&gt;Your cluster credentials live in the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;organize-cluster-access-kubeconfig&#x2F;&quot;&gt;kubeconfig file&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, usually at &lt;code&gt;~&#x2F;.kube&#x2F;config&lt;&#x2F;code&gt;. It defines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clusters&lt;&#x2F;strong&gt;: API server endpoints and certificates&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Users&lt;&#x2F;strong&gt;: Authentication credentials (certs, tokens, OIDC)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Contexts&lt;&#x2F;strong&gt;: A pairing of cluster + user + namespace&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;clusters&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cluster&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;https:&#x2F;&#x2F;eks-cluster.eu-west-3.eks.amazonaws.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;contexts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cluster&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prod-context&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;current-context&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prod-context&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&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;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eyJhbGciOiJSUzI1NiIsImtpZCI6...&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the equivalent of &lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt; for SSH connections — defining which clusters you can access and how to authenticate.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;manifest-files-infrastructure-as-code&quot;&gt;Manifest files — infrastructure as code&lt;&#x2F;h4&gt;
&lt;p&gt;All K8s resources are defined in &lt;strong&gt;manifest files&lt;&#x2F;strong&gt; — YAML or JSON documents. You store them in version control alongside your application code, making infrastructure changes auditable and reviewable.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;my-app&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── service.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── ingress.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── configmap.yaml
&lt;&#x2F;span&gt;&lt;span&gt;└── secrets.yaml    # (encrypted in git using tools like git-crypt or sealed-secrets)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply them all at once:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f .&#x2F;k8s&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Managed K8s services (&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;what-is-eks.html&quot;&gt;EKS&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.cloud.google.com&#x2F;kubernetes-engine&#x2F;docs&quot;&gt;GKE&lt;&#x2F;a&gt;) also let you manage some resources through their web consoles or CLIs. If you ask me, I&#x27;ll tell you the best practice is &lt;strong&gt;GitOps&lt;&#x2F;strong&gt;: all configuration in &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&quot;&gt;Git&lt;&#x2F;a&gt;, applied via CI&#x2F;CD or tools like &lt;a href=&quot;https:&#x2F;&#x2F;argoproj.github.io&#x2F;cd&#x2F;&quot;&gt;ArgoCD&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;&quot;&gt;Flux&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;helm-the-k8s-package-manager&quot;&gt;Helm — the K8s package manager&lt;&#x2F;h4&gt;
&lt;p&gt;Writing YAML manifests for every environment (dev, staging, prod) gets repetitive. You need to change image tags, replica counts, resource limits — but the structure stays the same. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;&quot;&gt;Helm&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; solves this by templating manifests. I need to master this part.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;strong&gt;Helm chart&lt;&#x2F;strong&gt; is a collection of templated YAML files plus a &lt;code&gt;values.yaml&lt;&#x2F;code&gt; file for customization:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# values.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicaCount&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tag&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v2.0&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# templates&#x2F;deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Values.replicaCount&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag }}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Install a chart:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;helm install my-app .&#x2F;my-chart
&lt;&#x2F;span&gt;&lt;span&gt;helm install my-app .&#x2F;my-chart --set replicaCount=5   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Override values
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade my-app .&#x2F;my-chart                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Update
&lt;&#x2F;span&gt;&lt;span&gt;helm rollback my-app                                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rollback
&lt;&#x2F;span&gt;&lt;span&gt;helm uninstall my-app                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Remove everything
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Helm also has a massive &lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;public chart repository&lt;&#x2F;a&gt; — want to deploy PostgreSQL, Redis, Nginx Ingress Controller? There&#x27;s a chart for that.&lt;&#x2F;p&gt;
&lt;p&gt;Think of Helm as the &lt;code&gt;apt&lt;&#x2F;code&gt; or &lt;code&gt;dnf&lt;&#x2F;code&gt; of Kubernetes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enter-eks&quot;&gt;Enter EKS&lt;&#x2F;h3&gt;
&lt;p&gt;Everything up to now has been generic Kubernetes — you could run it on bare metal, in your basement, or in any cloud. Now let&#x27;s talk about &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;eks&#x2F;&quot;&gt;Amazon EKS (Elastic Kubernetes Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, AWS&#x27;s managed Kubernetes offering.&lt;&#x2F;p&gt;
&lt;p&gt;The main alternatives to EKS for managing K8s include options coming from the &lt;em&gt;&lt;a href=&quot;#&quot;&gt;Hyperscalers&lt;&#x2F;a&gt; (yeah, Hyperscalers, I like the name)&lt;&#x2F;em&gt;  such as Google Kubernetes Engine (GKE) (often considered to be more powerful), Azure Kubernetes Service (AKS) (ideal for the Micros10p ecosystem). For hybrid or on-premises management, Rancher and Red Hat OpenShift are robust alternatives. As &lt;em&gt;a proud&lt;&#x2F;em&gt; DigitalOcean user, I should mention &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;products&#x2F;kubernetes&quot;&gt;DigitalOcean Kubernetes (DOKS)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What EKS manages for you:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With self-managed Kubernetes, &lt;em&gt;you&lt;&#x2F;em&gt; install, patch, upgrade, and monitor the API server, etcd, scheduler, and controller manager. If etcd crashes at 3am, someone will be paged. With EKS, AWS runs the control plane for you:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;You Manage (Self-hosted K8s)&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Manages (EKS)&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control plane nodes (HA setup, patching, upgrades)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Fully managed, multi-AZ by default&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;etcd backups and disaster recovery&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Automated backups&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control plane scaling&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Auto-scales based on cluster size&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;API server availability&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; 99.95% SLA&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Security patches for control plane&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; AWS handles it&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Worker nodes (EC2 instances)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; You still manage these&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Application deployments&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; Still your responsibility&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster monitoring and logging&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; You configure CloudWatch or Prometheus&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;EKS is a &lt;strong&gt;managed control plane&lt;&#x2F;strong&gt;, not a fully managed Kubernetes. You still provision and manage worker nodes (EC2 instances), configure networking &lt;a href=&quot;&#x2F;posts&#x2F;aws-1&#x2F;#network&quot;&gt;VPCs&lt;&#x2F;a&gt;, and set up &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#iam-policies-how-aws-actually-decides&quot;&gt;IAM roles&lt;&#x2F;a&gt;, etc...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Creating an EKS cluster with eksctl:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eksctl.io&#x2F;&quot;&gt;eksctl&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the official CLI for EKS. It abstracts away the complexity of creating, managing, and operating Amazon Elastic Kubernetes Service (Amazon EKS) clusters. Written in Go, eksctl provides a declarative syntax through YAML configurations and CLI commands to handle complex EKS cluster operations that would otherwise require multiple manual steps across different AWS services.&lt;&#x2F;p&gt;
&lt;p&gt;Simple cluster creation using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;getting-started-eksctl.html&quot;&gt;cli&lt;&#x2F;a&gt; (assuming you have the right sets or roles to do so):&lt;&#x2F;p&gt;
&lt;p&gt;In plain english:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Create a new Kubernetes cluster named my-cluster in the Paris region (eu-west-3). Add a group of worker nodes called standard-workers, each being a t3.medium machine. Start with 3 nodes running, but allow the cluster to scale down to a minimum of 1 node and up to a maximum of 4 nodes if needed. Make this node group managed by AWS (meaning AWS handles patching and updates for me).&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --region eu-west-3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodegroup-name standard-workers \
&lt;&#x2F;span&gt;&lt;span&gt;  --node-type t3.medium \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes 3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes-min 1 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes-max 4 \
&lt;&#x2F;span&gt;&lt;span&gt;  --managed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This command:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Creates a new VPC with 8 &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;eksctl&#x2F;vpc-configuration.html&quot;&gt;subnets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Deploys the EKS control plane&lt;&#x2F;li&gt;
&lt;li&gt;Launches a managed node group (3 t3.medium EC2 instances)&lt;&#x2F;li&gt;
&lt;li&gt;Configures Auto Scaling (1-4 nodes)&lt;&#x2F;li&gt;
&lt;li&gt;Sets up kubectl access automatically&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After 10-15 minutes, your cluster is ready:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl get nodes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                                           STATUS   ROLES    AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-1-10.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-2-20.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-3-30.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Advanced configuration&lt;&#x2F;strong&gt; (using a config file):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# cluster.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eksctl.io&#x2F;v1alpha5&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterConfig&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production-cluster&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;region&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;vpc&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;vpc-0123456789abcdef&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Use existing VPC from aws1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;subnets&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;private&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3a&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-a&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3b&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-b&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3c&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-c&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;managedNodeGroups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;general-purpose&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;instanceType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;t3.large&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;minSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;maxSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;desiredCapacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allow&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;publicKeyName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-keypair&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;general&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tags&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;team&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;platform&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&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;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-optimized&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;instanceType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;c5.2xlarge&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;minSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;maxSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;desiredCapacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-intensive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;taints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-intensive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NoSchedule&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create cluster -f cluster.yaml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;EKS vs. self-managed Kubernetes:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Factor&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;EKS&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Self-Managed on EC2&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Setup time&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;15 minutes (eksctl)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Hours to days (kubeadm, Terraform, Ansible)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Control plane HA&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Built-in, multi-AZ&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You configure and maintain&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Upgrades&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;eksctl upgrade cluster&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual, risky, time-consuming&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;$73&#x2F;month + nodes&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Just node costs, but more ops time&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS integration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Native (IAM, VPC, ELB, EBS)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual integration required&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Flexibility&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limited control plane customization&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full control&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;When to use&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most production workloads&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cost-sensitive, control plane customization needed&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;For most teams, EKS is worth the €€€&#x2F;month. You&#x27;re paying AWS to handle the hard parts (HA, backups, upgrades, security patches) so you can focus on running applications, not babysitting control planes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;eks-networking-iam-integration&quot;&gt;EKS networking &amp;amp; IAM integration&lt;&#x2F;h3&gt;
&lt;p&gt;EKS isn&#x27;t just Kubernetes on AWS — it&#x27;s deeply integrated with AWS services. Three key integrations make EKS feel native to the AWS ecosystem.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-vpc-cni-pods-get-real-vpc-ips&quot;&gt;1. VPC CNI — Pods get real VPC IPs&lt;&#x2F;h4&gt;
&lt;p&gt;In standard Kubernetes, pods get IP addresses from an internal overlay network (like Calico or Flannel). Pods can talk to each other, but they&#x27;re isolated from the rest of your infrastructure. If you want a pod to access an RDS database in your VPC, you need to configure routing.&lt;&#x2F;p&gt;
&lt;p&gt;EKS uses the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;pod-networking.html&quot;&gt;AWS VPC CNI plugin&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; instead. Every pod gets an IP address &lt;em&gt;directly from your VPC subnets&lt;&#x2F;em&gt; — the same subnets your EC2 instances and RDS databases live in. This means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pods are first-class VPC citizens&lt;&#x2F;strong&gt;: They appear in VPC Flow Logs, Security Groups apply to them, NACLs filter their traffic&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;No NAT for pod-to-pod traffic&lt;&#x2F;strong&gt;: Pods communicate directly via VPC routing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Simplified networking&lt;&#x2F;strong&gt;: Your pod at &lt;code&gt;10.0.1.50&lt;&#x2F;code&gt; can directly connect to your RDS instance at &lt;code&gt;10.0.2.100&lt;&#x2F;code&gt; — no special configuration needed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: Each worker node has a limited number of &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AWSEC2&#x2F;latest&#x2F;UserGuide&#x2F;using-eni.html&quot;&gt;Elastic Network Interfaces (ENIs)&lt;&#x2F;a&gt;, and each ENI has a limited number of secondary IP addresses. This caps how many pods you can run per node. A t3.medium can run ~17 pods, a c5.large can run ~29 pods. Plan your node sizing accordingly.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;                                   Traditional K8s:                   EKS with VPC CNI:
&lt;&#x2F;span&gt;&lt;span&gt;                                   +---------------------+            +---------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  VPC 10.0.0.0&#x2F;16    |            |  VPC 10.0.0.0&#x2F;16    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |                     |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  EC2: 10.0.1.10     |            |  EC2: 10.0.1.10     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  RDS: 10.0.2.100    |            |  RDS: 10.0.2.100    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |                     |            |  Pod: 10.0.1.50     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  +---------------+  |            |  Pod: 10.0.1.51     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Overlay net   |  |            |  Pod: 10.0.2.20     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | 192.168.0.0&#x2F;16|  |            |  (all in VPC range) |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  |               |  |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Pod: 192.168  |  |            |  Direct routing,    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Pod: 192.168  |  |            |  no overlay needed  |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  +---------------+  |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   +---------------------+            +---------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;2-irsa-pods-get-aws-permissions-without-secrets&quot;&gt;2. IRSA — Pods get AWS permissions without secrets&lt;&#x2F;h4&gt;
&lt;p&gt;Your pods need to access AWS services: read from S3, write to DynamoDB, publish to SQS. The wrong way to do this is hardcoding AWS credentials in a Secret (seriously, don&#x27;t). The right way is &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;iam-roles-for-service-accounts.html&quot;&gt;IAM Roles for Service Accounts (IRSA)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;IRSA uses &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#openid-connect-oidc&quot;&gt;OpenID Connect&lt;&#x2F;a&gt; to let Kubernetes Service Accounts assume IAM roles. Here&#x27;s how it works:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;EKS cluster has an OIDC provider endpoint&lt;&#x2F;li&gt;
&lt;li&gt;You create an IAM role that trusts this OIDC provider&lt;&#x2F;li&gt;
&lt;li&gt;You annotate a Kubernetes Service Account with the IAM role ARN&lt;&#x2F;li&gt;
&lt;li&gt;Pods using that Service Account automatically get temporary AWS credentials&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Step 1 — Enable OIDC provider for your cluster (one-time):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl utils associate-iam-oidc-provider \
&lt;&#x2F;span&gt;&lt;span&gt;  --cluster genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --approve
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 2 — Create an IAM policy (what AWS permissions the pod needs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&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:#d69d85;&quot;&gt;&amp;quot;Statement&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&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:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&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:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&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:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::genomics-sequencing-data&#x2F;*&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 3 — Create IAM role and Service Account together:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create iamserviceaccount \
&lt;&#x2F;span&gt;&lt;span&gt;  --name genomics-pipeline \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace genomics \
&lt;&#x2F;span&gt;&lt;span&gt;  --cluster genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --attach-policy-arn arn:aws:iam::123456789012:policy&#x2F;GenomicsS3ReadWritePolicy \
&lt;&#x2F;span&gt;&lt;span&gt;  --approve
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 4 — Use the Service Account in your pod:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;variant-analysis-job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;serviceAccountName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# This pod can read&#x2F;write genomics-sequencing-data
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analyzer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline:v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your application code just uses the standard AWS SDK — no credentials to configure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;boto3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;s3 = boto3.client(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;s3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Credentials auto-discovered from IRSA
&lt;&#x2F;span&gt;&lt;span&gt;s3.put_object(Bucket=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;genomics-sequencing-data&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, Key=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;results&#x2F;patient-42.vcf&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, Body=data)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Why this is brilliant&lt;&#x2F;strong&gt;: No secrets stored anywhere, credentials rotate automatically (just like EC2 instance roles from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Day 1&lt;&#x2F;a&gt;), and you get per-pod IAM policies — the genomics pipeline pod can access sequencing data while a separate clinical trials pod accesses a completely different bucket, all within the same cluster.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;irsa_eks_flow.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;3-aws-load-balancer-controller-ingress-creates-real-albs&quot;&gt;3. AWS Load Balancer Controller — Ingress creates real ALBs&lt;&#x2F;h4&gt;
&lt;p&gt;When you create a Kubernetes Ingress object in EKS, you want it to provision an actual &lt;a href=&quot;&#x2F;posts&#x2F;aws-1&#x2F;#load-balancing&quot;&gt;Application Load Balancer (ALB)&lt;&#x2F;a&gt;, not some pod running Nginx.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes-sigs.github.io&#x2F;aws-load-balancer-controller&#x2F;&quot;&gt;AWS Load Balancer Controller&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; does exactly this. Install it once in your cluster, and every time you create an Ingress, it provisions a real AWS ALB with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;TLS termination using ACM certificates&lt;&#x2F;li&gt;
&lt;li&gt;Path-based and host-based routing&lt;&#x2F;li&gt;
&lt;li&gt;WAF integration for DDoS protection&lt;&#x2F;li&gt;
&lt;li&gt;Full CloudWatch metrics and logging&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Installation&lt;&#x2F;strong&gt; (using Helm):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Add the EKS chart repo
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add eks https:&#x2F;&#x2F;aws.github.io&#x2F;eks-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo update
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Install the controller
&lt;&#x2F;span&gt;&lt;span&gt;helm install aws-load-balancer-controller eks&#x2F;aws-load-balancer-controller \
&lt;&#x2F;span&gt;&lt;span&gt;  -n kube-system \
&lt;&#x2F;span&gt;&lt;span&gt;  --set clusterName=genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --set serviceAccount.create=false \
&lt;&#x2F;span&gt;&lt;span&gt;  --set serviceAccount.name=aws-load-balancer-controller
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;&#x2F;strong&gt; — create an Ingress with ALB annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;scheme&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;internet-facing&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;target-type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Routes to pod IPs directly via VPC CNI
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;certificate-arn&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;arn:aws:acm:eu-west-3:123456789012:certificate&#x2F;abc123&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ingressClassName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;alb&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;api.genomics-platform.example.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&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;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it, and within 2-3 minutes, the controller creates an AWS ALB, configures target groups pointing directly to your pod IPs (thanks to VPC CNI), and updates Route 53 (if you&#x27;re using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes-sigs&#x2F;external-dns&quot;&gt;ExternalDNS&lt;&#x2F;a&gt;). Your API is now publicly accessible at &lt;code&gt;https:&#x2F;&#x2F;api.genomics-platform.example.com&lt;&#x2F;code&gt;, with TLS handled by ACM and traffic distributed across pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;This is the real and only good reason to use EKS&lt;&#x2F;strong&gt;: Kubernetes-native workflows (&lt;code&gt;kubectl apply -f ingress.yaml&lt;&#x2F;code&gt;) that provision real AWS infrastructure (ALBs, target groups, security groups) automatically. You get the declarative model of Kubernetes with the managed services of AWS.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;eks_alb_ingress_flow.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;practical-example&quot;&gt;Practical example&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s deploy a simple web application to EKS end-to-end. We use nginx here for clarity — in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Day 6&lt;&#x2F;a&gt; we&#x27;ll replace it with the actual genomics Django API, packaged as a Helm chart.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;EKS cluster running (created with &lt;code&gt;eksctl&lt;&#x2F;code&gt; as shown above)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;kubectl&lt;&#x2F;code&gt; configured to talk to your cluster&lt;&#x2F;li&gt;
&lt;li&gt;AWS Load Balancer Controller installed (optional, for the Ingress part)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Step 1 — Create the application Deployment:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx:1.25&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;64Mi&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;250m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;128Mi&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;500m&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp created
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                      READY   STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-2xqwp   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-8h4kt   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-n9p5r   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2 — Expose the Deployment with a Service:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LoadBalancer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;TCP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;targetPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# service&#x2F;webapp-service created
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get service webapp-service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME             TYPE           CLUSTER-IP      EXTERNAL-IP                             PORT(S)        AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-service   LoadBalancer   10.100.200.50   a3f2...eu-west-3.elb.amazonaws.com      80:32415&#x2F;TCP   2m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;EKS automatically provisions an AWS Elastic Load Balancer. After 2-3 minutes, the &lt;code&gt;EXTERNAL-IP&lt;&#x2F;code&gt; appears — that&#x27;s your app&#x27;s public endpoint.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 3 — Scale the application:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp scaled
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                      READY   STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-2xqwp   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-8h4kt   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-n9p5r   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-q8w3j   1&#x2F;1     Running   0          10s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-x7k2m   1&#x2F;1     Running   0          10s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The load balancer automatically distributes traffic across all 5 pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 4 — Update the application (rolling update):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp nginx=nginx:1.26
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp image updated
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout status deployment&#x2F;webapp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Waiting for deployment &amp;quot;webapp&amp;quot; rollout to finish: 2 out of 5 new replicas have been updated...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment &amp;quot;webapp&amp;quot; successfully rolled out
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;K8s replaces pods one at a time, ensuring zero downtime.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 5 — Check logs:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl logs -l app=webapp --tail=20
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shows logs from all webapp pods
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs webapp-7d8b9c5f6d-2xqwp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shows logs from a specific pod
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Step 6 — Clean up:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl delete -f webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete -f webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Or delete everything at once:
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete deployment,service -l app=webapp
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What just happened:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You described your desired state in YAML (3 replicas of nginx)&lt;&#x2F;li&gt;
&lt;li&gt;K8s scheduled pods across worker nodes&lt;&#x2F;li&gt;
&lt;li&gt;EKS provisioned an AWS ELB and configured it to route traffic to your pods&lt;&#x2F;li&gt;
&lt;li&gt;You scaled, updated, and monitored the app with simple &lt;code&gt;kubectl&lt;&#x2F;code&gt; commands&lt;&#x2F;li&gt;
&lt;li&gt;All of this ran on infrastructure defined in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Day 1&lt;&#x2F;a&gt; (VPC, subnets, security groups, IAM roles)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the declarative model in action: you say &lt;em&gt;what&lt;&#x2F;em&gt; you want, K8s figures out &lt;em&gt;how&lt;&#x2F;em&gt; to make it happen.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;eks-vs-alternatives&quot;&gt;EKS vs. alternatives&lt;&#x2F;h3&gt;
&lt;p&gt;You have containerized applications and want to run them on AWS. What should you choose? Here&#x27;s the honest comparison.&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Factor&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;EKS&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;ECS + Fargate&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Self-Managed K8s on EC2&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Complexity&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Medium&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Low&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Setup time&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;15 minutes (eksctl)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;5 minutes (CloudFormation)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Hours to days (kubeadm, Terraform)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Learning curve&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Steep (K8s expertise required)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Gentle (AWS-native, simpler concepts)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Very steep (K8s + infrastructure management)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Orchestration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full Kubernetes (industry standard)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-specific, simpler model&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full Kubernetes, full control&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Portability&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High (standard K8s, runs anywhere)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Low (AWS-only, vendor lock-in)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High (K8s is portable)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Infrastructure management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You manage worker nodes (or use Fargate)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Serverless (no nodes to manage)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You manage everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ecosystem&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Massive (Helm charts, operators, CNCF projects)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS services only&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Massive (K8s ecosystem)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;$73&#x2F;month control plane + nodes&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pay per task (no idle costs)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Just EC2 costs + your time&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Horizontal Pod Autoscaler + Cluster Autoscaler&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Auto-scales per task&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You configure everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Networking&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;VPC CNI, complex but powerful&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS native, simple&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You choose (Calico, Flannel, etc.)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;IAM integration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;IRSA (excellent)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Native task roles (excellent)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual (complex)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Monitoring&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch + Prometheus + third-party&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch native&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You set up everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Complex microservices, multi-cloud strategy, K8s expertise on team&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple containerized apps, AWS-first teams, want low ops overhead&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full control needed, K8s expertise, cost-sensitive&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Avoid if&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple 2-3 container setup, no K8s experience&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Need K8s portability, complex networking requirements&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Small team, want to focus on apps not infrastructure&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;my-honest-recommendation-for-a-biomedical-research-center&quot;&gt;My honest recommendation for a biomedical research center&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t like giving recommendations. There are so many factors to consider, so many criteria to take into account. I&#x27;ve always believed you should start simple and, if necessary, move on to more complex options.&lt;&#x2F;p&gt;
&lt;p&gt;So, for most teams, &lt;strong&gt;start with ECS + Fargate&lt;&#x2F;strong&gt;. It&#x27;s simpler, cheaper for small workloads, and gets you running quickly. As complexity grows (more services, more teams, multi-cloud needs), &lt;em&gt;then&lt;&#x2F;em&gt; evaluate EKS. If you already know Kubernetes or need portability: &lt;strong&gt;use EKS&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For example. If you&#x27;re running batch analysis jobs (genomic processing, statistical models): &lt;strong&gt;ECS + Fargate&lt;&#x2F;strong&gt; is perfect. Define the job, let AWS run it, pay only for execution time. If you&#x27;re building a complex platform, handling lots of requests, with web apps, APIs, databases, data pipelines, and ML inference: &lt;strong&gt;EKS&lt;&#x2F;strong&gt; gives you the flexibility and ecosystem to compose these pieces together.&lt;&#x2F;p&gt;
&lt;p&gt;Self-managed K8s only makes sense if you have specific requirements that EKS can&#x27;t meet, or if you have a dedicated platform team that lives and breathes Kubernetes.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Kubernetes emerged from Google&#x27;s need to manage &lt;strong&gt;&lt;em&gt;thousands of containers across massive infrastructure&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. It solved real problems at that &lt;strong&gt;&lt;em&gt;scale&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. Today, it&#x27;s becoming the &lt;strong&gt;&lt;em&gt;industry standard&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; because the problems it solves, orchestration, self-healing, automatic scaling, service discovery, are increasingly common. But that doesn&#x27;t mean every team needs it right now. Come on man, you&#x27;re not Google.&lt;&#x2F;p&gt;
&lt;p&gt;The real value is: if you understand Kubernetes, you understand container orchestration itself. That knowledge transfers everywhere: AWS EKS, Google GKE, Azure AKS, your own data center. The mental model is identical across platforms. That&#x27;s why Kubernetes literacy is worth investing in, even if you don&#x27;t deploy it immediately. Learning it now means you&#x27;ll be prepared when that moment arrives.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;solved_problem.jpg&quot; alt=&quot;You&#x27;re welcome&quot; title=&quot;You&#x27;re welcome&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;This article is awfully long &lt;em&gt;wtf&lt;&#x2F;em&gt;! I really hope you did learn something. The topic is amazingly huge and cannot be covered in one tiny small simple article. Here are resources to continue your Kubernetes and EKS journey:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Blog posts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.boot.dev&#x2F;blog&#x2F;education&#x2F;maybe-you-do-need-kubernetes&#x2F;&quot;&gt;Maybe you do need Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;&quot;&gt;Kubernetes documentation - concepts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;&quot;&gt;Amazon EKS user guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.eksworkshop.com&#x2F;&quot;&gt;Amazon EKS workshop&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;EKS best practices guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=H5sPGruv2yc&quot;&gt;You don&#x27;t need Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=s_o8dwzRlu4&quot;&gt;Kubernetes crash course for absolute beginners&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=X48VuDVv0do&quot;&gt;Kubernetes tutorial for beginners&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=QThadS3Soig&quot;&gt;Getting started with Amazon EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=l_iZfujb9rc&quot;&gt;Joe Beda on co-creating Kubernetes at Google&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Interactive learning:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;training.play-with-kubernetes.com&#x2F;kubernetes-workshop&#x2F;&quot;&gt;Free browser-based K8s playground&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;killercoda.com&#x2F;kubernetes&quot;&gt;KillerCoda interactive K8s tutorials&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools to practice with:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;minikube.sigs.k8s.io&#x2F;&quot;&gt;Minikube&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;&quot;&gt;Kind (Kubernetes in Docker)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;canonical.com&#x2F;microk8s&quot;&gt;MicroK8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k9scli.io&#x2F;&quot;&gt;k9s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k3s.io&#x2F;&quot;&gt;k3s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.k0sproject.io&#x2F;stable&#x2F;&quot;&gt;k0s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Numeronyms:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;d14n, a11y, l10n, o11y, g11n, m17n, p13n, v12n, c14n, ...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 2-3)</title>
        <published>2026-02-04T00:00:00+00:00</published>
        <updated>2026-02-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-2-3/"/>
        <id>https://nskm.xyz/posts/aws-2-3/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-2-3/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;devoops.png&quot; alt=&quot;Dev oops&quot; title=&quot;Dev oops&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I don&#x27;t agree with this, but my employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;FEYlE8pHICk&quot;&gt;I don&#x27;t ever want a problem&lt;&#x2F;a&gt;. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Welcome to the second episode of this series. Already three days in the training. The pace is fast, there are many concepts to master, fatigue and exhaustion are setting in. Today, we&#x27;ll talk about the security and audit systems that determine
whether your cloud infrastructure can be trusted with sensitive data. The previous episode can be found &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#security-and-audit&quot;&gt;Security and Audit&lt;&#x2F;a&gt; - How AWS enforces permissions and tracks access
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#iam-policies-how-aws-actually-decides&quot;&gt;IAM Policies&lt;&#x2F;a&gt; - Policy evaluation logic and types&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#openid-connect-oidc&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;a&gt; - Federated identity and cross-organizational access&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#kms-and-acm-encryption-and-certificates&quot;&gt;KMS and ACM&lt;&#x2F;a&gt; - Encryption and certificate management&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail&lt;&#x2F;a&gt; - Audit logging and compliance&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;security-and-audit&quot;&gt;Security and Audit&lt;&#x2F;h2&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#identity-and-access-management&quot;&gt;previous article&lt;&#x2F;a&gt;, we introduced IAM: users, groups, roles, policies, and the principle of least privilege. That was the &quot;who can do what&quot; overview. Today we go deeper into the &lt;em&gt;how&lt;&#x2F;em&gt; — how policies are actually evaluated, how to avoid hardcoding credentials entirely (even across organizations), how to encrypt things, and how to know &lt;em&gt;exactly&lt;&#x2F;em&gt; what happened in your account at 3am last Tuesday.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;iam-policies-how-aws-actually-decides&quot;&gt;IAM Policies: how AWS actually decides&lt;&#x2F;h3&gt;
&lt;p&gt;You write a policy, attach it to a user or role, and hope for the best. But what happens when &lt;em&gt;multiple&lt;&#x2F;em&gt; policies apply? When one says Allow and another says Deny? AWS follows a &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_evaluation-logic.html&quot;&gt;specific evaluation logic&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Default deny&lt;&#x2F;strong&gt; — everything is denied unless explicitly allowed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Explicit deny wins&lt;&#x2F;strong&gt; — if &lt;em&gt;any&lt;&#x2F;em&gt; policy says Deny, it&#x27;s denied, period&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Allow must be present&lt;&#x2F;strong&gt; — the action must be explicitly allowed by at least one policy&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Boundaries are checked&lt;&#x2F;strong&gt; — SCPs, permission boundaries, and session policies can further restrict&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Think of it like this: you need a &quot;yes&quot; from every gatekeeper, and a single &quot;no&quot; from anyone overrides everything.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Types of policies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Policy Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Attached To&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_id-based&quot;&gt;Identity-based&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Users, Groups, Roles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Grant permissions to an identity&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_resource-based&quot;&gt;Resource-based&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;S3 buckets, SQS queues, etc.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control who can access &lt;em&gt;this&lt;&#x2F;em&gt; resource&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies_boundaries.html&quot;&gt;Permission boundaries&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Users, Roles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Set the &lt;em&gt;maximum&lt;&#x2F;em&gt; permissions an identity can have&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_manage_policies_scps.html&quot;&gt;Service Control Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Organization accounts&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Guardrails across entire accounts&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_session&quot;&gt;Session policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Temporary sessions&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limit permissions for a specific session&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Permission boundaries&lt;&#x2F;strong&gt; deserve special attention. They don&#x27;t &lt;em&gt;grant&lt;&#x2F;em&gt; permissions — they set a ceiling on what an identity can do. Think of it as a safety net: an identity policy can allow an action, but if the permission boundary doesn&#x27;t include it, the action is blocked.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Permission boundary allows: &lt;code&gt;s3:*&lt;&#x2F;code&gt; and &lt;code&gt;ec2:DescribeInstances&lt;&#x2F;code&gt; (read-only)&lt;&#x2F;li&gt;
&lt;li&gt;Identity policy allows: &lt;code&gt;s3:*&lt;&#x2F;code&gt;, &lt;code&gt;ec2:*&lt;&#x2F;code&gt; (full EC2 access)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Effective result&lt;&#x2F;strong&gt;: The user can do all S3 actions and only read EC2, not modify it&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A permission boundary is a maximum limit. The effective permissions are the intersection (overlap) of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What the permission boundary allows&lt;&#x2F;li&gt;
&lt;li&gt;What the identity policy allows&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is useful when you want to let developers create their own IAM roles. You set a permission boundary that says &quot;you can have S3 and read-only EC2,&quot; and even if a developer accidentally adds a policy that grants &lt;code&gt;ec2:TerminateInstances&lt;&#x2F;code&gt;, that action is blocked by the boundary. The boundary prevents privilege escalation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A more realistic policy example:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The day 1 article showed a simple S3 read policy. Here&#x27;s what a real-world policy looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&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:#d69d85;&quot;&gt;&amp;quot;Statement&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:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadSharedDatasets&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&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:#d69d85;&quot;&gt;&amp;quot;Resource&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:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&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:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;shared&#x2F;*&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:#d69d85;&quot;&gt;&amp;quot;Condition&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:#d69d85;&quot;&gt;&amp;quot;StringEquals&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:#d69d85;&quot;&gt;&amp;quot;aws:RequestedRegion&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;eu-west-3&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 style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;UploadOwnResults&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&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:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;results&#x2F;${aws:username}&#x2F;*&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:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;DenyUnencryptedUploads&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deny&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&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:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;*&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:#d69d85;&quot;&gt;&amp;quot;Condition&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:#d69d85;&quot;&gt;&amp;quot;StringNotEquals&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:#d69d85;&quot;&gt;&amp;quot;s3:x-amz-server-side-encryption&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;aws:kms&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;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You read it like this (&lt;em&gt;Sid -&amp;gt; Effet -&amp;gt; Action -&amp;gt; Resource -&amp;gt; Condition&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;ReadSharedDatasets: Allow s3:GetObject, s3:ListBucket on research-datasets when in eu-west-3&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;UploadOwnResults: Allow s3:PutObject on own results datasets owned by current user with username&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;DenyUnencryptedUploads: Deny s3:PutObject on research-datasets when there is no KMS encryption&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You understand it like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;ReadSharedDatasets: Allow reading from the shared research-datasets bucket, but only from eu-west-3&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;UploadOwnResults: Allow uploading to your personal results folder&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;DenyUnencryptedUploads: Deny uploading unencrypted files to the research-datasets bucket&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
Now tet&#x27;s imagine the following interaction:
&lt;p&gt;A researcher tries to upload an unencrypted file to their results folder:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Policy 2 says: &quot;You can upload files&quot; ✅&lt;&#x2F;li&gt;
&lt;li&gt;Policy 3 says: &quot;But NOT unencrypted files&quot; ❌&lt;&#x2F;li&gt;
&lt;li&gt;Result: Upload is DENIED — because Explicit deny wins (rule #2 from the evaluation logic: Explicit deny wins — if any policy says Deny, it&#x27;s denied, period)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
Notice three things:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_elements_condition.html&quot;&gt;Conditions&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; restrict &lt;em&gt;where&lt;&#x2F;em&gt; actions can happen (only &lt;code&gt;eu-west-3&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_variables.html&quot;&gt;Policy variables&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; like &lt;code&gt;${aws:username}&lt;&#x2F;code&gt; scope access per current user dynamically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Explicit Deny blocks everything&lt;&#x2F;strong&gt;  A researcher can&#x27;t bypass this, even if they accidentally add a permissive policy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Why do we mention this?&lt;&#x2F;p&gt;
&lt;p&gt;To reinforce the critical IAM evaluation rule: &lt;strong&gt;&quot;A single Deny overrides all Allows&quot;&lt;&#x2F;strong&gt;. This is one of the most important security
principles in AWS.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Creating an IAM Role (practical example):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s say you have an EC2 instance running a Python script that needs to read from S3 and write to DynamoDB. Here&#x27;s how you&#x27;d do it properly with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;cli&#x2F;latest&#x2F;userguide&#x2F;cli-chap-welcome.html&quot;&gt;AWS CLI&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;Step 1 — Create the trust policy (who can assume this role):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&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:#d69d85;&quot;&gt;&amp;quot;Statement&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Principal&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Service&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ec2.amazonaws.com&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sts:AssumeRole&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Reading this in plain English:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Allow the EC2 service to assume this role (ResearchAnalysisRole)&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Breaking it down:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Principal&lt;&#x2F;strong&gt; (&lt;code&gt;ec2.amazonaws.com&lt;&#x2F;code&gt;) = WHO can do this → the EC2 service&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Action&lt;&#x2F;strong&gt; (&lt;code&gt;sts:AssumeRole&lt;&#x2F;code&gt;) = WHAT they can do → take on this role&#x27;s permissions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Effect&lt;&#x2F;strong&gt; (&lt;code&gt;Allow&lt;&#x2F;code&gt;) = permission granted&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Step 2 — Create the role and attach the trust policy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam create-role \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole \
&lt;&#x2F;span&gt;&lt;span&gt;  --assume-role-policy-document file:&#x2F;&#x2F;trust-policy.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Key distinction:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trust policy&lt;&#x2F;strong&gt; (Step 1): &quot;Who can assume this role?&quot; → Answer: The EC2 service&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Permissions policy&lt;&#x2F;strong&gt; (Step 3): &quot;What can this role do?&quot; → Answer: Read S3, write to DynamoDB&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Step 3 — Create and attach the permissions policy:&lt;&#x2F;p&gt;
&lt;p&gt;First, create the &lt;code&gt;permissions-policy.json&lt;&#x2F;code&gt; file with the permissions the role needs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&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:#d69d85;&quot;&gt;&amp;quot;Statement&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:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadFromS3&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&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:#d69d85;&quot;&gt;&amp;quot;Resource&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:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-data&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:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-data&#x2F;*&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 style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;WriteToDynamoDB&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dynamodb:PutItem&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dynamodb:UpdateItem&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:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:dynamodb:eu-west-3:123456789012:table&#x2F;analysis-results&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now attach this permissions policy to the role:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam put-role-policy \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole \
&lt;&#x2F;span&gt;&lt;span&gt;  --policy-name ResearchAnalysisPermissions \
&lt;&#x2F;span&gt;&lt;span&gt;  --policy-document file:&#x2F;&#x2F;permissions-policy.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 4 — Create an instance profile and attach the role:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam create-instance-profile \
&lt;&#x2F;span&gt;&lt;span&gt;  --instance-profile-name ResearchAnalysisProfile
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam add-role-to-instance-profile \
&lt;&#x2F;span&gt;&lt;span&gt;  --instance-profile-name ResearchAnalysisProfile \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now any EC2 instance launched with this profile gets temporary credentials based on the ResearchAnalysisRole&#x27;s permissions. automatically. No access keys to manage, no secrets to rotate, no &lt;code&gt;.env&lt;&#x2F;code&gt; file to accidentally commit inside the Git repository. Your Python script just calls &lt;code&gt;boto3.client(&#x27;s3&#x27;)&lt;&#x2F;code&gt; and it works, the SDK picks up the credentials from the instance metadata.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The complete picture:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | IAM Role: ResearchAnalysisRole                             |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | Trust Policy:                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   &amp;quot;Allow EC2 service to assume this role&amp;quot;                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          |                                                            |
&lt;&#x2F;span&gt;&lt;span&gt;                          | Permission Policy:                                         |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   - Allow S3: GetObject, ListBucket                        |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   - Allow DynamoDB: PutItem, UpdateItem                    |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                                 | (attached to)
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | Instance Profile: ResearchAnalysisProfile                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          | (container that holds the role)                            |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                                 | (attached to)
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | EC2 Instance                                               |
&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;                          |  | Python Script (running on instance)              |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  |                                                  |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | import boto3                                     |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | s3 = boto3.client(&amp;#39;s3&amp;#39;)                          |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | db = boto3.client(&amp;#39;dynamodb&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;span&gt;                          |  | Instance Metadata Service            |   |              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | (provides temporary creds) ----------+   |              |
&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&gt;                                   |            |
&lt;&#x2F;span&gt;&lt;span&gt;                               +---+---+   +----+--------+
&lt;&#x2F;span&gt;&lt;span&gt;                               |  S3   |   |  DynamoDB   |
&lt;&#x2F;span&gt;&lt;span&gt;                               |(read) |   |  (write)    |
&lt;&#x2F;span&gt;&lt;span&gt;                               +-------+   +-------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;assume-role.webp&quot; alt=&quot;Assume role&quot; title=&quot;Assume role&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;openid-connect-oidc&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;h3&gt;
&lt;p&gt;So far, IAM handles identities &lt;em&gt;inside&lt;&#x2F;em&gt; AWS. But what about the outside world? What if your GitHub Actions pipeline needs to deploy to AWS? What if your researchers log in through your organization&#x27;s Active Directory?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;openid.net&#x2F;developers&#x2F;how-connect-works&#x2F;&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an identity layer built on top of &lt;a href=&quot;https:&#x2F;&#x2F;oauth.net&#x2F;2&#x2F;&quot;&gt;OAuth 2.0&lt;&#x2F;a&gt;. It allows external identity providers to authenticate users and services, which can then assume AWS roles. No long-lived credentials stored anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it works in practice:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                                            Step 1: Authenticate with Identity Provider
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | GitHub &#x2F; Google &#x2F; Azure AD|
&lt;&#x2F;span&gt;&lt;span&gt;                                            | (Identity Provider)       |
&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;                                                       | &amp;quot;Login with GitHub&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                    +--+--+
&lt;&#x2F;span&gt;&lt;span&gt;                                                    |User |
&lt;&#x2F;span&gt;&lt;span&gt;                                                    +--+--+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 2: Receive JWT Token
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | (cryptographic proof of identity)
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | JWT Token                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | Contains:                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Repository name         |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Branch                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Commit SHA              |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Timestamp               |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 3: Send token to AWS STS
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | AWS STS                   |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | (Security Token Service)  |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 4: STS checks trust policy
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | &amp;quot;Is this token from the repo
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |  I trust? YES -&amp;gt; OK&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | Temporary AWS Credentials |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Access Key ID           |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Secret Access Key       |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Session Token           |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Expires in 1 hour       |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;The flow:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User&#x2F;Service authenticates&lt;&#x2F;strong&gt; with an external identity provider (GitHub, Google, Azure AD, corporate LDAP)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Provider issues a JSON Web Token&lt;&#x2F;strong&gt;, a cryptographic &lt;a href=&quot;https:&#x2F;&#x2F;jwt.io&#x2F;introduction&quot;&gt;proof&lt;&#x2F;a&gt; containing metadata (repository, branch, user identity, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Token is sent to AWS STS (Security Token Service)&lt;&#x2F;strong&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;STS&#x2F;latest&#x2F;APIReference&#x2F;welcome.html&quot;&gt;STS&lt;&#x2F;a&gt; examines it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;STS checks the trust policy&lt;&#x2F;strong&gt; — &quot;Is this token from a trusted source?&quot; If yes, temporary credentials are issued&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Credentials expire automatically&lt;&#x2F;strong&gt; — typically 1 hour, so no manual cleanup needed&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Real-world example — GitHub Actions deploying to AWS:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead of storing AWS access keys as GitHub secrets, you configure an &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles_providers_create_oidc.html&quot;&gt;OIDC identity provider in AWS&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# .github&#x2F;workflows&#x2F;deploy.yml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;permissions&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id-token&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Required for OIDC
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;contents&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;uses&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws-actions&#x2F;configure-aws-credentials@v4&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;role-to-assume&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;arn:aws:iam::123456789012:role&#x2F;GitHubDeployRole&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;aws-region&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws s3 sync .&#x2F;build s3:&#x2F;&#x2F;my-app-bucket&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Security: What if someone forks your repo?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If someone forks your repo, they can&#x27;t assume your role. Here&#x27;s why:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Github OIDC token includes metadata&lt;&#x2F;strong&gt;: repository name, branch, commit SHA, etc.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Your trust policy is specific&lt;&#x2F;strong&gt;: it explicitly checks: &quot;Only allow tokens from &lt;code&gt;organization&#x2F;original-repo-name&lt;&#x2F;code&gt;&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The fork has different metadata&lt;&#x2F;strong&gt;: when the fork&#x27;s workflow runs, the token says &lt;code&gt;fork-owner&#x2F;forked-repo&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The policy rejects it&lt;&#x2F;strong&gt;: AWS compares: &lt;code&gt;fork-owner&#x2F;forked-repo&lt;&#x2F;code&gt; ≠ &lt;code&gt;organization&#x2F;original-repo-name&lt;&#x2F;code&gt; → Denied&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Result: No credentials, no access&lt;&#x2F;strong&gt; — Even if the attacker has your exact workflow file, the OIDC token won&#x27;t match the trust policy&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Why this matters for a biomedical research center:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Researchers often come from partner institutions, universities, or international organizations. Instead of creating and managing IAM users for each collaborator, you can federate identity through their home institution&#x27;s identity provider. They log in with their university credentials, get temporary AWS access scoped to exactly what they need, and when their collaboration ends, you revoke nothing — their access simply stops when the trust relationship is removed.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 210px&quot; src=&quot;&#x2F;images&#x2F;security-check.webp&quot; alt=&quot;Security check&quot; title=&quot;Security check&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;kms-and-acm-encryption-and-certificates&quot;&gt;KMS and ACM: encryption and certificates&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;overview.html&quot;&gt;AWS KMS (Key Management Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Manages encryption keys for your data. If you&#x27;re storing patient data, genomic sequences, or any sensitive research data, encryption isn&#x27;t optional — it&#x27;s a compliance requirement (HIPAA, GDPR, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What it does&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;concepts.html#kms_keys&quot;&gt;Customer Master Key (CMK)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The top-level key. Never leaves AWS. You control who can use it. IAM policies define access.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;concepts.html#data-keys&quot;&gt;Data key&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Generated by KMS, used to actually encrypt your data. You use it locally, then discard it.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;key-policies.html&quot;&gt;Key policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;IAM-like policies controlling who can use or manage the key. Auditable via CloudTrail.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;rotate-keys.html&quot;&gt;Automatic rotation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS rotates key material annually. Old data remains decryptable. Compliance requirement.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;How envelope encryption works:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Step 1: Request data key from KMS
&lt;&#x2F;span&gt;&lt;span&gt;Application --&amp;gt; KMS: &amp;quot;Give me a data key&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 2: KMS returns both plaintext and encrypted key
&lt;&#x2F;span&gt;&lt;span&gt;KMS --&amp;gt; Application:
&lt;&#x2F;span&gt;&lt;span&gt;  - Plaintext key (256-bit AES key)
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted key (encrypted with CMK)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 3: Encrypt data locally with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;Application:
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypts patient data with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;  - Discards plaintext key from memory
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 4: Store encrypted data + encrypted key
&lt;&#x2F;span&gt;&lt;span&gt;Database stores:
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted patient data (gigabytes)
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted data key (tiny, ~200 bytes)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 5: To decrypt later
&lt;&#x2F;span&gt;&lt;span&gt;Application: &amp;quot;KMS, decrypt this key for me&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;KMS: Decrypts it, returns plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;Application: Uses plaintext key to decrypt patient data
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Why this design?&lt;&#x2F;strong&gt; Sending gigabytes of sensitive data to KMS would be slow, expensive, and create a bottleneck. Instead, KMS only handles small cryptographic keys, and the heavy encryption happens locally in your application. Best of both worlds: security + performance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Practical example — patient records:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;1. Patient uploads medical scan (500 MB)
&lt;&#x2F;span&gt;&lt;span&gt;2. You request a data key from KMS (costs ~$0.03)
&lt;&#x2F;span&gt;&lt;span&gt;3. Application encrypts scan with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;4. Plaintext key is immediately discarded
&lt;&#x2F;span&gt;&lt;span&gt;5. Database stores:
&lt;&#x2F;span&gt;&lt;span&gt;   - Encrypted scan (500 MB, unreadable)
&lt;&#x2F;span&gt;&lt;span&gt;   - Encrypted data key (200 bytes, small)
&lt;&#x2F;span&gt;&lt;span&gt;6. The CMK stays locked in KMS (never exported, never leaves AWS)
&lt;&#x2F;span&gt;&lt;span&gt;7. To decrypt: send encrypted key to KMS, get plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;8. Audit trail in CloudTrail: &amp;quot;Who decrypted what and when&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;AWS-managed vs. Customer-managed keys:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Cost&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Control&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use when&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS-managed&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Free&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limited (AWS rotates annually)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most AWS services (S3, RDS, DynamoDB by default)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Customer-managed&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;~$1&#x2F;month + API calls&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full (you choose rotation, who can access, audit trail)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Compliance-heavy (HIPAA, GDPR, biomedical data)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;For biomedical research with patient data, &lt;strong&gt;customer-managed keys are typically required&lt;&#x2F;strong&gt; because auditors need to see exactly who accessed the encryption keys and when (CloudTrail).&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;acm&#x2F;latest&#x2F;userguide&#x2F;acm-overview.html&quot;&gt;AWS ACM (Certificate Manager)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Handles TLS&#x2F;SSL certificates for your domains. If you&#x27;ve wrestled with &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;&quot;&gt;Let&#x27;s Encrypt&lt;&#x2F;a&gt; renewals, ACM is the managed equivalent.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Public certificates (Free):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Domain validation: ACM verifies you own the domain&lt;&#x2F;li&gt;
&lt;li&gt;Use with: ALB, CloudFront, API Gateway&lt;&#x2F;li&gt;
&lt;li&gt;Automatic renewal: No more &quot;certificate expired at 3am&quot; alerts&lt;&#x2F;li&gt;
&lt;li&gt;Wildcard support: &lt;code&gt;*.example.com&lt;&#x2F;code&gt; covers all subdomains&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Private CA (Paid):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For internal services that need TLS but aren&#x27;t exposed to the internet&lt;&#x2F;li&gt;
&lt;li&gt;Example: Your research database server communicates with Python scripts using mutual TLS&lt;&#x2F;li&gt;
&lt;li&gt;Cost: ~$400&#x2F;month for the CA, plus per-certificate fees&lt;&#x2F;li&gt;
&lt;li&gt;Use when: Internal services need encrypted communication, but you control both client and server&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;The tradeoff:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACM public certificates:&lt;&#x2F;strong&gt; Free, automatic, but only work with AWS services&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Let&#x27;s Encrypt:&lt;&#x2F;strong&gt; Free, but you manage renewal automation yourself&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ACM private CA:&lt;&#x2F;strong&gt; Paid, but manages all internal TLS automatically&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For biomedical research centers: use &lt;strong&gt;free public certificates for your website&lt;&#x2F;strong&gt; (ACM + ALB), and use &lt;strong&gt;HTTP&#x2F;2 between internal services&lt;&#x2F;strong&gt; (encryption handled by VPC itself, no need for certificates).&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;crypto.png&quot; alt=&quot;Speak louder for those at the back of the room&quot; title=&quot;Speak louder for those at the back of the room&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail: who did what, and when&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudtrail-user-guide.html&quot;&gt;AWS CloudTrail&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; records every API call made in your AWS account. Every. Single. One. Someone launched an EC2 instance? Logged. Someone changed a security group? Logged. Someone tried to access an S3 bucket and was denied? Logged.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What CloudTrail captures:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Field&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Example&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Who&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;arn:aws:iam::123456789012:user&#x2F;jdoe&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;What&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;RunInstances&lt;&#x2F;code&gt;, &lt;code&gt;PutBucketPolicy&lt;&#x2F;code&gt;, &lt;code&gt;DeleteObject&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;When&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;2026-02-04T14:32:17Z&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Where&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;eu-west-3&lt;&#x2F;code&gt;, source IP &lt;code&gt;203.0.113.42&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;How&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Console, CLI, SDK, or assumed role&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Result&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Success or failure (with error code)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Event types:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Management events&lt;&#x2F;strong&gt;: Control plane operations (creating resources, changing configurations). Logged by default.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Data events&lt;&#x2F;strong&gt;: Data plane operations (reading S3 objects, invoking Lambda functions). &lt;em&gt;Not&lt;&#x2F;em&gt; logged by default — you must explicitly enable them. They&#x27;re high-volume and cost money.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Insights events&lt;&#x2F;strong&gt;: CloudTrail analyzes your patterns and flags unusual activity (sudden spike in API calls, unusual error rates).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Practical example — investigating a security incident:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A researcher reports they can&#x27;t access their S3 bucket anymore. You suspect someone changed the bucket policy. With CloudTrail and &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;logs&#x2F;AnalyzingLogData.html&quot;&gt;CloudWatch Logs Insights&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span&gt;fields @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;userIdentity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;arn&lt;&#x2F;span&gt;&lt;span&gt;, eventName, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;requestParameters&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;bucketName
&lt;&#x2F;span&gt;&lt;span&gt;| filter eventSource = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3.amazonaws.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;| filter eventName &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;like &#x2F;&lt;&#x2F;span&gt;&lt;span&gt;PutBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;| filter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;requestParameters&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;bucketName &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;research-datasets&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;| sort @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;timestamp desc
&lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;limit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This query shows you exactly who modified the bucket policy, when, and from where. No more guessing, no more &quot;it wasn&#x27;t me.&quot; The audit trail is immutable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Best practices:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable CloudTrail in all regions&lt;&#x2F;strong&gt; — attacks often target regions you&#x27;re not watching&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Send logs to a centralized S3 bucket&lt;&#x2F;strong&gt; in a dedicated security account — so attackers can&#x27;t delete their tracks even if they compromise a workload account&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Enable log file integrity validation&lt;&#x2F;strong&gt; — CloudTrail can detect if someone tampered with log files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Set up &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudwatch-alarms-for-cloudtrail.html&quot;&gt;CloudWatch alarms&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; for critical events: root account login, IAM policy changes, security group modifications, console sign-in failures&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;The traditional infrastructure equivalent:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;CloudTrail Feature&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Management events&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt; on Linux, syslog for config changes&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Data events&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Application-level access logs (Apache, Nginx logs)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Insights&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Custom anomaly detection scripts, SIEM correlation rules&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Log integrity&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;AIDE&lt;&#x2F;code&gt;, &lt;code&gt;Tripwire&lt;&#x2F;code&gt;, signed log shipping&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Multi-region logging&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Centralized syslog server, rsyslog forwarding&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;In the biomedical research context:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;CloudTrail is &lt;em&gt;required&lt;&#x2F;em&gt; for compliance. HIPAA mandates audit trails for access to protected health information. GDPR requires you to demonstrate who accessed personal data and why. CloudTrail, combined with &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;config&#x2F;latest&#x2F;developerguide&#x2F;WhatIsConfig.html&quot;&gt;AWS Config&lt;&#x2F;a&gt; (which tracks &lt;em&gt;resource&lt;&#x2F;em&gt; configuration changes over time), gives you a complete audit story.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;equivalence-in-the-linux-world&quot;&gt;Equivalence in the Linux world&lt;&#x2F;h2&gt;
&lt;p&gt;The concepts we&#x27;ve covered aren&#x27;t AWS innovations. They&#x27;re &lt;strong&gt;fundamental security patterns&lt;&#x2F;strong&gt; that exist in every operating system. Here&#x27;s how AWS services map to traditional Linux&#x2F;Unix equivalents:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Service&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Linux&#x2F;Unix Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;IAM Policies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;, file permissions (rwx), RBAC&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Define who can do what&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Permission Boundaries&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AppArmor, SELinux policies&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Set maximum permissions ceiling&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;OIDC (Federated Identity)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;LDAP, Kerberos, PAM modules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;External identity provider authentication&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Trust Policy&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;, PAM rules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Define who can assume a role&#x2F;user&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;KMS (Encryption Keys)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;GPG, OpenSSL, PKCS#11, HSM&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manage encryption keys centrally&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ACM (Certificates)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Let&#x27;s Encrypt + certbot, OpenSSL&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manage TLS&#x2F;SSL certificates&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;CloudTrail (Audit)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;syslog&lt;&#x2F;code&gt;, &lt;code&gt;journalctl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Immutable audit logs of system activity&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Why AWS then?&lt;&#x2F;strong&gt; These equivalents work great on Linux, but AWS eliminates the plumbing work, automates, standardizes, and integrates these patterns across hundreds of services. AWS provides enterprise-grade reliability.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;If Day 1 was about &quot;where and what,&quot; Day 2-3 has been about &quot;how and who.&quot; Security and audit should not be something you think about &lt;em&gt;after&lt;&#x2F;em&gt;. They&#x27;re the foundation of any production infrastructure, especially even more for people handling sensitive data like what we do with &lt;a href=&quot;&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;4S&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The patterns here generalize beyond AWS: whether you&#x27;re running on-premises or on another cloud, the principles remain the same:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default deny, explicit allow&lt;&#x2F;strong&gt;: the principle of least privilege applied everywhere&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Separate the identity layer&lt;&#x2F;strong&gt;: authentication (who you are) from authorization (what you can do)&lt;&#x2F;li&gt;
&lt;li&gt;**Keep an immutable audit trail: you can&#x27;t defend what you can&#x27;t prove&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Encrypt by default&lt;&#x2F;strong&gt;: both in transit and at rest&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Use temporary credentials&lt;&#x2F;strong&gt;: no long-lived secrets scattered across your infrastructure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I don&#x27;t think I have fully understood and mastered everything. I don&#x27;t think I can explore everything in a single article. If you want to dive deeper into AWS security and audit, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;best-practices.html&quot;&gt;AWS Identity and Access Management Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;architecture&#x2F;security-identity-compliance&#x2F;&quot;&gt;AWS Security Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;compliance&#x2F;hipaa-compliance&#x2F;&quot;&gt;HIPAA Compliance on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;compliance&#x2F;gdpr-center&#x2F;&quot;&gt;GDPR Compliance on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudtrail-user-guide.html&quot;&gt;CloudTrail User Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;best-practices.html&quot;&gt;KMS Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;prescriptive-guidance&#x2F;latest&#x2F;security-reference-architecture&#x2F;&quot;&gt;AWS Security Reference Architecture (SRA)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles_providers_oidc.html&quot;&gt;OpenID Connect on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;owasp.org&#x2F;www-project-top-ten&#x2F;&quot;&gt;The OWASP Top 10 and how cloud addresses it&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;security&#x2F;zero-trust&#x2F;&quot;&gt;Zero Trust Architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 1)</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://nskm.xyz/posts/aws-1/"/>
        <id>https://nskm.xyz/posts/aws-1/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-1/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-infra.jpg&quot; alt=&quot;infrastructure&quot; title=&quot;infrastructure&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I don&#x27;t agree with this, but my employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;FEYlE8pHICk&quot;&gt;I don&#x27;t ever want a problem&lt;&#x2F;a&gt;. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If you are a colleague and recognize the situation described below, remember: I&#x27;m critiquing the system, not the people.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Render unto Caesar what is Caesar&#x27;s, Claude helped me find up-to-date documentation links and he also helped beautify all the diagrams used (and not used) in this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;One of the joys of corporate life: you&#x27;re politely asked what training would help you be more productive, and a few months later, you&#x27;re enrolled in something completely unrelated to your request.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been asked to take a course called &quot;AWS Automation and Observability.&quot; Of course, I only have one choice: accept. Even though I wasn&#x27;t sure it would be immediately relevant to my current work.&lt;&#x2F;p&gt;
&lt;p&gt;Training you didn&#x27;t choose &lt;em&gt;(especially when you already have some technical background)&lt;&#x2F;em&gt; can feel misaligned with your current interests. When the content covers tools like &lt;a href=&quot;https:&#x2F;&#x2F;i.giphy.com&#x2F;pPhyAv5t9V8djyRFJH.webp&quot;&gt;Jenkins&lt;&#x2F;a&gt; without discussing more modern CI&#x2F;CD approaches, the relevance can feel limited.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a certain irony in being told:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;« Il est strictement interdit d&#x27;enregistrer, de filmer ou de fixer par quelque moyen que ce soit les sessions de formation. Les supports doivent rester confidentiels. »&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;...when the material itself is widely available in public documentation, and when &lt;em&gt;(at least for day 0)&lt;&#x2F;em&gt;, there was no instructor-specific examples or custom material. I respect the instructor&#x27;s knowledge of the subject, &lt;em&gt;he clearly knows his stuff&lt;&#x2F;em&gt;, but I felt the format, delivery, and relevance could have been better tailored to the audience.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the problem isn&#x27;t the instructor but the constraints he was working under: limited time, the fact that there were too many people with different levels in the same class, or budget restrictions. In an ideal world, training would be more engaging, current, and tailored to diverse experience levels. There were opportunities to improve on these dimensions.&lt;&#x2F;p&gt;
&lt;p&gt;Since there&#x27;s no escaping it, might as well make the most of it and stay in a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=m7XZyj6Ru9w&quot;&gt;good mood&lt;&#x2F;a&gt;. Let&#x27;s talk about what I wish the first day had covered and &lt;em&gt;how&lt;&#x2F;em&gt; it should have been covered.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aws&quot;&gt;AWS&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;&quot;&gt;Amazon Web Services (AWS)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is Amazon&#x27;s cloud computing platform, launched in 2006 with two initial services: &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;&quot;&gt;S3 (Simple Storage Service)&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ec2&#x2F;&quot;&gt;EC2 (Elastic Compute Cloud)&lt;&#x2F;a&gt;. The idea emerged from Amazon&#x27;s internal infrastructure challenges—they had built robust, scalable systems to handle their e-commerce peaks, and realized they could rent that infrastructure to others.&lt;&#x2F;p&gt;
&lt;p&gt;Today, AWS offers &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;products&#x2F;&quot;&gt;200+ services&lt;&#x2F;a&gt; spanning compute, storage, databases, machine learning, networking, and more. It holds roughly 31% of the global cloud market share (as of 2024), making it the largest cloud provider. &lt;em&gt;Phew&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In Africa, the &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;local&#x2F;africa&#x2F;cape-town&#x2F;&quot;&gt;Cape Town region (af-south-1)&lt;&#x2F;a&gt; was launched in 2020. It is AWS&#x27;s first and currently only African region. There&#x27;s no dedicated region yet for West Africa specifically. Users typically connect to eu-west-3 (Paris) or af-south-1 (Cape Town) depending on latency requirements.&lt;&#x2F;p&gt;
&lt;p&gt;AWS does also have :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;about-aws&#x2F;whats-new&#x2F;2023&#x2F;06&#x2F;aws-edge-location-nigeria&#x2F;&quot;&gt;Edge locations (CloudFront POPs) in Lagos and Nairobi&lt;&#x2F;a&gt; for content delivery.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;about-aws&#x2F;whats-new&#x2F;2025&#x2F;04&#x2F;aws-wavelength-zone-dakar&#x2F;&quot;&gt;Wavelength zone in Dakar Senegal&lt;&#x2F;a&gt;, a new type of infrastructure designed to run workloads that require low latency or edge resiliency.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;alternatives-the-hyperscalers&quot;&gt;Alternatives: the hyperscalers&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Hyperscalers&lt;&#x2F;strong&gt; are cloud providers operating at &lt;em&gt;massive&lt;&#x2F;em&gt; scale; we are talking about data centers across multiple continents, serving &lt;em&gt;millionZ&lt;&#x2F;em&gt; of customers simultaneously. The &lt;em&gt;&quot;Big 3&quot;&lt;&#x2F;em&gt; dominate the market:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Provider &lt;&#x2F;th&gt;&lt;th&gt;Share&lt;&#x2F;th&gt;&lt;th&gt;Strengths&lt;&#x2F;th&gt;&lt;th&gt;Best For&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;&quot;&gt;AWS&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~31%&lt;&#x2F;td&gt;&lt;td&gt;Widest service catalog, mature ecosystem&lt;&#x2F;td&gt;&lt;td&gt;General purpose, enterprise, startups&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;azure.microsoft.com&#x2F;&quot;&gt;Azure&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~24%&lt;&#x2F;td&gt;&lt;td&gt;Windows integration, hybrid cloud&lt;&#x2F;td&gt;&lt;td&gt;Microsoft shops, hybrid deployments&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;&quot;&gt;GCP&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~11%&lt;&#x2F;td&gt;&lt;td&gt;Data analytics, ML&#x2F;AI (TensorFlow), Kubernetes &lt;&#x2F;td&gt;&lt;td&gt;Data-heavy workloads, ML projects&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Notable alternatives:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;&quot;&gt;DigitalOcean&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;&quot;&gt;Linode&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;www.vultr.com&#x2F;&quot;&gt;Vultr&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Simpler, developer-friendly, cheaper for small workloads&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ovhcloud.com&#x2F;&quot;&gt;OVHcloud&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — European provider, good for GDPR compliance, competitive pricing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.scaleway.com&#x2F;&quot;&gt;Scaleway&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — French provider, strong EU presence, interesting ARM offerings&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.hetzner.com&#x2F;&quot;&gt;Hetzner&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — German provider, excellent price-to-performance ratio, popular for self-hosted projects&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The hyperscaler choice often comes down to existing tooling, team expertise, and specific service needs rather than raw capability. They all solve similar problems.&lt;&#x2F;p&gt;
&lt;p&gt;As an advocate for the &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;free-software-intro.en.html&quot;&gt;free software movement&lt;&#x2F;a&gt;, what is my advice ?&lt;&#x2F;p&gt;
&lt;p&gt;GCP: While proprietary, Google has historically &lt;a href=&quot;https:&#x2F;&#x2F;opensource.google&#x2F;projects&quot;&gt;opened up key technologies&lt;&#x2F;a&gt; such as Kubernetes and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&quot;&gt;many others&lt;&#x2F;a&gt; to promote interoperability and reduce vendor lock-in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;technologies&#x2F;cloud-computing&#x2F;openshift&quot;&gt;Red Hat OpenShift (on any cloud)&lt;&#x2F;a&gt;: Not a &lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;topics&#x2F;cloud-computing&#x2F;what-is-a-hyperscaler&quot;&gt;hyperscaler&lt;&#x2F;a&gt; per se, but using this platform on a cloud infrastructure allows you to maintain a free and portable software layer between different providers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-would-a-biomedical-research-center-use-aws&quot;&gt;Why would a biomedical research center use AWS ?&lt;&#x2F;h3&gt;
&lt;p&gt;For an organization handling sensitive health data and research workloads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compliance&lt;&#x2F;strong&gt;: HIPAA, GDPR-ready configurations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Burst capacity&lt;&#x2F;strong&gt;: spin up hundreds of CPUs for genomic analysis, pay only for what you use&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Global collaboration&lt;&#x2F;strong&gt;: share datasets across continents with proper access controls&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Focus on research&lt;&#x2F;strong&gt;: less time managing servers, more time on science&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#fundamentals&quot;&gt;Fundamentals&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#identity-and-access-management&quot;&gt;Identity and Access Management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#network&quot;&gt;Network&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;VPC basics (CIDR, Subnets)&lt;&#x2F;li&gt;
&lt;li&gt;Gateways (IGW, NAT)&lt;&#x2F;li&gt;
&lt;li&gt;Hybrid connectivity&lt;&#x2F;li&gt;
&lt;li&gt;Network Security&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#load-balancing&quot;&gt;Load Balancing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#compute-services&quot;&gt;Compute Services&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#storage&quot;&gt;Storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#observability&quot;&gt;Observability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aws-concepts-traditional-infrastructure&quot;&gt;AWS concepts → Traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been managing Linux servers, you already know most of these concepts. AWS just wraps them in managed services with different names:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;AWS Service&#x2F;Concept&lt;&#x2F;th&gt;&lt;th&gt;Traditional Equivalent&lt;&#x2F;th&gt;&lt;th&gt;What&#x27;s Different?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EC2&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Physical server, VM (KVM&#x2F;VMware)&lt;&#x2F;td&gt;&lt;td&gt;Rent by the hour, no hardware to buy&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VPC&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Network subnet, VLAN&lt;&#x2F;td&gt;&lt;td&gt;Software-defined, fully isolated per customer&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Security Groups&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt; rules (instance-level)&lt;&#x2F;td&gt;&lt;td&gt;Stateful, attached to network interfaces&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt; at router&#x2F;subnet level&lt;&#x2F;td&gt;&lt;td&gt;Stateless, numbered rules, processed in order&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;File server (NFS, Samba), MinIO&lt;&#x2F;td&gt;&lt;td&gt;Object storage (not filesystem), infinite scale, HTTP API&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EBS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hard drive, LVM volume&lt;&#x2F;td&gt;&lt;td&gt;Network-attached block storage, point-in-time snapshots&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EFS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;NFS share&lt;&#x2F;td&gt;&lt;td&gt;Managed NFS, auto-scaling, multi-AZ&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;RDS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;PostgreSQL server you installed&lt;&#x2F;td&gt;&lt;td&gt;AWS manages backups, patches, replication, HA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Load Balancer (ALB&#x2F;NLB)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Nginx, HAProxy, Apache &lt;code&gt;mod_proxy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Fully managed, auto-scales, integrated health checks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Auto Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Custom bash scripts watching &lt;code&gt;top&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Automatic instance scaling based on CloudWatch metrics&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;passwd&lt;&#x2F;code&gt;, &lt;code&gt;sudo&lt;&#x2F;code&gt;, LDAP&#x2F;Active Directory&lt;&#x2F;td&gt;&lt;td&gt;Controls AWS API access, not just OS users&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IAM Roles&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Service accounts, &lt;code&gt;systemd&lt;&#x2F;code&gt; user credentials&lt;&#x2F;td&gt;&lt;td&gt;Temporary credentials that auto-rotate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Metrics&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Prometheus, Nagios, Zabbix, Grafana&lt;&#x2F;td&gt;&lt;td&gt;Pre-integrated with all AWS services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Logs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;syslog&lt;&#x2F;code&gt;, &lt;code&gt;journald&lt;&#x2F;code&gt;, ELK stack&lt;&#x2F;td&gt;&lt;td&gt;Centralized log aggregation, SQL-like queries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Alarms&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Nagios alerts, &lt;code&gt;monit&lt;&#x2F;code&gt;, custom scripts&lt;&#x2F;td&gt;&lt;td&gt;Trigger actions (scaling, notifications, Lambda)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudTrail&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;var&#x2F;log&#x2F;audit&#x2F;audit.log&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Every AWS API call logged (who did what, when)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Lambda&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Cron jobs + shell scripts&lt;&#x2F;td&gt;&lt;td&gt;Event-driven functions, no server to manage&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Route 53&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;BIND, &lt;code&gt;dnsmasq&lt;&#x2F;code&gt;, PowerDNS&lt;&#x2F;td&gt;&lt;td&gt;Managed DNS with health checks and routing policies&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Regions&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Multiple data center locations&lt;&#x2F;td&gt;&lt;td&gt;Completely isolated, compliance&#x2F;data residency boundaries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Availability Zones&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Separate racks&#x2F;power&#x2F;networking in same DC&lt;&#x2F;td&gt;&lt;td&gt;Physical separation within region, low-latency links&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: You give up control (can&#x27;t SSH into the Load Balancer) in exchange for less maintenance (AWS patches it for you). Whether that&#x27;s worth it depends on your team size, expertise, and what you&#x27;re trying to build. And if you understood everything inside the table above, you can stop here, I&#x27;m serious :\&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;want-to-know-more-okay&quot;&gt;Want to know more ? Okay&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;fundamentals&quot;&gt;Fundamentals&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;global-infrastructure&#x2F;latest&#x2F;regions&#x2F;aws-regions.html&quot;&gt;Regions&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are geographically isolated clusters of data centers. Each region (e.g., &lt;code&gt;eu-west-3&lt;&#x2F;code&gt; for Paris, &lt;code&gt;us-east-1&lt;&#x2F;code&gt; for N. Virginia) operates independently. You choose a region based on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;&#x2F;strong&gt; — closer to your users = faster response&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compliance&lt;&#x2F;strong&gt; — data residency laws may require specific locations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Service availability&lt;&#x2F;strong&gt; — not all services exist in all regions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt; — costs vary by region&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;global-infrastructure&#x2F;latest&#x2F;regions&#x2F;aws-availability-zones.html&quot;&gt;Availability Zones (AZs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are physically separate data centers within a region, connected by low-latency links. Deploying across multiple Zones provides fault tolerance: if one data center fails, your application survives.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_introduction.html&quot;&gt;Organizations&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is a service designed for central governance and management of multiple AWS accounts. They are useful for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Isolating environments (dev&#x2F;staging&#x2F;prod)&lt;&#x2F;li&gt;
&lt;li&gt;Separating billing by department or project&lt;&#x2F;li&gt;
&lt;li&gt;Applying security policies across accounts&lt;&#x2F;li&gt;
&lt;li&gt;Consolidated billing with volume discounts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;identity-and-access-management&quot;&gt;Identity and Access Management&lt;&#x2F;h3&gt;
&lt;p&gt;Before you start spinning up resources, you need to understand &lt;strong&gt;who can do what&lt;&#x2F;strong&gt; in your AWS account. This is where &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;introduction.html&quot;&gt;IAM (Identity and Access Management)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; comes in.&lt;&#x2F;p&gt;
&lt;p&gt;IAM is AWS&#x27;s authentication and authorization service. It controls who can access your AWS resources and what actions they can perform. Get this wrong, and you&#x27;ll either lock yourself out or leave your infrastructure wide open to attackers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Core IAM concepts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;th&gt;When to Use&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_users.html&quot;&gt;Users&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Individual identities with permanent credentials&lt;&#x2F;td&gt;&lt;td&gt;Human access via Console&#x2F;CLI&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_groups.html&quot;&gt;Groups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Collections of users with shared permissions&lt;&#x2F;td&gt;&lt;td&gt;Organizing users by function (developers, ops, analysts)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles.html&quot;&gt;Roles&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Temporary credentials that can be assumed&lt;&#x2F;td&gt;&lt;td&gt;Services, applications, cross-account access&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html&quot;&gt;Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;JSON documents defining permissions&lt;&#x2F;td&gt;&lt;td&gt;Attach to users, groups, or roles&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html&quot;&gt;IAM Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are JSON documents that specify allowed or denied actions. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&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:#d69d85;&quot;&gt;&amp;quot;Statement&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:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&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:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&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:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::my-research-data&#x2F;*&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This policy allows reading objects from a specific S3 bucket, nothing more. That&#x27;s the &lt;strong&gt;principle of least privilege&lt;&#x2F;strong&gt;: grant only the minimum permissions needed to do the job.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why roles matter more than you think:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The biggest mistake beginners make is hardcoding AWS credentials in their applications. I should be honest with you here, yes I&#x27;ve done it when I was younger. But today, please, I&#x27;m telling you, don&#x27;t do this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example scenario&lt;&#x2F;strong&gt;: Your EC2 instance needs to read files from S3.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Wrong approach&lt;&#x2F;strong&gt;: Store AWS access keys in a config file on the instance.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Keys can be stolen if the instance is compromised&lt;&#x2F;li&gt;
&lt;li&gt;Keys don&#x27;t rotate automatically&lt;&#x2F;li&gt;
&lt;li&gt;Difficult to audit who used which credentials&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Right approach&lt;&#x2F;strong&gt;: Attach an IAM role with S3 read permissions to the EC2 instance.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No credentials stored anywhere&lt;&#x2F;li&gt;
&lt;li&gt;Temporary credentials rotate automatically&lt;&#x2F;li&gt;
&lt;li&gt;CloudTrail logs show exactly which instance accessed which resources&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Root account protection:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When you create an AWS account, you get a root user with unlimited access. This is dangerous. Best practices:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable MFA&lt;&#x2F;strong&gt; (Multi-Factor Authentication) on the root account&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Create IAM users&lt;&#x2F;strong&gt; for daily work, even for administrators&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lock away root credentials&lt;&#x2F;strong&gt; - only use them for tasks that &lt;em&gt;require&lt;&#x2F;em&gt; root (billing, account closure)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_manage_policies_scps.html&quot;&gt;AWS Organizations and Service Control Policies (SCPs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; add another layer: they set permission boundaries across multiple accounts. Even if an IAM policy allows an action, an SCP can block it at the organization level. Useful for enforcing compliance (e.g., &quot;no one can launch instances outside eu-west-3&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;In the biomedical research context:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;d use IAM to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Give researchers read-only access to specific S3 buckets containing datasets&lt;&#x2F;li&gt;
&lt;li&gt;Allow the data engineering team to manage ETL pipelines (write access to certain resources)&lt;&#x2F;li&gt;
&lt;li&gt;Grant your analysis scripts (running on EC2&#x2F;Lambda) temporary credentials to access databases&lt;&#x2F;li&gt;
&lt;li&gt;Prevent anyone from accidentally exposing patient data by restricting public S3 bucket creation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Security Groups (covered below) control &lt;em&gt;network&lt;&#x2F;em&gt; access. IAM controls &lt;em&gt;identity and authorization&lt;&#x2F;em&gt;. You need both.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network&quot;&gt;Network&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Maybe I did need this class after all. I&#x27;m having flashbacks... crimping tool... crossover cable... straight cable... cat5.... class C... IPV6... Layer 3... Layer 4....&lt;&#x2F;em&gt; Heeelp! \o&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;what-is-amazon-vpc.html&quot;&gt;VPC (Virtual Private Cloud)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is your isolated network within AWS. With a VPC you define:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;what-is&#x2F;cidr&#x2F;&quot;&gt;CIDR block&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: your IP range (e.g., &lt;code&gt;10.0.0.0&#x2F;16&lt;&#x2F;code&gt; gives you 65,536 IPs)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;configure-subnets.html&quot;&gt;Subnets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: subdivisions of your VPC, placed in specific Zones
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Public subnets&lt;&#x2F;em&gt;: resources can have public IPs, direct internet access&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Private subnets&lt;&#x2F;em&gt;: no direct internet access, only internal communication&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Gateways:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;VPC_Internet_Gateway.html&quot;&gt;Internet Gateway (IGW)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: enables internet access for public subnets. Attach one to your VPC, add routes, done.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-nat-gateway.html&quot;&gt;NAT Gateway&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: lets private subnet resources reach the internet (for updates, API calls) without being directly reachable..&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Hybrid connectivity:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpn&#x2F;latest&#x2F;s2svpn&#x2F;VPC_VPN.html&quot;&gt;Site-to-Site VPN&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: encrypted tunnel between your on-premises network and AWS VPC. Quick to set up, uses public internet, variable latency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;directconnect&#x2F;latest&#x2F;UserGuide&#x2F;Welcome.html&quot;&gt;AWS Direct Connect&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: dedicated physical connection to AWS. Consistent latency, higher bandwidth, but requires physical setup and contracts. Useful for heavy data transfer or strict latency requirements.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network Security:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;AWS provides two complementary layers of network security: &lt;strong&gt;Security Groups&lt;&#x2F;strong&gt; and &lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt;. Understanding when to use each is critical.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-security-groups.html&quot;&gt;Security Groups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are stateful firewalls attached to resources (EC2 instances, RDS databases, etc.). They act like bouncers at the door of individual servers. Define allowed inbound&#x2F;outbound traffic by port, protocol, and source. If you allow inbound traffic on port 80, the return traffic is automatically allowed—that&#x27;s what &quot;stateful&quot; means.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-network-acls.html&quot;&gt;Network ACLs (NACLs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are stateless firewalls at the subnet level. They filter traffic entering or leaving entire subnets. Rules are evaluated in numerical order (100, 200, 300...), and the first match wins. Unlike Security Groups, NACLs require explicit rules for both inbound and outbound traffic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Security Groups vs. Network ACLs:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;Security Groups&lt;&#x2F;th&gt;&lt;th&gt;Network ACLs&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Instance level (attached to ENI)&lt;&#x2F;td&gt;&lt;td&gt;Subnet level&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;State&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Stateful (return traffic auto-allowed)&lt;&#x2F;td&gt;&lt;td&gt;Stateless (must allow both directions)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Rules&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Only Allow rules&lt;&#x2F;td&gt;&lt;td&gt;Allow + Deny rules&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Evaluation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;All rules evaluated&lt;&#x2F;td&gt;&lt;td&gt;Processed in order, first match wins&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Default behavior&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Deny all inbound, allow all outbound&lt;&#x2F;td&gt;&lt;td&gt;Allow everything&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Typical use&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Your primary security control&lt;&#x2F;td&gt;&lt;td&gt;Edge cases, compliance, IP blocking&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Security Groups&lt;&#x2F;strong&gt; should be your default choice for 95% of scenarios:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Allow SSH (port 22) only from your office IP&lt;&#x2F;li&gt;
&lt;li&gt;Let web servers accept HTTP&#x2F;HTTPS from anywhere&lt;&#x2F;li&gt;
&lt;li&gt;Allow database connections only from application servers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt; are for specific edge cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Block a known malicious IP range at the subnet boundary&lt;&#x2F;li&gt;
&lt;li&gt;Compliance requirements mandating subnet-level controls&lt;&#x2F;li&gt;
&lt;li&gt;Defense-in-depth: add a second layer of protection&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Example scenario - Blocking an attacking IP:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Your web servers (in a public subnet) are under attack from &lt;code&gt;203.0.113.0&#x2F;24&lt;&#x2F;code&gt;. Security Groups can only &lt;em&gt;allow&lt;&#x2F;em&gt; traffic, not deny it. Solution: add a NACL rule.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;NACL Inbound Rules (evaluated in order):
&lt;&#x2F;span&gt;&lt;span&gt;Rule 100: DENY   TCP   80   from 203.0.113.0&#x2F;24   (block attackers)
&lt;&#x2F;span&gt;&lt;span&gt;Rule 200: ALLOW  TCP   80   from 0.0.0.0&#x2F;0        (allow everyone else)
&lt;&#x2F;span&gt;&lt;span&gt;Rule *:   DENY   ALL   ALL  from 0.0.0.0&#x2F;0        (default deny)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because NACLs are stateless, you also need outbound rules for responses:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;NACL Outbound Rules:
&lt;&#x2F;span&gt;&lt;span&gt;Rule 100: ALLOW  TCP  1024-65535  to 0.0.0.0&#x2F;0   (ephemeral ports)
&lt;&#x2F;span&gt;&lt;span&gt;Rule *:   DENY   ALL  ALL         to 0.0.0.0&#x2F;0    (default deny)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;1024-65535&lt;&#x2F;code&gt; range covers ephemeral ports used by client connections. Yes, this is annoying. This is why most people stick to Security Groups.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;&#x2F;strong&gt; The default NACL in your VPC allows all traffic. Most AWS users never modify it. Only touch NACLs when you have &lt;em&gt;3&lt;&#x2F;em&gt; specific reasons.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;flow-logs.html&quot;&gt;Flow Logs&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Capture network traffic metadata (source&#x2F;destination IP, port, protocol, action) for debugging and audit. Essential for troubleshooting connectivity issues and security investigations. Send logs to CloudWatch or S3 for analysis.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;load-balancing&quot;&gt;Load Balancing&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;High Availability&lt;&#x2F;strong&gt; means your application stays up even when parts of the infrastructure fail. In AWS, this typically involves deploying across multiple Availability Zones and using load balancers to distribute traffic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;elasticloadbalancing&#x2F;&quot;&gt;Elastic Load Balancing (ELB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; automatically distributes incoming traffic across multiple targets. AWS offers several types:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Layer&lt;&#x2F;th&gt;&lt;th&gt;Best For&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;application&#x2F;introduction.html&quot;&gt;Application Load Balancer (ALB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 7 (HTTP&#x2F;HTTPS)&lt;&#x2F;td&gt;&lt;td&gt;Web apps, microservices, content-based routing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;network&#x2F;introduction.html&quot;&gt;Network Load Balancer (NLB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 4 (TCP&#x2F;UDP)&lt;&#x2F;td&gt;&lt;td&gt;Ultra-low latency, millions of requests&#x2F;sec&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;gateway&#x2F;introduction.html&quot;&gt;Gateway Load Balancer&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 3&lt;&#x2F;td&gt;&lt;td&gt;Third-party virtual appliances (firewalls, IDS)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;autoscaling&#x2F;ec2&#x2F;userguide&#x2F;what-is-amazon-ec2-auto-scaling.html&quot;&gt;Auto Scaling&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; automatically adjusts the number of EC2 instances based on demand:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduled scaling&lt;&#x2F;strong&gt;: scale at predictable times (e.g., business hours)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic scaling&lt;&#x2F;strong&gt;: react to CloudWatch metrics (CPU, memory, custom metrics)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Predictive scaling&lt;&#x2F;strong&gt;: ML-based forecasting of future demand&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Multi-AZ resilience&lt;&#x2F;strong&gt;: Deploy instances across multiple AZs, place a load balancer in front, and Auto Scaling replaces failed instances automatically. This is the foundation of most production architectures on AWS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compute-services&quot;&gt;Compute Services&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Compute&lt;&#x2F;strong&gt; refers to the processing power needed to run applications. AWS offers several options depending on your level of control vs. convenience:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ec2&#x2F;&quot;&gt;EC2 (Elastic Compute Cloud)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Virtual machines you fully control. Choose your OS, instance type (CPU&#x2F;RAM), and storage. Pricing models:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;th&gt;Savings&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;On-Demand&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pay by the hour&#x2F;second, no commitment&lt;&#x2F;td&gt;&lt;td&gt;Baseline pricing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Reserved&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;1 or 3-year commitment for steady workloads&lt;&#x2F;td&gt;&lt;td&gt;Up to 72% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Spot&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Bid on unused capacity, can be interrupted&lt;&#x2F;td&gt;&lt;td&gt;Up to 90% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Savings Plans&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Flexible commitment across instance families&lt;&#x2F;td&gt;&lt;td&gt;Up to 72% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Container services&lt;&#x2F;strong&gt; — For containerized workloads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonECS&#x2F;latest&#x2F;developerguide&#x2F;Welcome.html&quot;&gt;ECS (Elastic Container Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: AWS-native container orchestration. Simpler than Kubernetes, tightly integrated with AWS.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;what-is-eks.html&quot;&gt;EKS (Elastic Kubernetes Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Managed Kubernetes. Use this if you need Kubernetes compatibility or already use K8s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;fargate&#x2F;&quot;&gt;Fargate&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Serverless compute for containers. No EC2 instances to manage—just define CPU&#x2F;memory and run your containers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;EC2: Full control needed, legacy apps, specific OS requirements&lt;&#x2F;li&gt;
&lt;li&gt;ECS + Fargate: Simple containerized apps, AWS-native approach&lt;&#x2F;li&gt;
&lt;li&gt;EKS: Kubernetes expertise on the team, multi-cloud portability needed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-computing.jpg&quot; alt=&quot;Cloud computing&quot; title=&quot;Cloud computing&quot;&#x2F;&gt;
&lt;h3 id=&quot;storage&quot;&gt;Storage&lt;&#x2F;h3&gt;
&lt;p&gt;AWS offers different storage types for different use cases:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;&quot;&gt;Amazon S3&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Object storage for any type of data. Highly durable (11 nines), infinitely scalable. &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;storage-classes&#x2F;&quot;&gt;Storage classes&lt;&#x2F;a&gt; optimize cost based on access patterns:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Class&lt;&#x2F;th&gt;&lt;th&gt;Access Pattern&lt;&#x2F;th&gt;&lt;th&gt;Retrieval&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Standard&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Frequent access&lt;&#x2F;td&gt;&lt;td&gt;Instant&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Intelligent-Tiering&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Unknown&#x2F;changing patterns&lt;&#x2F;td&gt;&lt;td&gt;Instant (auto-moves data)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Standard-IA&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Infrequent access&lt;&#x2F;td&gt;&lt;td&gt;Instant&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;storage-classes&#x2F;glacier&#x2F;&quot;&gt;S3 Glacier Instant&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Archive, rare access&lt;&#x2F;td&gt;&lt;td&gt;Milliseconds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Glacier Flexible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Archive&lt;&#x2F;td&gt;&lt;td&gt;Minutes to hours&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Glacier Deep Archive&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Long-term archive&lt;&#x2F;td&gt;&lt;td&gt;12-48 hours&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Lifecycle policies&lt;&#x2F;strong&gt; automatically transition objects between classes or delete them after a period.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Block vs. File storage:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ebs&#x2F;&quot;&gt;EBS (Elastic Block Store)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Block storage attached to a single EC2 instance. Think: hard drive for your VM. Great for databases.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;efs&#x2F;&quot;&gt;EFS (Elastic File System)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Shared file system mountable by multiple EC2 instances. Think: NFS. Great for shared application data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Databases:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;Welcome.html&quot;&gt;Amazon RDS (Relational Database Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Managed relational databases for PostgreSQL, &lt;em&gt;(and other database providers I won&#x27;t talk about because I am a free software advocate)&lt;&#x2F;em&gt;. AWS handles the operational heavy lifting: backups, patching, OS updates, and replication. You focus on schema design and queries.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;High Availability and scaling options:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Understanding the difference between &lt;strong&gt;Multi-AZ&lt;&#x2F;strong&gt; and &lt;strong&gt;Read Replicas&lt;&#x2F;strong&gt; is critical:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;Multi-AZ&lt;&#x2F;th&gt;&lt;th&gt;Read Replicas&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purpose&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;High availability (failover)&lt;&#x2F;td&gt;&lt;td&gt;Read scaling, analytics&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Replication&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Synchronous (to standby in another AZ)&lt;&#x2F;td&gt;&lt;td&gt;Asynchronous (can lag slightly)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Failover&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Automatic (1-2 minutes)&lt;&#x2F;td&gt;&lt;td&gt;Manual promotion required&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Readable&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Standby is not accessible&lt;&#x2F;td&gt;&lt;td&gt;Yes, handle read traffic&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use case&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Production databases requiring uptime&lt;&#x2F;td&gt;&lt;td&gt;Distribute read load, reporting queries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~2x (paying for standby)&lt;&#x2F;td&gt;&lt;td&gt;Additional instance cost per replica&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Multi-AZ deployment&lt;&#x2F;strong&gt;: Your primary database synchronously replicates to a standby instance in a different Availability Zone. If the primary fails (hardware issue, AZ outage), RDS automatically fails over to the standby. Your application reconnects to the same endpoint—no code changes needed. This is for &lt;strong&gt;disaster recovery&lt;&#x2F;strong&gt;, not performance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Read Replicas&lt;&#x2F;strong&gt;: Create up to 15 read-only copies of your database. Use them to offload read traffic (analytics, reporting) from the primary. Replication is asynchronous, so there may be a slight lag (usually milliseconds to seconds). You can promote a replica to primary if needed, but it&#x27;s a manual operation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;rds&#x2F;aurora&#x2F;&quot;&gt;Amazon Aurora&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — AWS&#x27;s proprietary database engine, PostgreSQL compatible:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;&#x2F;strong&gt;: Up to 3x faster than PostgreSQL (according to AWS benchmarks)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Storage auto-scaling&lt;&#x2F;strong&gt;: Starts at 10GB, grows automatically up to 128TB in 10GB increments&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;High availability built-in&lt;&#x2F;strong&gt;: Data replicated 6 ways across 3 AZs automatically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Read scaling&lt;&#x2F;strong&gt;: Up to 15 Aurora Replicas with sub-10ms replica lag&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;: More expensive than standard RDS, but better price-to-performance for demanding workloads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cloudzero.com&#x2F;blog&#x2F;aurora-vs-rds&#x2F;&quot;&gt;Aurora&lt;&#x2F;a&gt; is AWS&#x27;s recommended choice for new applications that need high performance and availability.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Backup Strategies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;RDS provides two backup mechanisms:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;USER_WorkingWithAutomatedBackups.html&quot;&gt;Automated backups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enabled by default&lt;&#x2F;li&gt;
&lt;li&gt;Point-in-time recovery: restore your database to any second within the retention period (1-35 days)&lt;&#x2F;li&gt;
&lt;li&gt;Full daily backups + transaction logs&lt;&#x2F;li&gt;
&lt;li&gt;Deleted when you delete the RDS instance (unless you configure a final snapshot)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;USER_CreateSnapshot.html&quot;&gt;Manual snapshots&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;User-initiated, persist until you explicitly delete them&lt;&#x2F;li&gt;
&lt;li&gt;Useful before major changes (schema migrations, upgrades)&lt;&#x2F;li&gt;
&lt;li&gt;Can be copied across regions for disaster recovery&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;&#x2F;strong&gt;: Before any risky operation (major version upgrade, schema change), create a manual snapshot. Automated backups might not cover you if the retention period expires.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;RDS vs. NoSQL:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not all data fits the relational model. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;amazondynamodb&#x2F;latest&#x2F;developerguide&#x2F;Introduction.html&quot;&gt;Amazon DynamoDB&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is AWS&#x27;s managed NoSQL database (key-value and document store):&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;RDS (SQL)&lt;&#x2F;th&gt;&lt;th&gt;DynamoDB (NoSQL)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Data model&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Tables with fixed schema, relations&lt;&#x2F;td&gt;&lt;td&gt;Key-value &#x2F; JSON documents, flexible schema&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Queries&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complex SQL (JOINs, aggregations)&lt;&#x2F;td&gt;&lt;td&gt;Simple key lookups, limited querying&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Vertical (bigger instance), Read Replicas&lt;&#x2F;td&gt;&lt;td&gt;Horizontal (automatic), virtually unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Transactions&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Full ACID support&lt;&#x2F;td&gt;&lt;td&gt;Limited transactions (single-item ACID, multi-item with conditions)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complex queries, reporting, traditional apps&lt;&#x2F;td&gt;&lt;td&gt;High-throughput simple queries, IoT, gaming, mobile backends&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pay for instance size (even if idle)&lt;&#x2F;td&gt;&lt;td&gt;Pay for storage + read&#x2F;write capacity used&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RDS&lt;&#x2F;strong&gt;: You need SQL, complex queries, transactions, existing relational schema, or you&#x27;re migrating from on-premises MySQL&#x2F;PostgreSQL&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;DynamoDB&lt;&#x2F;strong&gt;: Key-value access patterns, need massive scale, unpredictable traffic spikes, single-digit millisecond latency requirements&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Most traditional applications (e-commerce, ERP, content management) use RDS. DynamoDB shines for high-scale, low-latency use cases where you don&#x27;t need complex querying.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-storage.jpg&quot; alt=&quot;cloud storage&quot; title=&quot;cloud storage&quot;&#x2F;&gt;
&lt;h3 id=&quot;observability&quot;&gt;Observability&lt;&#x2F;h3&gt;
&lt;p&gt;Observability = understanding what&#x27;s happening inside your systems. AWS provides &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;WhatIsCloudWatch.html&quot;&gt;Amazon CloudWatch&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; as the central service for this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;working_with_metrics.html&quot;&gt;Metrics&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Numerical data points over time. AWS services automatically send metrics (CPU usage, network traffic, request counts). You can also publish custom metrics from your applications.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;logs&#x2F;WhatIsCloudWatchLogs.html&quot;&gt;Logs&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Centralized log storage and analysis. Stream logs from EC2, Lambda, containers, or any application. Use &lt;strong&gt;Log Insights&lt;&#x2F;strong&gt; to query across log groups with a SQL-like syntax.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;AlarmThatSendsEmail.html&quot;&gt;Alarms&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Watch metrics and trigger actions when thresholds are breached:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Send notifications via SNS (email, SMS, Slack)&lt;&#x2F;li&gt;
&lt;li&gt;Trigger Auto Scaling to add&#x2F;remove instances&lt;&#x2F;li&gt;
&lt;li&gt;Execute Lambda functions for custom remediation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Example alarm&lt;&#x2F;strong&gt;: &quot;If average CPU &amp;gt; 80% for 5 minutes, add 2 instances and notify the ops team.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Beyond CloudWatch:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;xray&#x2F;&quot;&gt;AWS X-Ray&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Distributed tracing for microservices&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cloudtrail&#x2F;&quot;&gt;CloudTrail&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Audit log of all API calls in your account&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-observability.jpg&quot; alt=&quot;cloud observability&quot; title=&quot;cloud observability&quot;&#x2F;&gt;
&lt;br&gt;
&lt;h2 id=&quot;one-picture-is-worth-thousand-words&quot;&gt;One picture is worth thousand words&lt;&#x2F;h2&gt;


&lt;div class=&quot;aws-diagram-wrapper&quot;&gt;
    &lt;style&gt;
        .aws-diagram-wrapper {
            --aws-bg: #0d1117;
            --aws-bg-secondary: #161b22;
            --aws-bg-tertiary: #21262d;
            --aws-border: #30363d;
            --aws-text: #e6edf3;
            --aws-text-muted: #8b949e;
            --aws-orange: #ff9900;
            --aws-green: #238636;
            --aws-blue: #1f6feb;
            --aws-blue-light: #388bfd;
            --aws-purple: #a371f7;
            --aws-yellow: #f0883e;

            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--aws-bg);
            color: var(--aws-text);
            padding: 40px 20px;
            border-radius: 8px;
            margin: 30px 0;
        }

        .aws-diagram-wrapper * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .aws-diagram-wrapper h1 {
            font-size: 1.6rem;
            font-weight: 600;
            margin-bottom: 8px;
            color: var(--aws-orange);
        }

        .aws-diagram-wrapper .subtitle {
            color: var(--aws-text-muted);
            font-size: 0.9rem;
            margin-bottom: 40px;
        }

        .aws-diagram-wrapper .diagram-container {
            position: relative;
            background: linear-gradient(180deg, var(--aws-bg-secondary) 0%, var(--aws-bg) 100%);
            border: 1px solid var(--aws-border);
            border-radius: 8px;
            padding: 30px;
            overflow-x: auto;
        }

        .aws-diagram-wrapper .diagram {
            display: flex;
            flex-direction: column;
            gap: 16px;
            min-width: 1100px;
        }

        .aws-diagram-wrapper .zone {
            border: 2px dashed var(--aws-border);
            border-radius: 8px;
            padding: 20px;
            position: relative;
        }

        .aws-diagram-wrapper .zone-label {
            position: absolute;
            top: -10px;
            left: 20px;
            background: var(--aws-bg);
            padding: 2px 12px;
            font-size: 0.7rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 1px;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .zone.internet {
            border-color: var(--aws-green);
            background: rgba(35, 134, 54, 0.05);
        }

        .aws-diagram-wrapper .zone.vpc {
            border-color: var(--aws-blue);
            background: rgba(31, 111, 235, 0.03);
        }

        .aws-diagram-wrapper .zone.public-subnet {
            border-color: var(--aws-yellow);
            background: rgba(240, 136, 62, 0.05);
        }

        .aws-diagram-wrapper .zone.private-subnet {
            border-color: var(--aws-purple);
            background: rgba(163, 113, 247, 0.05);
        }

        .aws-diagram-wrapper .zone.az {
            border-color: var(--aws-blue-light);
            border-style: dotted;
            background: rgba(56, 139, 253, 0.03);
        }

        .aws-diagram-wrapper .row {
            display: flex;
            gap: 20px;
            align-items: flex-start;
        }

        .aws-diagram-wrapper .component {
            background: var(--aws-bg-tertiary);
            border: 1px solid var(--aws-border);
            border-radius: 6px;
            padding: 14px 18px;
            min-width: 130px;
            text-align: center;
            position: relative;
            transition: all 0.2s ease;
            cursor: pointer;
        }

        .aws-diagram-wrapper .component:hover {
            border-color: var(--aws-orange);
            transform: translateY(-2px);
            box-shadow: 0 4px 20px rgba(255, 153, 0, 0.15);
        }

        .aws-diagram-wrapper .component.active {
            border-color: var(--aws-orange);
            background: #2d333b;
        }

        .aws-diagram-wrapper .component-name {
            font-weight: 600;
            font-size: 0.85rem;
            margin-bottom: 6px;
            color: var(--aws-text);
        }

        .aws-diagram-wrapper .component-type {
            font-family: &#x27;JetBrains Mono&#x27;, &#x27;Fira Code&#x27;, monospace;
            font-size: 0.65rem;
            color: var(--aws-orange);
            background: rgba(255, 153, 0, 0.1);
            padding: 3px 8px;
            border-radius: 3px;
            display: inline-block;
        }

        .aws-diagram-wrapper .arrow-container {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 8px 0;
        }

        .aws-diagram-wrapper .arrow {
            display: flex;
            align-items: center;
            gap: 8px;
            color: #6e7681;
            font-size: 0.7rem;
            font-family: &#x27;JetBrains Mono&#x27;, monospace;
        }

        .aws-diagram-wrapper .arrow-line {
            width: 50px;
            height: 2px;
            background: linear-gradient(90deg, var(--aws-border) 0%, var(--aws-orange) 50%, var(--aws-border) 100%);
            position: relative;
        }

        .aws-diagram-wrapper .arrow-line::after {
            content: &#x27;&gt;&#x27;;
            position: absolute;
            right: -6px;
            top: -7px;
            color: var(--aws-orange);
            font-size: 0.7rem;
            font-weight: bold;
        }

        .aws-diagram-wrapper .arrow-down {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .aws-diagram-wrapper .arrow-down .arrow-line {
            width: 2px;
            height: 30px;
            background: linear-gradient(180deg, var(--aws-border) 0%, var(--aws-orange) 50%, var(--aws-border) 100%);
        }

        .aws-diagram-wrapper .arrow-down .arrow-line::after {
            content: &#x27;v&#x27;;
            right: -5px;
            top: auto;
            bottom: -10px;
            font-size: 0.6rem;
        }

        .aws-diagram-wrapper .flex-center {
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .aws-diagram-wrapper .flex-between {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
        }

        .aws-diagram-wrapper .flex-col {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
        }

        .aws-diagram-wrapper .info-panel {
            margin-top: 30px;
            background: var(--aws-bg-secondary);
            border: 1px solid var(--aws-border);
            border-radius: 8px;
            padding: 24px;
            min-height: 180px;
        }

        .aws-diagram-wrapper .info-panel h3 {
            font-size: 1rem;
            color: var(--aws-orange);
            margin-bottom: 12px;
        }

        .aws-diagram-wrapper .info-panel .description {
            color: var(--aws-text-muted);
            line-height: 1.7;
            margin-bottom: 16px;
            font-size: 0.9rem;
        }

        .aws-diagram-wrapper .info-panel .analogy {
            background: var(--aws-bg-tertiary);
            border-left: 3px solid var(--aws-green);
            padding: 12px 16px;
            border-radius: 0 6px 6px 0;
            margin-bottom: 16px;
        }

        .aws-diagram-wrapper .info-panel .analogy-label {
            font-size: 0.65rem;
            text-transform: uppercase;
            letter-spacing: 1px;
            color: var(--aws-green);
            margin-bottom: 6px;
        }

        .aws-diagram-wrapper .info-panel .analogy p {
            font-size: 0.85rem;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .info-panel .code {
            font-family: &#x27;JetBrains Mono&#x27;, &#x27;Fira Code&#x27;, monospace;
            font-size: 0.75rem;
            background: var(--aws-bg);
            padding: 12px 16px;
            border-radius: 6px;
            color: #79c0ff;
            overflow-x: auto;
            line-height: 1.5;
        }

        .aws-diagram-wrapper .storage-section {
            display: flex;
            gap: 20px;
            margin-top: 16px;
        }

        .aws-diagram-wrapper .storage-group {
            flex: 1;
            background: var(--aws-bg-secondary);
            border: 1px solid var(--aws-border);
            border-radius: 6px;
            padding: 16px;
        }

        .aws-diagram-wrapper .storage-group h4 {
            font-size: 0.75rem;
            color: var(--aws-text-muted);
            margin-bottom: 12px;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .aws-diagram-wrapper .storage-items {
            display: flex;
            gap: 12px;
            flex-wrap: wrap;
        }

        .aws-diagram-wrapper .legend {
            display: flex;
            gap: 24px;
            flex-wrap: wrap;
            margin-top: 20px;
            padding: 14px;
            background: var(--aws-bg-secondary);
            border-radius: 6px;
        }

        .aws-diagram-wrapper .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.75rem;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .legend-color {
            width: 14px;
            height: 14px;
            border-radius: 3px;
            border: 2px dashed;
        }

        .aws-diagram-wrapper .legend-color.internet { border-color: var(--aws-green); background: rgba(35, 134, 54, 0.2); }
        .aws-diagram-wrapper .legend-color.vpc { border-color: var(--aws-blue); background: rgba(31, 111, 235, 0.2); }
        .aws-diagram-wrapper .legend-color.public { border-color: var(--aws-yellow); background: rgba(240, 136, 62, 0.2); }
        .aws-diagram-wrapper .legend-color.private { border-color: var(--aws-purple); background: rgba(163, 113, 247, 0.2); }

        .aws-diagram-wrapper .click-hint {
            text-align: center;
            color: #6e7681;
            font-size: 0.75rem;
            margin-top: 14px;
        }

        .aws-diagram-wrapper .or-divider {
            font-size: 0.65rem;
            color: #6e7681;
            font-style: italic;
        }
    &lt;&#x2F;style&gt;

    &lt;h1&gt;AWS Architecture - Overview&lt;&#x2F;h1&gt;
    &lt;p class=&quot;subtitle&quot;&gt;Click on a component to see details and analogy with your current stack&lt;&#x2F;p&gt;

    &lt;div class=&quot;diagram-container&quot;&gt;
        &lt;div class=&quot;diagram&quot;&gt;

            &lt;!-- Internet Zone --&gt;
            &lt;div class=&quot;zone internet&quot;&gt;
                &lt;span class=&quot;zone-label&quot;&gt;Internet&lt;&#x2F;span&gt;
                &lt;div class=&quot;flex-center&quot;&gt;
                    &lt;div class=&quot;component&quot; data-component=&quot;users&quot;&gt;
                        &lt;div class=&quot;component-name&quot;&gt;Users&lt;&#x2F;div&gt;
                        &lt;div class=&quot;component-type&quot;&gt;Front &amp; mobile Apps&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;arrow&quot;&gt;
                        &lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;
                        &lt;span&gt;HTTPS&lt;&#x2F;span&gt;
                        &lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;component&quot; data-component=&quot;route53&quot;&gt;
                        &lt;div class=&quot;component-name&quot;&gt;Route 53&lt;&#x2F;div&gt;
                        &lt;div class=&quot;component-type&quot;&gt;DNS&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;!-- VPC --&gt;
            &lt;div class=&quot;zone vpc&quot;&gt;
                &lt;span class=&quot;zone-label&quot;&gt;VPC (10.0.0.0&#x2F;16)&lt;&#x2F;span&gt;

                &lt;div class=&quot;flex-between&quot; style=&quot;gap: 20px;&quot;&gt;

                    &lt;!-- AZ 1 --&gt;
                    &lt;div class=&quot;zone az&quot; style=&quot;flex: 1;&quot;&gt;
                        &lt;span class=&quot;zone-label&quot;&gt;AZ-1 (eu-west-3a)&lt;&#x2F;span&gt;

                        &lt;!-- Public Subnet AZ1 --&gt;
                        &lt;div class=&quot;zone public-subnet&quot; style=&quot;margin-bottom: 15px;&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Public Subnet (10.0.1.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;igw&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Internet Gateway&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;IGW&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;arrow-down&quot;&gt;&lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;alb&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Load Balancer&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;ALB &#x2F; NLB&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;nat&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;NAT Gateway&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;NAT&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;

                        &lt;!-- Private Subnet AZ1 --&gt;
                        &lt;div class=&quot;zone private-subnet&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Private Subnet (10.0.10.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ec2&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;EC2 Instance&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;t3.medium&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;or-divider&quot;&gt;or&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ecs&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;ECS &#x2F; Fargate&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;Container&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;

                    &lt;!-- AZ 2 --&gt;
                    &lt;div class=&quot;zone az&quot; style=&quot;flex: 1;&quot;&gt;
                        &lt;span class=&quot;zone-label&quot;&gt;AZ-2 (eu-west-3b)&lt;&#x2F;span&gt;

                        &lt;!-- Public Subnet AZ2 --&gt;
                        &lt;div class=&quot;zone public-subnet&quot; style=&quot;margin-bottom: 15px;&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Public Subnet (10.0.2.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;alb&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Load Balancer&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;ALB (replica)&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;

                        &lt;!-- Private Subnet AZ2 --&gt;
                        &lt;div class=&quot;zone private-subnet&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Private Subnet (10.0.20.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ec2&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;EC2 Instance&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;t3.medium&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;arrow-down&quot;&gt;&lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;rds&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;RDS PostgreSQL&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;Multi-AZ&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;!-- Storage &amp; Monitoring --&gt;
            &lt;div class=&quot;storage-section&quot;&gt;
                &lt;div class=&quot;storage-group&quot;&gt;
                    &lt;h4&gt;Storage&lt;&#x2F;h4&gt;
                    &lt;div class=&quot;storage-items&quot;&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;s3&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;S3 Bucket&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Object Storage&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;ebs&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;EBS Volume&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Block Storage&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;efs&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;EFS&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;File System&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;storage-group&quot;&gt;
                    &lt;h4&gt;Monitoring and Streaming&lt;&#x2F;h4&gt;
                    &lt;div class=&quot;storage-items&quot;&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;cloudwatch&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;CloudWatch&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Monitoring&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;msk&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;MSK (Kafka)&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Streaming&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Legend --&gt;
    &lt;div class=&quot;legend&quot;&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color internet&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Internet (public access)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color vpc&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;VPC (your private network)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color public&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Public Subnet (exposed)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color private&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Private Subnet (protected)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;p class=&quot;click-hint&quot;&gt;Click on a component to see details&lt;&#x2F;p&gt;

    &lt;!-- Info Panel --&gt;
    &lt;div class=&quot;info-panel&quot; id=&quot;aws-info-panel&quot;&gt;
        &lt;h3&gt;Select a component&lt;&#x2F;h3&gt;
        &lt;p class=&quot;description&quot;&gt;
            Click on any element of the diagram to see a detailed explanation
            and the equivalent in your current environment (Nginx, Django, PostgreSQL...).
        &lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const componentInfo = {
        users: {
            title: &quot;Users &#x2F; Clients&quot;,
            description: &quot;The users who access your applications from the Internet. This could be health workers using our &lt;a href=&#x27;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&#x27;&gt;syndromic surveillance system&lt;&#x2F;a&gt;.&quot;,
            analogy: &quot;It&#x27;s the same as now - your users typing the URL in their browser or systems calling your REST API.&quot;,
            code: &quot;curl https:&#x2F;&#x2F;surveillance.pasteur.sn&#x2F;api&#x2F;v1&#x2F;cases&#x2F;&quot;
        },
        route53: {
            title: &quot;Route 53 - DNS Service&quot;,
            description: &quot;AWS&#x27;s managed DNS service. It translates domain names (surveillance.pasteur.sn) into IP addresses. Can perform health checking and intelligent routing (geolocation, failover).&quot;,
            analogy: &quot;Equivalent to your current DNS (maybe managed by your registrar or Cloudflare). The difference: Route 53 integrates natively with other AWS services.&quot;,
            code: &quot;# Example record&lt;br&gt;surveillance.pasteur.sn  A  -&gt; ALB (alias)&quot;
        },
        igw: {
            title: &quot;Internet Gateway (IGW)&quot;,
            description: &quot;The gateway in and out of your VPC to the Internet. Without IGW, nothing in your VPC can communicate with the outside world. There is ONE per VPC.&quot;,
            analogy: &quot;It&#x27;s like the router&#x2F;firewall of your datacenter that connects your internal network to the Internet. Like your platform&#x27;s main gateway.&quot;,
            code: &quot;# One VPC = One IGW&lt;br&gt;aws ec2 create-internet-gateway&quot;
        },
        alb: {
            title: &quot;Application Load Balancer (ALB &#x2F; NLB)&quot;,
            description: &quot;Distributes traffic between multiple instances. ALB = Layer 7 (HTTP), understands URLs and can route &#x2F;api to one group, &#x2F;admin to another. NLB = Layer 4 (TCP), faster but less intelligent.&quot;,
            analogy: &quot;It&#x27;s your Nginx in reverse proxy mode, but managed and automatically scalable. No need to manage the nginx.conf file anymore!&quot;,
            code: &quot;# Nginx equivalent&lt;br&gt;upstream django {&lt;br&gt;    server 10.0.10.5:8000;&lt;br&gt;    server 10.0.20.5:8000;&lt;br&gt;}&lt;br&gt;location &#x2F; {&lt;br&gt;    proxy_pass http:&#x2F;&#x2F;django;&lt;br&gt;}&quot;
        },
        nat: {
            title: &quot;NAT Gateway&quot;,
            description: &quot;Allows resources in a PRIVATE subnet to access the Internet (for updates, external APIs) WITHOUT being accessible from the Internet. Outgoing traffic goes through NAT, but no incoming traffic is possible.&quot;,
            analogy: &quot;Like when your Django server (behind a firewall) can do &#x27;pip install&#x27; or call the Africa&#x27;s Talking API, but no one can access that server directly from the Internet.&quot;,
            code: &quot;# From your private EC2, this works:&lt;br&gt;curl https:&#x2F;&#x2F;api.africastalking.com&#x2F;send&lt;br&gt;&lt;br&gt;# But from the Internet, impossible to reach the EC2&quot;
        },
        ec2: {
            title: &quot;EC2 - Elastic Compute Cloud&quot;,
            description: &quot;Virtual machines. You choose the type (t3.medium = 2 vCPU, 4 GB RAM), the OS (Ubuntu, Amazon Linux), and you pay per hour. On Demand = flexible, Reserved = -60%, Spot = -90% but interruptible.&quot;,
            analogy: &quot;It&#x27;s exactly like your current VPS or physical servers, but elastic. You can create 10 in 2 minutes, and delete them afterwards.&quot;,
            code: &quot;# Equivalent to your current server&lt;br&gt;Ubuntu 22.04&lt;br&gt;2 vCPU, 4 GB RAM&lt;br&gt;Django + Gunicorn + your code&quot;
        },
        ecs: {
            title: &quot;ECS &#x2F; EKS &#x2F; Fargate - Containers&quot;,
            description: &quot;ECS = AWS container orchestrator. EKS = Managed Kubernetes. Fargate = serverless (no servers to manage). You package your Django in a Docker image, and AWS handles the rest.&quot;,
            analogy: &quot;If you&#x27;re using Docker now with docker-compose, ECS is the same but in production and scalable. No need to SSH into the server to do &#x27;docker pull&#x27;.&quot;,
            code: &quot;# Dockerfile&lt;br&gt;FROM python:3.11&lt;br&gt;COPY . &#x2F;app&lt;br&gt;RUN pip install -r requirements.txt&lt;br&gt;CMD [\&quot;gunicorn\&quot;, \&quot;config.wsgi:application\&quot;]&quot;
        },
        rds: {
            title: &quot;RDS - Relational Database Service&quot;,
            description: &quot;Managed databases (PostgreSQL, MySQL, etc.). AWS handles automatic backups, security patches, Multi-AZ replication. You focus on your queries, not maintenance.&quot;,
            analogy: &quot;It&#x27;s your current PostgreSQL, but you no longer have to worry about pg_dump, version upgrades, or replication. AWS does everything.&quot;,
            code: &quot;# Django settings.py&lt;br&gt;DATABASES = {&lt;br&gt;    &#x27;default&#x27;: {&lt;br&gt;        &#x27;ENGINE&#x27;: &#x27;django.db.backends.postgresql&#x27;,&lt;br&gt;        &#x27;HOST&#x27;: &#x27;mydb.xxxxx.eu-west-3.rds.amazonaws.com&#x27;,&lt;br&gt;        &#x27;NAME&#x27;: &#x27;surveillance_db&#x27;,&lt;br&gt;    }&lt;br&gt;}&quot;
        },
        s3: {
            title: &quot;S3 - Simple Storage Service&quot;,
            description: &quot;Unlimited object storage. Perfect for static files, backups, media uploads. Not a classic file system (no mkdir), but &#x27;buckets&#x27; and &#x27;objects&#x27; with URLs.&quot;,
            analogy: &quot;Replaces your &#x2F;var&#x2F;www&#x2F;media&#x2F; folder for Django uploads. No more disk space issues, and your files are accessible via URL directly.&quot;,
            code: &quot;# Django settings with django-storages&lt;br&gt;DEFAULT_FILE_STORAGE = &#x27;storages.backends.s3boto3.S3Boto3Storage&#x27;&lt;br&gt;AWS_STORAGE_BUCKET_NAME = &#x27;ipd-surveillance-media&#x27;&quot;
        },
        ebs: {
            title: &quot;EBS - Elastic Block Store&quot;,
            description: &quot;Virtual hard drives attached to an EC2 instance. Like your server&#x27;s SSD. Persistent (data remains even if EC2 is stopped). Different types: gp3 (general), io2 (high perf), st1 (cheap HDD).&quot;,
            analogy: &quot;It&#x27;s exactly your current server&#x27;s hard drive. &#x2F;dev&#x2F;sda1 but in the cloud. If your EC2 dies, you can attach the EBS to a new instance.&quot;,
            code: &quot;# On your EC2&lt;br&gt;df -h&lt;br&gt;&#x2F;dev&#x2F;nvme0n1p1  100G   45G   55G  45% &#x2F;&quot;
        },
        efs: {
            title: &quot;EFS - Elastic File System&quot;,
            description: &quot;File system shared between MULTIPLE EC2 instances. Like a NAS. Useful when multiple servers need to access the same files (ex: shared uploads, common source code).&quot;,
            analogy: &quot;Like an NFS share between your servers. If you have 3 Django instances that all need to see the same uploaded files, EFS solves this problem.&quot;,
            code: &quot;# Mounted on multiple EC2&lt;br&gt;mount -t nfs4 fs-xxxxx.efs.eu-west-3.amazonaws.com:&#x2F; &#x2F;mnt&#x2F;shared&quot;
        },
        cloudwatch: {
            title: &quot;CloudWatch - Monitoring&quot;,
            description: &quot;Collects metrics (CPU, RAM, requests), centralizes logs, and triggers alerts. Built-in dashboard. Can trigger automatic actions (ex: scale up if CPU &gt; 80%).&quot;,
            analogy: &quot;Combines htop + tail -f &#x2F;var&#x2F;log + your alert system. But everything is centralized and you can create visual dashboards.&quot;,
            code: &quot;# Alert example&lt;br&gt;If CPUUtilization &gt; 80% for 5 min&lt;br&gt;-&gt; Send email to ops@pasteur.sn&lt;br&gt;-&gt; Add 2 instances to Auto Scaling Group&quot;
        },
        msk: {
            title: &quot;MSK - Managed Streaming for Kafka&quot;,
            description: &quot;Apache Kafka managed by AWS. For real-time data streaming, data pipelines, or event-driven architecture. Useful for processing millions of events per second.&quot;,
            analogy: &quot;Imagine each suspected case report generates an &#x27;event&#x27; that must be processed in real-time to trigger epidemiological alerts. Kafka enables this continuous flow of data.&quot;,
            code: &quot;# Producer (notification system)&lt;br&gt;producer.send(&#x27;alerts-topic&#x27;, {&lt;br&gt;    &#x27;type&#x27;: &#x27;suspected_case&#x27;,&lt;br&gt;    &#x27;disease&#x27;: &#x27;cholera&#x27;,&lt;br&gt;    &#x27;location&#x27;: &#x27;dakar&#x27;,&lt;br&gt;    &#x27;timestamp&#x27;: &#x27;2025-01-31T10:30:00Z&#x27;&lt;br&gt;})&quot;
        }
    };

    const wrapper = document.querySelector(&#x27;.aws-diagram-wrapper&#x27;);
    const panel = wrapper.querySelector(&#x27;#aws-info-panel&#x27;);

    wrapper.querySelectorAll(&#x27;.component&#x27;).forEach(comp =&gt; {
        comp.addEventListener(&#x27;click&#x27;, function() {
            const componentId = this.dataset.component;
            const info = componentInfo[componentId];

            if (info) {
                wrapper.querySelectorAll(&#x27;.component&#x27;).forEach(c =&gt; c.classList.remove(&#x27;active&#x27;));
                wrapper.querySelectorAll(`[data-component=&quot;${componentId}&quot;]`).forEach(c =&gt; c.classList.add(&#x27;active&#x27;));

                panel.innerHTML = `
                    &lt;h3&gt;${info.title}&lt;&#x2F;h3&gt;
                    &lt;p class=&quot;description&quot;&gt;${info.description}&lt;&#x2F;p&gt;
                    &lt;div class=&quot;analogy&quot;&gt;
                        &lt;div class=&quot;analogy-label&quot;&gt;Equivalent dans ton stack actuel&lt;&#x2F;div&gt;
                        &lt;p&gt;${info.analogy}&lt;&#x2F;p&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;code&quot;&gt;${info.code.replace(&#x2F;\n&#x2F;g, &#x27;&lt;br&gt;&#x27;)}&lt;&#x2F;div&gt;
                `;
            }
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;how-to-practice&quot;&gt;How to practice&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need a corporate account to learn AWS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;free&#x2F;&quot;&gt;AWS Free Tier&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: The real AWS, free for 12 months (with limits). Great for hands-on experience with actual services.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;localstack.cloud&#x2F;&quot;&gt;LocalStack&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: AWS emulator running on your laptop. Spin up S3, Lambda, DynamoDB locally. No cloud costs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;minikube.sigs.k8s.io&#x2F;&quot;&gt;Minikube&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;&quot;&gt;Kind&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Local Kubernetes clusters for learning EKS concepts.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k3s.io&#x2F;&quot;&gt;K3s&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;k3d.io&#x2F;&quot;&gt;K3d&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Lightweight Kubernetes distributions, perfect for development and edge deployments.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.podman.io&#x2F;en&#x2F;latest&#x2F;markdown&#x2F;podman-compose.1.html&quot;&gt;Podman Compose&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Simulate architectures with containers (PostgreSQL, Redis, Nginx). Understand the concepts before going managed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The key insight is this: everything you&#x27;ve been doing manually for years, fingers in the nose, eyes closed (configuring Nginx, Gunicorn, PostgreSQL, managing users, monitoring logs), AWS offers it as managed services. You&#x27;re trading full control for less maintenance.&lt;&#x2F;p&gt;
&lt;p&gt;Is that trade-off worth it? It depends. For a small team that needs to move fast and can&#x27;t afford dedicated ops, managed services make sense. For organizations with specific compliance needs or those who want to avoid vendor lock-in, the calculus changes.&lt;&#x2F;p&gt;
&lt;p&gt;Either way, understanding these concepts matters, whether you end up using AWS, another cloud, or staying on-premises.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;there_is_no_cloud.png&quot; alt=&quot;There is no cloud&quot; title=&quot;There is no cloud&quot;&#x2F;&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations, you made it to the end. I hope you learned something, if you enjoyed this piece, you can read my post about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;how I&#x27;m helping save lives in West Africa using free software&lt;&#x2F;a&gt;, or you can &lt;em&gt;like, share and subscribe; it helps fight the algorithm.&lt;&#x2F;em&gt; Here are some links you may find interesing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=uaflChh3n1A&quot;&gt;Introduction to AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;908&#x2F;&quot;&gt;The Cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MQbkN99eBD8&quot;&gt;Why is Kubernetes everywhere?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;basecamp.com&#x2F;cloud-exit&quot;&gt;We left the cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=vBjonut1JMk&quot;&gt;How Kubernetes is built&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tCehFMwjWqM&quot;&gt;AI won&#x27;t take your job (but this will)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=CjKhQoYeR4Q&quot;&gt;Getting started with AWS, step by step guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Syndromic Surveillance! (Part 1)</title>
        <published>2025-08-24T00:00:00+00:00</published>
        <updated>2025-08-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/syndromic-surveillance/"/>
        <id>https://nskm.xyz/posts/syndromic-surveillance/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/syndromic-surveillance/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;surveillance_screens.jpg&quot; alt=&quot;&quot; title=&quot;Liberty&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#hook&quot;&gt;Hook&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#history&quot;&gt;Definition, context, history&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#what&quot;&gt;4S overview&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#core&quot;&gt;Core principles&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#collect&quot;&gt;Data collection&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#process&quot;&gt;Data processing and storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#share&quot;&gt;Data sharing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#alert&quot;&gt;Alerting and notifications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#integration&quot;&gt;Integration with existing systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#stack&quot;&gt;The technological stack&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#front&quot;&gt;Frontend&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#back&quot;&gt;Backend&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#else&quot;&gt;More&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#engineers&quot;&gt;The engineering team&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#future&quot;&gt;The roadmap&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#more&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;&lt;u&gt;Hook:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;From &lt;strong&gt;June 30 to July 2, 2025&lt;&#x2F;strong&gt;, a coordination meeting for the entire 4S network was recently held in &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lom%C3%A9&quot;&gt;Lomé, Togo&lt;&#x2F;a&gt;. During this meeting, a new implementation of the &lt;strong&gt;4S platform&lt;&#x2F;strong&gt; was presented to the participants.&lt;&#x2F;p&gt;
&lt;video style=&quot;display: block; margin: 0 auto; width: 600px&quot; class=&quot;video&quot; controls=&quot;controls&quot; &gt;
  &lt;source  src=&quot;&#x2F;images&#x2F;4s-annual-regional-coordination-meeting.mp4&quot; type=&quot;video&#x2F;mp4&quot; &#x2F;&gt;
  Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Quote:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Le réseau 4S a été conçu pour répondre à un besoin crucial, celui de disposer d&#x27;un système régional de surveillance capable de détecter précocément les maladies de santé publique, de renforcer les capacités de laboratoires et de partager des données pour une réponse adéquate et adaptée aux problèmes sanitaires.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Quote :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The 4S network was designed to meet a crucial need: to have a regional surveillance system capable of early detection of public health diseases, strengthening laboratory capacities and sharing data for an adequate and appropriate response to health issues.
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The striking disconnect that exists across many sectors, public health included. Officials excel at announcing initiatives and securing funding. Press releases about &lt;em&gt;&quot;implementing advanced early detection systems&quot;&lt;&#x2F;em&gt; generate buzz and demonstrate progress. But when it comes to the unglamorous technical work: database design, API development, system integration... Silence. These crucial implementation details, handled by &lt;em&gt;anonymous engineers and developers&lt;&#x2F;em&gt;, rarely see daylight in public discourse.&lt;&#x2F;p&gt;
&lt;p&gt;While policy makers avoid technical specifics, it&#x27;s precisely these software choices that determine whether systems function during critical moments.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;mother.jpg&quot; alt=&quot;Mother&quot; title=&quot;Mother&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;history&quot;&gt;&lt;u&gt;Definition, context, history:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A syndromic surveillance system is a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Y6DPDC_Mf90&quot;&gt;public health&lt;&#x2F;a&gt; &lt;strong&gt;surveillance&lt;&#x2F;strong&gt; system that monitors &lt;strong&gt;symptom clusters&lt;&#x2F;strong&gt; rather than specific confirmed diagnoses. It aims to &lt;strong&gt;detect epidemics or public health events&lt;&#x2F;strong&gt; at an &lt;strong&gt;early&lt;&#x2F;strong&gt; stage, by analyzing data in real time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2007&quot;&gt;2007:&lt;&#x2F;h3&gt;
&lt;p&gt;Before 2007, &lt;a href=&quot;https:&#x2F;&#x2F;simple.wikipedia.org&#x2F;wiki&#x2F;Madagascar&quot;&gt;Madagascar&lt;&#x2F;a&gt; only had a passive, monthly paper-based reporting system that was &lt;em&gt;&lt;strong&gt;too slow&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; for outbreak response. The &lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pubmed.ncbi.nlm.nih.gov&#x2F;17505252&#x2F;&quot;&gt;chikungunya outbreak&lt;&#x2F;a&gt;&lt;&#x2F;em&gt; in the Indian Ocean exposed &lt;em&gt;&lt;strong&gt;critical gaps&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; in Madagascar&#x27;s disease surveillance.&lt;&#x2F;p&gt;
&lt;p&gt;The solution was to setup a real-time sentinel surveillance system using mobile phones for daily data transmission. This implementation was &lt;em&gt;&lt;strong&gt;the first nationwide real-time-like&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pdfs.semanticscholar.org&#x2F;66b8&#x2F;8be85954b548c3b744ffd7ea8bac7ccae008.pdf&quot;&gt;surveillance system&lt;&#x2F;a&gt; ever established in Madagascar.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2012&quot;&gt;2012:&lt;&#x2F;h3&gt;
&lt;p&gt;The Syndromic Sentinel Surveillance System in Senegal, the 4S network, is &lt;a href=&quot;https:&#x2F;&#x2F;rh.pasteur.sn&#x2F;en&#x2F;research-and-public-health&#x2F;epidemiology-clinical-research-and-data-science&#x2F;fever-surveillance-syndromic-sentinel-surveillance-senegal-4s-network&quot;&gt;Another syndromic sentinel surveillance system&lt;&#x2F;a&gt; based on febrile syndromes. It was implemented in Senegal in 2012 and inpired by the Madagascar model.&lt;&#x2F;p&gt;
&lt;p&gt;The criteria of individual target diseases are based on &lt;a href=&quot;https:&#x2F;&#x2F;www.who.int&#x2F;publications&#x2F;i&#x2F;item&#x2F;who-recommended-surveillance-standards&quot;&gt;World Health Organization recommended surveillance standards&lt;&#x2F;a&gt;. This means: for &lt;em&gt;each disease&lt;&#x2F;em&gt; or &lt;em&gt;syndrome&lt;&#x2F;em&gt; there is a description of the &lt;em&gt;rationale for surveillance, case definition, types of surveillance, minimum data elements, data analyses and principal uses of data for decision-making.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Data are transmitted on a daily basis by the general practitioners of the sentinel sites. They are validated and analyzed daily within the epidemiology unit of the Institution. These data are sent to the Ministry of Health in the form of a weekly newsletter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2015&quot;&gt;2015:&lt;&#x2F;h3&gt;
&lt;p&gt;The existing implementation faced significant challenges. The database consisted of scattered Excel files distributed across multiple locations, making studies and analyses complicated and time-consuming. There was an urgent need to organize, structure, and centralize these disparate files.&lt;&#x2F;p&gt;
&lt;p&gt;To address these issues, a new platform was developed: Teranga. Built using &lt;a href=&quot;https:&#x2F;&#x2F;httpd.apache.org&#x2F;&quot;&gt;Apache&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.php.net&#x2F;&quot;&gt;PHP&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&quot;&gt;Javascript&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.mysql.com&#x2F;products&#x2F;community&#x2F;&quot;&gt;MySQL&lt;&#x2F;a&gt;, Teranga provides improved data management, enhanced tracking capabilities, modular architecture, and streamlined deployment during outbreak situations.&lt;&#x2F;p&gt;
&lt;p&gt;The new sentinel surveillance system included 17 health centers and &lt;a href=&quot;https:&#x2F;&#x2F;www.omicsonline.org&#x2F;proceedings&#x2F;early-outbreak-detection-through-sentinel-surveillance-system-in-senegal-51640.html&quot;&gt;identified 4 confirmed outbreaks&lt;&#x2F;a&gt;. The system has proved the feasibility of improving disease surveillance capacity through innovative technological solutions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020&quot;&gt;2020:&lt;&#x2F;h3&gt;
&lt;p&gt;When &lt;a href=&quot;https:&#x2F;&#x2F;www.cdc.gov&#x2F;covid&#x2F;about&#x2F;index.html&quot;&gt;COVID-19&lt;&#x2F;a&gt; struck, Teranga rose to meet an unprecedented challenge, becoming the backbone of Senegal&#x27;s pandemic response. Seamlessly coordinating patient care, traveler monitoring, financial operations, clinical research, and treatment center management across the entire country. The pandemic trully elevated Teranga to a mission-critical status.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2022&quot;&gt;2022:&lt;&#x2F;h3&gt;
&lt;p&gt;What began as a surveillance system for on institution, evolved to become West Africa indispensable healthcare hub: The 4S network. Teranga is now expanding from Senegal into other West African countries: Gambia, Cape-Verde, Mauritania, Niger, Mali, Togo, Guinea, Guinea Bissau, Sierra-Leone and Benin. The goal being to provide broader coverage and improve health systems in a sustainable and effective manner.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2023&quot;&gt;2023:&lt;&#x2F;h3&gt;
&lt;p&gt;I am hired by the Institution. I&#x27;m tasked with reimplementing the current system, rebuilding it from scratch while improving on what came before. I don&#x27;t have much say in the tech stack, just enough &lt;em&gt;freedom&lt;&#x2F;em&gt; to go with what works for &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;toolbelt&#x2F;&quot;&gt;me&lt;&#x2F;a&gt;. The usual lineup of &lt;a href=&quot;https:&#x2F;&#x2F;www.debian.org&#x2F;&quot;&gt;Debian&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;&quot;&gt;Python&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;Postgresql&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.nginx.org&#x2F;&quot;&gt;Nginx&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;podman.io&quot;&gt;Podman&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;Git&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;Emacs&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tmuxcheatsheet.com&#x2F;&quot;&gt;Tmux&lt;&#x2F;a&gt;, etc ... More on that in the following episodes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2025&quot;&gt;2025:&lt;&#x2F;h3&gt;
&lt;p&gt;The surveillance platform my colleagues and I have spent two years developing has now been presented to the public. But public recognition &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;vLK4Mq3jiKIAAAAC&#x2F;tenor.gif&quot;&gt;is not really the source of my pride&lt;&#x2F;a&gt;. What matters is that our system, our algorithms, our data structures, our functions, our for loops, our SQL queries are actively making a difference in saving lives. Phew!&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;wip.jpg&quot; alt=&quot;Work in progress&quot; title=&quot;Work in progress...&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;what&quot;&gt;&lt;u&gt;4S overview:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;identify unusual health events earlier and provide a quicker response.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I can&#x27;t say it better.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;core&quot;&gt;Core principles:&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s really fascinating that these early systems already recognized the core principles we are trying to implement today:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;collect&quot;&gt;1. Standardized data collection:&lt;&#x2F;h4&gt;
&lt;p&gt;Healthcare providers at sentinel sites should use standardized digital forms to capture essential demographic, clinical, and temporal information. We want to ensure consistency across all participating facilities and enable accurate epidemiological analysis. We should always try to adhere to WHO surveillance standards with clearly predefined entities &amp;amp; attributes.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;process&quot;&gt;2. Data processing and storage:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should handles real-time data streaming between microservices, enabling immediate processing of incoming surveillance data. Each microservice should ensures data integrity through automated validation rules. We should always check for completeness, consistency, and quality. Validated data should be stored in a database with proper indexing for efficient retrieval.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;share&quot;&gt;3. Information sharing:&lt;&#x2F;h4&gt;
&lt;p&gt;The epidemiology unit generates documents consolidating validated surveillance data for the Ministry of Health. The platform integrates with third parties to share aggregated data with the Ministry of Health. The platform also provides interactive dashboards for stakeholders.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;alert&quot;&gt;4. Alerting and notifications:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should ensure immediate notification delivery to relevant actor via email and dashboard notifications. Whenever needed, the platform should automatically generates notifications through multiple channels—email alerts, in-app notifications, and dashboard warnings.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;integration&quot;&gt;5. Integration with existing systems:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should seamlessly integrate with the regional health data aggregation system and any other existing platform used by Ministry of Health. The system must also integrate easily with any biobank systems that may exist.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A drawing is worth more than thousand words:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                                        [Health facility]   [Hospital]         [Clinic]
&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;                                         |              4S platform                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data collection (Patients, symptoms, ...)  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data validation &amp;amp; storage                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data treatment (Analyses, studies, ...)    |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data sharing (Reports, alerts, ...)        |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data dashboards (Statistics, plots, ...)   |
&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;                                         | Reports |              |        | Alerts  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         |Analytics|              |        |Warnings |
&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;                                        | Public Health |   | Research |    | Emergency |
&lt;&#x2F;span&gt;&lt;span&gt;                                        |   Department  |   |          |    | Response  |
&lt;&#x2F;span&gt;&lt;span&gt;                                        +---------------+   +----------+    +-----------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the platform we are trying to build :) I can stop the post here, thanks for reading ...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stack&quot;&gt;The technological stack:&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;front&quot;&gt;Frontend:&lt;&#x2F;h4&gt;
&lt;p&gt;The 4S platform frontend leverages &lt;a href=&quot;https:&#x2F;&#x2F;angularjs.dev&#x2F;&quot;&gt;AngularJS&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;&quot;&gt;TypeScript&lt;&#x2F;a&gt;, providing a dynamic and type-safe user interface that ensures smooth interactions for healthcare providers.&lt;&#x2F;p&gt;
&lt;p&gt;One of the main component of our architecture is &lt;a href=&quot;https:&#x2F;&#x2F;www.keycloak.org&#x2F;&quot;&gt;Keycloak&lt;&#x2F;a&gt;, an identity &amp;amp; access management solution that handles user authentication, authorization accross the entire platform. Customizing the Django Rest Framework&#x27;s authentication classes to handle different tokens sent by different realms was an adventure worthy of an article.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;back&quot;&gt;Backend:&lt;&#x2F;h4&gt;
&lt;p&gt;The backend infrastructure centers around &lt;a href=&quot;https:&#x2F;&#x2F;python.org&quot;&gt;Python&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;djangoproject.com&quot;&gt;Django&lt;&#x2F;a&gt;, and Django Rest Framework. With each passing day, as we make progress on the project, I become more and more convinced that it was the right choice. Django is an amazing piece of software, thanks a lot to all its contributors.&lt;&#x2F;p&gt;
&lt;p&gt;Data management is handled by &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&quot;&gt;PostgreSQL&lt;&#x2F;a&gt;, our primary database system. I can proudly say that I&#x27;m the one who made this choice. Postgresql is known for its reliability, strong adherence to SQL standards, powerful extensibility, support for complex data types, ACID compliance, robust security features, and excellent community support.&lt;&#x2F;p&gt;
&lt;p&gt;To handle real-time communication and event-driven processes such as email notifications, lab result updates, and system alerts, we&#x27;ve integrated &lt;a href=&quot;https:&#x2F;&#x2F;kafka.apache.org&#x2F;&quot;&gt;Apache Kafka&lt;&#x2F;a&gt;. Kafka ensures that critical healthcare information flows efficiently between different system components without data loss.&lt;&#x2F;p&gt;
&lt;p&gt;In order to detect outbreaks, samples (blood, urine, stool, etc.) must be collected. And to effectively manage vast biological sample collections, ensure data integrity, and streamline complex workflows, we need a Biobank and a Biobanking software. A biobank is essentially an organized library of biological samples (like blood and tissue) that are stored alongside health and personal information, all used to support medical research. &lt;a href=&quot;https:&#x2F;&#x2F;www.modul-bio.com&#x2F;en&#x2F;our-solutions&#x2F;mbiolims&#x2F;&quot;&gt;Mbiolims&lt;&#x2F;a&gt; is the biobanking software we use to manage our samples and their associated data.&lt;&#x2F;p&gt;
&lt;p&gt;Here too, I would need to write a really long article telling you how we&#x27;ve managed to do the integration between Django and MBioLIMS :) Hehe!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ops&quot;&gt;Operations:&lt;&#x2F;h4&gt;
&lt;p&gt;All code versioning and collaboration is managed through &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&quot;&gt;Git&lt;&#x2F;a&gt; &amp;amp; Bitbucket, ensuring secure source code management, proper access controls and audit trails. While Bitbucket provides comprehensive version control and collaboration features, I&#x27;m still convinced it was not the right choice. &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt; ? &lt;a href=&quot;https:&#x2F;&#x2F;about.gitea.com&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt; ? Github ? Come on!&lt;&#x2F;p&gt;
&lt;p&gt;The 4S platform is in fact a constallation of multiple running containers. Those containers are built using Docker and &lt;a href=&quot;https:&#x2F;&#x2F;podman.io&quot;&gt;Podman&lt;&#x2F;a&gt; technologies, enabling consistent deployment across different environments while simplifying development and testing workflows. I mean, I&#x27;m the only one using Podman while all my teammates are still using Docker :\&lt;&#x2F;p&gt;
&lt;p&gt;Our continuous integration and deployment pipeline is powered by Jenkins. Jenkins automates testing and deployment processes to maintain code quality and enable rapid, reliable updates. I prefer &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ci&#x2F;&quot;&gt;GitlabCI&lt;&#x2F;a&gt; by 13 parsecs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes&lt;&#x2F;a&gt; is used for container orchestration, deployment and operations. K8s provides automatic scaling, load balancing, and high availability to ensure our platform can handle varying loads and maintain uptime. My opinions on this tool are mixed.&lt;&#x2F;p&gt;
&lt;p&gt;In one side, K8s will allow us to easily scale our applications up or down based on demand. This is a critical requirement for managing sensitive healthcare information. In the other side, I live in a part of the world where most medical facilities (most people, let&#x27;s be honest) do not even have a working domain name, website, and email address. How can we ask them for the DevOps expertise to manage a Kubernetes cluster? I will see to what extent I can write an article about Kubernetes.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;else&quot;&gt;Even more:&lt;&#x2F;h4&gt;
&lt;p&gt;There are other essential components of the system which I am not really familiar with.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dhis2.org&#x2F;&quot;&gt;DHIS2&lt;&#x2F;a&gt; is widely adopted across West Africa for integrated health information systems, disease surveillance, education management, and public health emergency response. We simply cannot ask a country that already uses DHIS2 to use the 4S platform without it being able to transfer data back to a DHIS2 instance.&lt;&#x2F;p&gt;
&lt;p&gt;We have an &lt;a href=&quot;https:&#x2F;&#x2F;superset.apache.org&#x2F;&quot;&gt;Apache Superset&lt;&#x2F;a&gt; instance for data visualization and exploration. With Apache Superset, we can easily let a third party consult some information, without modifying our system.&lt;&#x2F;p&gt;
&lt;p&gt;Our platform generate lots of files, analysis reports &amp;amp; statistics. We needed something to store vast amounts of unstructured data, like images, videos, pdf documents, etc... We choosed &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;minio&#x2F;minio&quot;&gt;MinIO&lt;&#x2F;a&gt; for this use case.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;The diagram we&#x27;ve seen above can also be seen using this different perspective:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;    +-----------------------------------------------------------------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |                                                      KUBERNETES CLUSTER                                               |
&lt;&#x2F;span&gt;&lt;span&gt;    +-----------------------------------------------------------------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |                                                                                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +--------------------------------------------------+   &amp;lt;-- (Auth&#x2F;Roles) --&amp;gt;  +------------------+                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |             FRONTEND CLIENTS                     |------------------------&amp;gt;|     KEYCLOAK     |                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |          (AngularJS + TypeScript)                |&amp;lt;------------------------|   (Auth Server   |                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +------------------^-------------------------------+                         +-----^------------+                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                               |                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |              (API Requests)                                                         | (Auth&#x2F;Roles)                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                          +----+                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                          |                                      |
&lt;&#x2F;span&gt;&lt;span&gt;    +---------------------v----------------------------------------------------------v--------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |  +--------------------------------------------------------------------------------+      +--------------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |                BACKEND MICROSERVICES (Django Rest Framework)                   |      |    Biobank (Mbiolims)    | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |      Microservices exchanges data via a message broker (Kafka in our case)     |&amp;lt;----&amp;gt;|   Stores Samples infos   | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |   [Microservice A]  &amp;lt;--Data--&amp;gt;  [Microservice B] &amp;lt;--Data--&amp;gt; [Microservice N-1] |      |                          | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +-------------------------^-----------------------^-------------------------^----+      +--------------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;    |                            |                       |                         |                                        |
&lt;&#x2F;span&gt;&lt;span&gt;    |              (Store&#x2F;Retrieve)       (Write&#x2F;Open Files)      (Sends data aggregations)                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |                            |                       |                         |                                        |
&lt;&#x2F;span&gt;&lt;span&gt;    +----------------------------v-----------------------v-------------------------v----------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    | +--------------------------------+ +--------------------------------+ +--------------------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |        POSTGRESQL DB           | |             MINIO              | |                   DHIS2                    |  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |     (Primary Data Store)       | |      (Object&#x2F;File Storage)     | |           (External Data Recipient)        |  |
&lt;&#x2F;span&gt;&lt;span&gt;    | +--------------------------------+ +--------------------------------+ +--------------------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;    |               | (Reads Data)                                                                                          |
&lt;&#x2F;span&gt;&lt;span&gt;    |               |                                                                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;    | +-------------v--------------------+                                                                                  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |    APACHE SUPERSET (Dataviz)     |                                                                                  |
&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;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h3 id=&quot;engineers&quot;&gt;The engineering team:&lt;&#x2F;h3&gt;
&lt;p&gt;This article is also for my fellow developers who built the 4S network under impossible constraints—limited budgets, legacy infrastructure, unrealistic timelines. My colleagues engineers writing scripts to detect disease patterns, configuring servers that never get enough resources. My teammates who&#x27;s written documentation that nobody reads but everyone depends on. I&#x27;m talking about the people who made the story:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;cisse&quot;&gt;Cisse:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mamadou-cisse-723b29114&#x2F;&quot;&gt;Cisse&lt;&#x2F;a&gt; a.k.a &quot;Celui qui fait bouger le monde&quot;, plays a crucial role in coordinating activities across the Institution Digital Factory team. His expertise extends to managing and preserving the integrity of biomedical data within the Institution. He works closely with stakeholders to validate specifications of new health applications. To uncover more about him, follow this &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mamadou-cisse-723b29114&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mame-astou&quot;&gt;Mame Astou:&lt;&#x2F;h4&gt;
&lt;p&gt;As an integral member of the development team, &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&quot;&gt;Mame Astou&lt;&#x2F;a&gt; a.k.a &quot;Madame La Directrice&quot;, craft robust and dynamic web applications while maintaining a keen eye for intuitive user interface design. She knows how to create user experiences that prioritize both aesthetic appeal and seamless usability. What would we be without her? Absolutely nothing. To uncover more about her, please visit this &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&quot;&gt;page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;diom&quot;&gt;Diom:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.doyoubuzz.com&#x2F;diom-sow&quot;&gt;Diom&lt;&#x2F;a&gt;, a.k.a &quot;Le Grand Marabout de l&#x27;Architecture&quot;, is a DevOps engineer who bridges the gap between development and operations. With expertise in containerization technologies, cloud platforms, and monitoring solutions, he design and maintain scalable deployment environments while ensuring system reliability and security.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;abdoul-karim&quot;&gt;Abdoul Karim:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt; is probably the pillar of the team, always ready to make concessions and take responsibility. His technical experience spans multiple domains. It would take me hours to explain why he is an excellent engineer. Just go and find out by yourself how great &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;he is&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mariama&quot;&gt;Mariama:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;#&quot;&gt;Mariama&lt;&#x2F;a&gt; a.k.a &quot;La Sauveuse De Tous Les Hommes&quot;, has a deep knowledge of Scrum and agile principles. She guide the team through iterative development cycles while fostering continuous improvement and team collaboration. We are still waiting for that one day she will finally write a few lines of TypeScript. Access Mariama&#x27;s comprehensive profile by following this &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;birante&quot;&gt;Birante:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fr.linkedin.com&#x2F;in&#x2F;birantesy&quot;&gt;Birante&lt;&#x2F;a&gt; has an exceptional expertise that encompasses everything from custom UI animations and state management to integrating native device features and third-party services. He is able to deliver native-quality experiences across both iOS, Android and Web platforms. He secretly dreams about rewriting all the 4s platform using &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=gcwzWzC7gUA&quot;&gt;RoR&lt;&#x2F;a&gt; applications. Here is a &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt; to get the complete picture about Birante.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;tidiane&quot;&gt;Tidiane:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;adtidiane&quot;&gt;Tidiane&lt;&#x2F;a&gt;, a.k.a &quot;Le Sage&quot;, a.k.a &quot;The Biobank expert&quot;, is probably the wisest and most reserved member of the team. Tidiane is a seasoned backend developer who brings deep expertise in Django framework development. He excel at designing robust APIs and implementing complex business logic that powers modern web applications. If you know anyone who works at &lt;a href=&quot;https:&#x2F;&#x2F;www.modul-bio.com&quot;&gt;Mbiolims&lt;&#x2F;a&gt;, please tell them they should hire Tidiane. His background can be found &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;amadou-tidiane-diallo-61065a41&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;adrien&quot;&gt;Adrien:&lt;&#x2F;h4&gt;
&lt;p&gt;Aux âmes bien nées, la valeur n&#x27;attend point le nombre d&#x27;années. &lt;a href=&quot;#&quot;&gt;Adrien&lt;&#x2F;a&gt;, the youngest in the team, is a software engineer with an extensive experience in developing RESTful APIs, managing database migrations, and implementing automated testing frameworks within Django projects. For additional information about Adrien, visit this &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Guys, your dedication, your resilience, your ingenuity deserve recognition far beyond what they receive.
Thank you.&lt;&#x2F;strong&gt;
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;future&quot;&gt;The roadmap:&lt;&#x2F;h3&gt;
&lt;p&gt;Right now we&#x27;re developing comprehensive features related to &lt;strong&gt;&quot;case management&quot;&lt;&#x2F;strong&gt;. Those features will enable healthcare providers to track patient journeys from initial consultation through treatment completion, ensuring continuity of care and improved outcomes.&lt;&#x2F;p&gt;
&lt;p&gt;We plan to extend our platform to handle a &lt;strong&gt;wider spectrum of medical conditions and syndromes&lt;&#x2F;strong&gt;, transforming it from a specialized tool into a comprehensive healthcare management solution.&lt;&#x2F;p&gt;
&lt;p&gt;Our platform will also align with the &lt;strong&gt;One Health approach&lt;&#x2F;strong&gt;, recognizing the interconnection between human, animal, and environmental health.&lt;&#x2F;p&gt;
&lt;p&gt;Data exchange with other healthcare systems, electronic health records, and medical devices, is something we need to work towards. We really need to meet evolving healthcare standards and prepare for international expansion. While I agree we didn&#x27;t put enough efforts on this, compliance and interoperability remain central to our development strategy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more&quot;&gt;&lt;u&gt;More on the topic:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Writing about 4S implementation could fill volumes. For those ready to dig deeper into the technical and policy dimensions of public health surveillance, &lt;em&gt;and before I write the second part of this series&lt;&#x2F;em&gt;, here are resources that expand on the key concepts discussed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;healthsites-io&#x2F;cartographie-des-donn%C3%A9es-sanitaires-durgence-au-s%C3%A9n%C3%A9gal-474c3c3bec29&quot;&gt;Mapping emergency health data in Senegal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Z8pa6BQN54w&quot;&gt;How CARE transforms outbreaks into opportunities for Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cZfzP3J2VxY&quot;&gt;A new way to fight infectious diseases and predict outbreaks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stories.theglobalfund.org&#x2F;early-detection-for-rapid-response-strengthening-disease-surveillance-across-west-africa&quot;&gt;Early detection for rapid response: strengthening disease surveillance across West Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;institutpasteurdakar.sn&#x2F;strengthening-epidemic-resilience-through-one-health-and-integrated-community-based-surveillance&#x2F;&quot;&gt;Strengthening epidemic resilience through one health and integrated community-based surveillance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kaikai.dev&#x2F;blog&#x2F;blog-1&#x2F;ihe-for-senegal-a-look-back-at-the-ihe-training-week-6&quot;&gt;Launch and training on medical data exchange in Senegal according to IHE standards&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=pmiQza2kQmE&quot;&gt;Dengue sylvatique : l’angle mort du diagnostic — Dr Idrissa Dieng&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some people we might want to collaborate with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;data.humdata.org&#x2F;&quot;&gt;the Humanitarian Data Exchange&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;healthsites.io&#x2F;&quot;&gt;HealthSites.IO, I&#x27;ve contributed Python code for them&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eyone.net&#x2F;en&#x2F;about-us&quot;&gt;Eyone, improving the quality of medical care through technology.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;njureel.com&#x2F;#accueil&quot;&gt;Njureel,  reinventing the proximity between healthcare professionals and patients&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.geomatica.space&#x2F;&quot;&gt;Geomatica, one of the greatest company in geospatial data (The founder is a very good friend)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I hope you learned something. If you found this article interesting, please share it &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=K0HSD_i2DvA&quot;&gt;around the world&lt;&#x2F;a&gt;. Tell them there are people here who save lives with free and open source software.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;sample.jpg&quot; alt=&quot;&quot; title=&quot;Sample container&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Free and Open Source Software.... Again!</title>
        <published>2025-05-31T00:00:00+00:00</published>
        <updated>2025-05-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/fossa/"/>
        <id>https://nskm.xyz/posts/fossa/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/fossa/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;liberty.jpg&quot; alt=&quot;&quot; title=&quot;Liberty&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;table-of-content&quot;&gt;Table Of Content:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#1&quot;&gt;1 Intro &lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#4&quot;&gt;2. Why contribute&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#13&quot;&gt;3. Skepticism&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#14&quot;&gt;4. How to contribute&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#15&quot;&gt;5. Success stories&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#16&quot;&gt;6. More on the topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;1&quot;&gt;Intro&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m tired of seeing that the majority of Africans still don&#x27;t &lt;a href=&quot;#&quot;&gt;get it&lt;&#x2F;a&gt;, and probably never will, that free and open source software represents the optimal path forward for our continent. &lt;a href=&quot;https:&#x2F;&#x2F;roylab.xyz&#x2F;&quot;&gt;One of&lt;&#x2F;a&gt; my brightest students asked me to talk about free and open source software, and gave me 2 hours to do so. For him, for Africa, for the future, &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;h2M4FDyKANQAAAAC&#x2F;tenor.gif&quot;&gt;here I am&lt;&#x2F;a&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;IT&#x27;s been almost 20 years I see myself as a &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;SubscriberLink&#x2F;1023299&#x2F;7ba649b1ede41895&#x2F;&quot;&gt;free software&lt;&#x2F;a&gt; advocate, therefore my perspectives are inherently biased. Hopefully, the bias is not huge. Let&#x27;s cue the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UAs9-VL66vo&quot;&gt;music&lt;&#x2F;a&gt; please!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2&quot;&gt;&lt;ins&gt;&lt;em&gt;Free software:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The Free software movement, as defined by the &lt;a href=&quot;https:&#x2F;&#x2F;www.fsf.org&#x2F;&quot;&gt;Free Software Foundation&lt;&#x2F;a&gt;, is a social&#x2F;political movement about freedom, ethics, and user rights&#x2F;freedoms. Richard Stallman created the movement in 1983 and the &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;free-sw.html#four-freedoms&quot;&gt;4 essential user freedoms are&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Freedom to run the program for any purpose&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to study how the program works and change it&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to redistribute copies to help others&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to distribute modified versions to benefit the community&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;3&quot;&gt;&lt;ins&gt;&lt;em&gt;Open source software:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The term &quot;open source&quot; was coined to rebrand free software with a business-friendly focus. It emphasizes practical benefits like better quality, reliability, and development methodology rather than ethical considerations. Bruce Perens created the &lt;a href=&quot;https:&#x2F;&#x2F;opensource.org&#x2F;&quot;&gt;Open Source Initiative&lt;&#x2F;a&gt; in 1998 and Open source criteria include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Source code must be available&lt;&#x2F;li&gt;
&lt;li&gt;Free redistribution&lt;&#x2F;li&gt;
&lt;li&gt;Derived works allowed&lt;&#x2F;li&gt;
&lt;li&gt;No discrimination against groups or fields of use&lt;&#x2F;li&gt;
&lt;li&gt;License must not restrict other software&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If we read these &lt;em&gt;two definitions&lt;&#x2F;em&gt; calmly, we can see that there is a very important nuance that should be made here: &lt;strong&gt;the user freedom and independence&lt;&#x2F;strong&gt; is at the center of everything for a free software advocate. This is not necessarily the case for an open source advocate.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;4&quot;&gt;Why contribute:&lt;&#x2F;h2&gt;
&lt;p&gt;Here are compelling reasons why African people should fully embrace Free and Open Source software :&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5&quot;&gt;&lt;ins&gt;&lt;em&gt;Learning:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Free and Open Source Software often attract talented developers. When your code get reviewed by maintainers at companies around the globe, you receive mentorship that money can&#x27;t buy. You&#x27;ll encounter diverse codebases, architectural patterns, problem-solving approaches that you might never see in your day job. Free and Open Source Software forces you to read and understand existing code, which dramatically improves your development skills.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;6&quot;&gt;&lt;ins&gt;&lt;em&gt;Economic opportunities:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Open source contributions can help you land jobs or consulting opportunities. There are many companies worldwide are actively seeking talents. Open source provides the perfect &lt;a href=&quot;https:&#x2F;&#x2F;www.wearedevelopers.com&#x2F;world-congress&#x2F;github-open-source-spotlight&quot;&gt;showcase&lt;&#x2F;a&gt; of your &lt;a href=&quot;https:&#x2F;&#x2F;events.linuxfoundation.org&#x2F;open-source-summit-europe&#x2F;&quot;&gt;abilities&lt;&#x2F;a&gt;. Open source software is often the most accessible option for people with limited budgets. There are a lot of startups across the Black Continent that rely on free and open source solutions to build their digital infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;We often talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;about&#x2F;development-model&quot;&gt;RedHat&lt;&#x2F;a&gt;, but there are many other companies like: &lt;a href=&quot;https:&#x2F;&#x2F;www.zdnet.com&#x2F;article&#x2F;open-source-is-getting-bigger-and-richer-says-suse&#x2F;&quot;&gt;Suse&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;blog&#x2F;monetizing-and-being-open-source&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=13774420&quot;&gt;Docker&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nextcloud.com&#x2F;about&#x2F;&quot;&gt;NextCloud&lt;&#x2F;a&gt;, companies that demonstrate various and successful approaches built on free and open source foundations.&lt;&#x2F;p&gt;
&lt;p&gt;In a nutshell, those companies will offer subscriptions and services for a guaranteed support, security updates, patches, custom implementations, customizations, optimizations, trainings, certifications, consulting, ...&lt;&#x2F;p&gt;
&lt;p&gt;I would like to do a special mention for 2 companies: &lt;a href=&quot;https:&#x2F;&#x2F;www.entrouvert.com&#x2F;expertise&#x2F;logiciels-reellement-libres&#x2F;&quot;&gt;Entr&#x27;Ouvert&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.fr&#x2F;societe&quot;&gt;Logilab&lt;&#x2F;a&gt;. They offer implementations, customizations, trainings, and consulting services exclusively with free software, you can see it &lt;a href=&quot;https:&#x2F;&#x2F;dev.entrouvert.org&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;explore&quot;&gt;there&lt;&#x2F;a&gt;. They have a deep expertise in the free software industry and this expertise became a valuable service to their clients. Also, I have very good friends over there, shoutout o&#x2F;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;7&quot;&gt;&lt;ins&gt;&lt;em&gt;Breaking geographic barriers:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Thanks to Free and Open Source Software, your code quality matters more than your location or background. African developers can showcase their skills on the same &lt;a href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;platforms&lt;&#x2F;a&gt; as Silicon Valley engineers. Free and Open Source is our opportunity for challenging stereotypes and demonstrating our technical talent to the world.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;78&quot;&gt;&lt;ins&gt;&lt;em&gt;Gaming:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Linux was once held back by its compatibility with PC games, but thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.valvesoftware.com&quot;&gt;Valve&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;steamos&#x2F;&quot;&gt;SteamOS&lt;&#x2F;a&gt;, those days are in the past. Better gaming performance, better battery life, better power management, are &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=CJXp3UYj50Q&quot;&gt;another reasons&lt;&#x2F;a&gt; to use Linux.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;8&quot;&gt;&lt;ins&gt;&lt;em&gt;Community:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The open source community represents humanity at its best, a global network where people freely exchange expertise and genuinely celebrate one another&#x27;s wins. When you realize your contribution has solved someone&#x27;s problem or saved them hours of work, that feeling is pure gold. Belonging to a community, building &lt;a href=&quot;https:&#x2F;&#x2F;www.thesocialcreatures.org&#x2F;thecreaturetimes&#x2F;evolution-of-social-connection&quot;&gt;social connections&lt;&#x2F;a&gt; is essential to our wellbeing, it is as important as food, water and shelter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;9&quot;&gt;&lt;ins&gt;&lt;em&gt;Digital sovereignty:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2307.01791&quot;&gt;Digital sovereignty&lt;&#x2F;a&gt; encompasses control over critical digital infrastructure like internet networks, data centers, communication systems and mobile&#x2F;web platforms. Digital sovereignty is the ability to regulate how &lt;em&gt;our&lt;&#x2F;em&gt; data is collected, stored, and processed within &lt;em&gt;our&lt;&#x2F;em&gt; jurisdiction.&lt;&#x2F;p&gt;
&lt;p&gt;What happens when a country&#x27;s government systems, banking infrastructure, or communication networks depend entirely on software and services controlled by foreign companies. This is where free and open source software becomes crucial for digital sovereignty.&lt;&#x2F;p&gt;
&lt;p&gt;When you use non free and non open source software:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you&#x27;re dependent on the vendor&#x27;s decisions, pricing, and continued support.&lt;&#x2F;li&gt;
&lt;li&gt;you can&#x27;t see how it works, modify it for your needs, or ensure it doesn&#x27;t contain &lt;a href=&quot;https:&#x2F;&#x2F;cyberlaw.ccdcoe.org&#x2F;wiki&#x2F;African_Union_headquarters_hack_(2018)&quot;&gt;backdoors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;you &lt;a href=&quot;https:&#x2F;&#x2F;www.dw.com&#x2F;en&#x2F;will-meta-lawsuits-shape-africas-data-privacy-laws&#x2F;a-72567105&quot;&gt;lose the right to determine how your data is used&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;10&quot;&gt;&lt;ins&gt;&lt;em&gt;The others are moving&lt;&#x2F;em&gt;:&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;publiccode.eu&#x2F;en&#x2F;&quot;&gt;Public money, public code&lt;&#x2F;a&gt; an initiative advocating that software developed with public funds should be made freely available under a free and open-source license.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;code.gouv.fr&#x2F;fr&#x2F;&quot;&gt;Pôle open source et communs numériques&lt;&#x2F;a&gt;, Initiative to support government administrations in using free and open source software, assist their efforts to publish and share source code, and create connections with the open source ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.documentfoundation.org&#x2F;blog&#x2F;2024&#x2F;04&#x2F;04&#x2F;german-state-moving-30000-pcs-to-libreoffice&#x2F;&quot;&gt;The German federal state&lt;&#x2F;a&gt; has decided to move from Microsoft Windows and Microsoft Office to Linux and LibreOffice (and other free and open source software) on the 30,000 PCs used in the local government.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eu-os.eu&#x2F;&quot;&gt;EU OS&lt;&#x2F;a&gt;, a proof-of-concept for an Operating System for a typical organization inside the European Union public sector.&lt;&#x2F;p&gt;
&lt;p&gt;To move away from dependence on US software solutions and acquire genuine digital sovereignty, the &lt;a href=&quot;https:&#x2F;&#x2F;www.lyon.fr&#x2F;actualite&#x2F;action-municipale&#x2F;la-ville-de-lyon-renforce-sa-souverainete-numerique&quot;&gt;City of Lyon&lt;&#x2F;a&gt; has embarked on a major transformation of its digital tools.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;At this point, I don&#x27;t even know what else should I say to convince you...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.zdnet.com&#x2F;article&#x2F;why-denmark-is-dumping-microsoft-office-and-windows-for-libreoffice-and-linux&#x2F;&quot;&gt;Denmark&lt;&#x2F;a&gt; is transitioning away from Microsoft products in a key ministry due to a strategy focused on digital sovereignty and reducing reliance on foreign, particularly US-based, tech giants. This involves replacing Windows and Office 365 with open-source alternatives like Linux and LibreOffice.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;economictimes.indiatimes.com&#x2F;news&#x2F;international&#x2F;us&#x2F;after-danish-cities-germanys-schleswig-holstein-state-government-to-ban-microsoft-programs-at-work&#x2F;articleshow&#x2F;121833653.cms&quot;&gt;Schleswig-Holstein state&lt;&#x2F;a&gt; government is shifting completely to free and open source software, aiming to achieve what officials call &quot;digital sovereignty&quot; and to reduce reliance on U.S.-based tech giants [...] This isn’t just about software. It&#x27;s about control over sensitive data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;11&quot;&gt;&lt;ins&gt;&lt;em&gt;You&#x27;re already consuming:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;ve ever used &lt;a href=&quot;https:&#x2F;&#x2F;opensource.google&#x2F;&quot;&gt;Google&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;opensource.fb.com&#x2F;&quot;&gt;Facebook&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;whatsapp&quot;&gt;WhatsApp&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;opensource.microsoft.com&#x2F;&quot;&gt;Microsoft&lt;&#x2F;a&gt; or watched a &lt;a href=&quot;https:&#x2F;&#x2F;netflix.github.io&#x2F;&quot;&gt;Netflix&lt;&#x2F;a&gt; movie today, you&#x27;ve been relying on free and open source software without even knowing it. These tech giants don&#x27;t reinvent the wheel, they build their services on top of thousands of open source projects. None of those things would exist without free and open source software.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;13&quot;&gt;Skepticism:&lt;&#x2F;h2&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;skeptic.jpg&quot; alt=&quot;skeptical&quot; title=&quot;If free software is so great, why do I get the feeling that no one uses it?&quot;&#x2F;&gt;
&lt;p&gt;Technological proficiency is important, but &lt;strong&gt;correctly managing the cultural&lt;&#x2F;strong&gt; shift required to embrace free and open source software is also very important. There are a number of &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5GXGdavLu6Y&quot;&gt;complex reasons&lt;&#x2F;a&gt; why mass adoption of free and open software has not yet taken place in Africa.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cultural-resistance-and-habits&quot;&gt;&lt;ins&gt;&lt;em&gt;Cultural resistance and habits:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Users are used to the interfaces and workflows of proprietary software. Change naturally generates resistance, especially when the benefits are not immediately perceptible to the end-user.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;institutional-inertia&quot;&gt;&lt;ins&gt;&lt;em&gt;Institutional inertia:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Public and private organizations are often prisoners of their past technological choices. Migrating complex systems requires massive investment in training, data migration and process adaptation. This &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;7RXK-nR83f4&quot;&gt;vendor lock-in&lt;&#x2F;a&gt; is particularly strong in public administration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;perception-of-complexity-and-support&quot;&gt;&lt;ins&gt;&lt;em&gt;Perception of complexity and support:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In my humble opinion, this perception no longer corresponds to current reality. Yet, many still consider free and open source software to be more technical and less user-friendly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lobbying-and-political-influence&quot;&gt;&lt;ins&gt;&lt;em&gt;Lobbying and political influence:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Large technology companies exert considerable &lt;a href=&quot;https:&#x2F;&#x2F;corporateeurope.org&#x2F;en&#x2F;2023&#x2F;09&#x2F;lobbying-power-amazon-google-and-co-continues-grow&quot;&gt;influence&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.lbc.co.uk&#x2F;world-news&#x2F;british-icc-chief-prosecutor-lost-email-bank-accounts-frozen-trump-sanctions&#x2F;&quot;&gt;pressure&lt;&#x2F;a&gt; on political decisions and public procurement, hindering the adoption of alternative solutions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;economic-reasons&quot;&gt;&lt;ins&gt;&lt;em&gt;Economic reasons:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Business models built around proprietary software generate huge revenues. Companies like Microsoft, Adobe or Oracle have built entire ecosystems that create mutual financial dependency. To change would represent considerable transition costs and a loss of revenue for many players.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;to-go-even-deeper-on-this-subject&quot;&gt;&lt;ins&gt;&lt;em&gt;To go even deeper on this subject:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Here is a really interesting &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;papers.cfm?abstract_id=3138085&quot;&gt;study&lt;&#x2F;a&gt;, intitled &lt;strong&gt;&lt;em&gt;Adoption Barriers of Open-Source Software: A Systematic Review&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; and led by &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;cf_dev&#x2F;AbsByAuth.cfm?per_id=2321721&quot;&gt;Dmitrij Petrov&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;cf_dev&#x2F;AbsByAuth.cfm?per_id=2544892&quot;&gt;Nikolaus Obwegeser&lt;&#x2F;a&gt;. A study that tried to find all the significant barriers that hinder the wider adoption of Free and Open source software. Have been found 19 high-level factors that challenge or inhibit the adoption of FLOSS in various contexts. Long story short....&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 900px&quot; src=&quot;&#x2F;images&#x2F;adoption_barriers_of_foss.png&quot; alt=&quot;&quot; title=&quot;Barriers of FOSS&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;14&quot;&gt;How to contribute:&lt;&#x2F;h2&gt;
&lt;p&gt;There are so many &lt;a href=&quot;https:&#x2F;&#x2F;contribute.cncf.io&#x2F;contributors&#x2F;getting-started&#x2F;&quot;&gt;ways&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;get-started&#x2F;exploring-projects-on-github&#x2F;finding-ways-to-contribute-to-open-source-on-github&quot;&gt;contribute&lt;&#x2F;a&gt; to free and open source software. There are so many &lt;a href=&quot;https:&#x2F;&#x2F;www.freecodecamp.org&#x2F;news&#x2F;how-to-contribute-to-open-source-projects-beginners-guide&#x2F;#:~:text=Adding%20a%20description%20to%20a,the%20project%27s%20work%20folder%20correctly.&quot;&gt;articles&lt;&#x2F;a&gt;, so many &lt;a href=&quot;https:&#x2F;&#x2F;opensource.guide&#x2F;how-to-contribute&#x2F;&quot;&gt;guides&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;opensauced&#x2F;how-i-got-hired-contributing-to-open-source-projects-546i&quot;&gt;tutorials&lt;&#x2F;a&gt;. The choice is &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;resources&#x2F;articles&#x2F;how-to-contribute-to-open-source&quot;&gt;yours&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you really want me to answer the question, this is more or less how it should be done (on top of my head).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;0-contribution-types&quot;&gt;0. Contribution types:&lt;&#x2F;h4&gt;
&lt;p&gt;There are several ways you can contribute to free and open source projects.&lt;&#x2F;p&gt;
&lt;p&gt;Bug fixes involve addressing opened issues, improving error handling, and resolving technical problems that users have encountered. Feature contributions include adding new functionality, enhancing user experience and interface design, and optimizing performance to make applications run more efficiently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;diataxis.fr&#x2F;&quot;&gt;Documentation&lt;&#x2F;a&gt; improvements focus on enhancing readability, adding helpful examples and tutorials, providing translations for broader accessibility, and fixing typos or grammatical errors.&lt;&#x2F;p&gt;
&lt;p&gt;The last contribution type I would like to talk about is funding. Funding through &lt;a href=&quot;https:&#x2F;&#x2F;my.fsf.org&#x2F;join&quot;&gt;donating&lt;&#x2F;a&gt; or direct &lt;a href=&quot;https:&#x2F;&#x2F;palletsprojects.com&#x2F;donate&quot;&gt;sponsoring&lt;&#x2F;a&gt; can provide crucial financial support to help free and open source projects continue their development.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-tips&quot;&gt;1. Tips:&lt;&#x2F;h4&gt;
&lt;p&gt;Before diving into contributions, it&#x27;s essential to read the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;main&#x2F;CONTRIBUTING.rst&quot;&gt;CONTRIBUTING.md&lt;&#x2F;a&gt; file or any other available documentation to understand the project&#x27;s specific guidelines and processes.&lt;&#x2F;p&gt;
&lt;p&gt;Starting small with simple fixes like correcting typos or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;numpy&#x2F;numpy&#x2F;issues&#x2F;29258&quot;&gt;improving documentation&lt;&#x2F;a&gt; can be incredibly valuable and help you get familiar with the contribution workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to be patient during the review process, as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;pull&#x2F;19565&quot;&gt;reviews&lt;&#x2F;a&gt; are conducted by human beings who need time to thoroughly examine your work. Don&#x27;t hesitate to ask &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5k0ndcJiECo&quot;&gt;questions&lt;&#x2F;a&gt; when you&#x27;re stuck, and feel free to ask even more &lt;a href=&quot;https:&#x2F;&#x2F;palletsprojects.com&#x2F;contributing&#x2F;questions&quot;&gt;questions&lt;&#x2F;a&gt; to clarify requirements or processes.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also important to focus on making one logical change per Pull Request to keep your contributions clear and manageable for reviewers.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-discover-explore&quot;&gt;2. Discover &amp;amp; explore:&lt;&#x2F;h4&gt;
&lt;p&gt;Begin your open source journey by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;firstcontributions&#x2F;first-contributions&quot;&gt;finding&lt;&#x2F;a&gt; a project that you &lt;strong&gt;actively use&lt;&#x2F;strong&gt; or &lt;strong&gt;genuinely care about&lt;&#x2F;strong&gt;, as this personal connection will help sustain your &lt;strong&gt;motivation&lt;&#x2F;strong&gt;. Take time to thoroughly read the project&#x27;s documentation and contributing guidelines to understand how the community operates and what standards they maintain. Browse through the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;numpy&#x2F;numpy&#x2F;issues&quot;&gt;project&#x27;s issues&lt;&#x2F;a&gt; section, paying special attention to those tagged with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jazzband&#x2F;django-silk&#x2F;issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;&quot;good first issue&quot;&lt;&#x2F;a&gt; or &quot;beginner&quot; labels, as these are specifically designed to help newcomers get started with meaningful contributions.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;3-setup-your-environment&quot;&gt;3. Setup your environment:&lt;&#x2F;h4&gt;
&lt;p&gt;Getting started with development requires setting up your workspace properly. First, &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;pull-requests&#x2F;collaborating-with-pull-requests&#x2F;working-with-forks&#x2F;fork-a-repo&quot;&gt;fork&lt;&#x2F;a&gt; the repository to create your own copy of the project. Next, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-clone&quot;&gt;clone&lt;&#x2F;a&gt; this forked repository to your local machine where you can make changes and test your work.&lt;&#x2F;p&gt;
&lt;p&gt;Take time to set up the development environment according to the project&#x27;s instructions, which may involve &lt;a href=&quot;#&quot;&gt;installing&lt;&#x2F;a&gt; specific dependencies or configuring tools. Run any available &lt;a href=&quot;#&quot;&gt;unit tests&lt;&#x2F;a&gt; to ensure everything is working correctly in your setup, as this confirms your environment is properly configured. Finally, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-switch&quot;&gt;create a new branch&lt;&#x2F;a&gt; for your work to keep your changes organized and separate from the main codebase.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;4-make-your-contribution&quot;&gt;4. Make your contribution:&lt;&#x2F;h4&gt;
&lt;p&gt;When working on your contribution, it&#x27;s crucial to follow the project&#x27;s established &lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0008&#x2F;&quot;&gt;coding style and conventions&lt;&#x2F;a&gt; to maintain consistency across the codebase. Focus on writing your code, fixing bugs, or adding features while keeping the project&#x27;s standards and best practices in mind. Remember to update &lt;a href=&quot;#&quot;&gt;documentation&lt;&#x2F;a&gt; whenever your changes affect how users or developers interact with the project. Additionally, add or update &lt;a href=&quot;#&quot;&gt;tests&lt;&#x2F;a&gt; to cover your changes, ensuring that new functionality works as expected and that bug fixes prevent regression.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;5-test-prepare&quot;&gt;5. Test &amp;amp; prepare&lt;&#x2F;h4&gt;
&lt;p&gt;Before submitting your work, thoroughly &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;tree&#x2F;main&#x2F;tests&quot;&gt;test&lt;&#x2F;a&gt; your changes by running tests locally to catch any issues early in the process. Carefully review your changes to ensure they meet the project&#x27;s quality standards and actually solve the intended problem.&lt;&#x2F;p&gt;
&lt;p&gt;Write clear, &lt;a href=&quot;https:&#x2F;&#x2F;www.conventionalcommits.org&#x2F;en&#x2F;v1.0.0&#x2F;&quot;&gt;descriptive commit messages&lt;&#x2F;a&gt; that explain what your changes do and why they were necessary, as this helps maintainers understand your contribution. Double-check your work against the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;internals&#x2F;contributing&#x2F;&quot;&gt;contributing guide&lt;&#x2F;a&gt; to make sure you&#x27;ve followed all the project&#x27;s requirements and conventions.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;6-submit-your-work&quot;&gt;6. Submit your work&lt;&#x2F;h4&gt;
&lt;p&gt;Once your contribution is ready, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-push&quot;&gt;push&lt;&#x2F;a&gt; your branch to your forked repository to make it available for review. Create a &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;pull-requests&#x2F;collaborating-with-pull-requests&#x2F;proposing-changes-to-your-work-with-pull-requests&#x2F;about-pull-requests&quot;&gt;Pull Request&lt;&#x2F;a&gt; from your branch to the original project&#x27;s main branch, providing a clear pathway for your changes to be reviewed and potentially merged.&lt;&#x2F;p&gt;
&lt;p&gt;Fill out the PR template with detailed information about what your changes do, why they&#x27;re needed, and how they&#x27;ve been tested. If your contribution addresses specific issues, link those related issues in your PR description to provide context and help maintainers track the resolution of reported problems.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;7-collaborate-refine&quot;&gt;7. Collaborate &amp;amp; refine&lt;&#x2F;h4&gt;
&lt;p&gt;After submitting your Pull Request, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;healthsites&#x2F;healthsites&#x2F;pulls?q=+is%3Apr+author%3Alemeteore+&quot;&gt;actively engage with the review process&lt;&#x2F;a&gt; by responding promptly and thoughtfully to code review feedback from maintainers and other contributors. Make any requested changes to address concerns or suggestions, treating each piece of feedback as an opportunity to improve your contribution and learn from experienced developers.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout this process, engage in discussions &lt;strong&gt;respectfully and professionally&lt;&#x2F;strong&gt;, remembering that constructive feedback is meant to help improve the project rather than criticize your work personally. Pay attention to any failing CI checks and address them promptly, as these automated tests help ensure your changes don&#x27;t break existing functionality.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;8-merge-celebrate&quot;&gt;8. Merge &amp;amp; celebrate:&lt;&#x2F;h4&gt;
&lt;p&gt;Your contribution gets merged into the main project, congratulations 🎉. This marks a significant achievement in your open source journey. You&#x27;re now officially a project contributor, joining a community of developers who have helped shape and improve the software. Most importantly, your code now helps users worldwide, potentially solving problems, adding useful features, or improving the experience for countless people who rely on the project.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;blog&#x2F;2023&#x2F;04&#x2F;03&#x2F;outlining-the-structure-of-your-open-source-software-project&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; discussing, among other things, the tasks that are needed to be taken care of for different sizes of the open source project. We see that the bigger the project, the more ways there are to contribute.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;15&quot;&gt;Success stories:&lt;&#x2F;h2&gt;
&lt;p&gt;After &lt;a href=&quot;https:&#x2F;&#x2F;x.com&#x2F;fossfa&quot;&gt;searching&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.crunchbase.com&#x2F;organization&#x2F;fossfa&quot;&gt;very&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FOSSFA&quot;&gt;extensively&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.instagram.com&#x2F;fossfa&#x2F;&quot;&gt;everywhere&lt;&#x2F;a&gt; on the internet, I found no &lt;strong&gt;current&lt;&#x2F;strong&gt; organizations in Africa, that even remotely resembles the Free Software Foundation.&lt;&#x2F;p&gt;
&lt;p&gt;If you find interesting (and recent) informations about free and open source software initiaves&#x2F;organizations in Africa, if you are in one way or another, linked to an active Linux User Group in Africa, please, if you know any African initiative&#x2F;organization that promotes free and open source software in Africa, please let me know. I&#x27;ll be glad to update the article.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;open-source-contributions.jpg&quot; alt=&quot;&quot; title=&quot;Hopefully, you won&#x27;t leave! Because we need your help!&quot;&#x2F;&gt;
&lt;h2 id=&quot;16&quot;&gt;More on the topic:&lt;&#x2F;h2&gt;
&lt;p&gt;We could easily spend days on this topic! Since we only have two hours, here are some excellent resources to continue your journey into this fascinating subject.&lt;&#x2F;p&gt;
&lt;p&gt;In french:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Ef8jkpJEDVc&quot;&gt;La liberté du logiciel expliquée en moins de 3 min!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Xazuo7Rva2Y&quot;&gt;Se lancer dans l&#x27;open source à 100% (et en vivre !)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=JWJmFTcH1Bw&quot;&gt;Le logiciel libre comme levier de souveraineté&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YQTEq9BRefo&quot;&gt;Open Source: Comprendre, Contribuer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=y4AjuV0O3wo&quot;&gt;Comment devenir un contributeur Open Source ?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8U80yLOZLp4&quot;&gt;Open source &amp;amp; logiciel libre&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In english:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=PVD1LNDxOnc&quot;&gt;Open Source explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opensource.guide&#x2F;how-to-contribute&#x2F;&quot;&gt;How to contribute to Open Source&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;resources&#x2F;articles&#x2F;how-to-contribute-to-open-source&quot;&gt;How to contribute to Open Source, a step by step guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;open-source-misses-the-point.en.html&quot;&gt;Why Open Source misses the point of Free Software&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;1013776&#x2F;&quot;&gt;Lessons from open source in the Mexican government&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s be optimistic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;livingopensource.org&#x2F;the-rise-of-open-source-software-in-africa-current-trends-and-futureprospects&#x2F;&quot;&gt;The rise of Open Source software in Africa: current trends and future prospects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.africantechroundup.com&#x2F;open-source-proprietary-software-african-tech-round-up&#x2F;&quot;&gt;Open Source vs proprietary software: what is best for Africa?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ictworks.org&#x2F;digital-colonialism-african-software-development&#x2F;&quot;&gt;How to break digital colonialism in African software development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.universityworldnews.com&#x2F;post.php?story=20241203094802197&quot;&gt;Ten university teams worked on open-source operating system&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By the way...:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Free Software Foundation (FSF) &lt;a href=&quot;https:&#x2F;&#x2F;www.fsf.org&#x2F;fsf40&quot;&gt;turns forty&lt;&#x2F;a&gt; this year&lt;&#x2F;li&gt;
&lt;li&gt;PyCon Africa and PyConZA are &lt;a href=&quot;https:&#x2F;&#x2F;za.pycon.org&#x2F;&quot;&gt;joining forces!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;2025.djangocon.africa&#x2F;&quot;&gt;DjangoCon Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Co-locating &lt;a href=&quot;https:&#x2F;&#x2F;discourse.ubuntu.com&#x2F;t&#x2F;ubucon-africa-djangocon-africa-2025&#x2F;59940&quot;&gt;the 1st UbuCon Africa with the passionate Django community!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;oshwa.org&#x2F;about&#x2F;&quot;&gt;The Open Source Hardware Association&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Framework &lt;a href=&quot;https:&#x2F;&#x2F;frame.work&#x2F;about&quot;&gt;electronics are open to repair and upgrade&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the next few weeks, I will publish findings regarding the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ssssss&#x2F;&quot;&gt;Syndromic Surveillance System&lt;&#x2F;a&gt; I&#x27;m currently working on. Expect a detailed writeup showing exactly how free and open source software is driving a positive change to the West Africa&#x27;s public health infrastructure. Stay tuned...&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 200px&quot; src=&quot;&#x2F;images&#x2F;stay_tuned.gif&quot; alt=&quot;&quot; title=&quot;stay tuned&quot;&#x2F;&gt;
&lt;p&gt;Thanks for sharing!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>C Pointers</title>
        <published>2024-06-18T00:00:00+00:00</published>
        <updated>2024-06-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/ptrs/"/>
        <id>https://nskm.xyz/posts/ptrs/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/ptrs/">&lt;p&gt;In my &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;&quot;&gt;last&lt;&#x2F;a&gt; post, I&#x27;ve written about lots of things but not about C pointers. I thought the topic deserves a post in itself because it&#x27;s one of the most important features of the C language.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with some &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=24ntpKNiUMs&quot;&gt;music&lt;&#x2F;a&gt; please.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;pointers.png&quot; alt=&quot;C Pointers&quot; title=&quot;C Pointers&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#i&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#d&quot;&gt;Declaration &amp;amp; initialization&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#o&quot;&gt;Operators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#u&quot;&gt;Use cases&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#a&quot;&gt;Arrays &amp;amp; strings manipulation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#p&quot;&gt;Pass by reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#m&quot;&gt;Memory allocation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#s&quot;&gt;Data structure implementation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#f&quot;&gt;Functions pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#h&quot;&gt;Hardware interface&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#g&quot;&gt;Going further&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;i&quot;&gt;Introduction:&lt;&#x2F;h2&gt;
&lt;p&gt;A pointer is a variable that contains the memory address of another variable. A pointer allows
us to &lt;em&gt;indirectly&lt;&#x2F;em&gt; access and manipulate the value of the variable that is pointed to. Like other variables, C pointers have a type.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img
    style=&quot;display: block; margin: 0 auto; width: 600px&quot;
    src=&quot;&#x2F;assets&#x2F;pointers_repr.png&quot;
    alt=&quot;Pointers&quot;
    title=&quot;Pointers&quot;&#x2F;&gt;&lt;&#x2F;p&gt;
  &lt;center&gt;
    &lt;a href=&quot;https:&#x2F;&#x2F;codeforwin.org&quot;&gt;Source&lt;&#x2F;a&gt;
  &lt;&#x2F;center&gt;
&lt;h2 id=&quot;d&quot;&gt;Declaration and initialization:&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; bar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;83&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;foo;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer variable, type int, receives the address of foo variable*
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int **&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;ptr; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; pointer to a pointer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr to ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bar;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr, still: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the output of the previous program is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;Value of foo: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is: 0x7ffc6155fd60, and ptr is pointing to: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr is: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is pointing to: 0x7ffc6155fd60
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr: 12
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr to ptr: 13
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is now: 0x7ffc6155fd64, and ptr is now pointing to: 83
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr, still: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is now pointing to: 0x7ffc6155fd64
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;o&quot;&gt;C pointer operators:&lt;&#x2F;h2&gt;
&lt;p&gt;C offers operators for pointer manipulation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Address-of operator (&amp;amp;): to return the memory address of a variable&lt;&#x2F;li&gt;
&lt;li&gt;Dereference operator (*): to access the value stored at the memory address pointed to&lt;&#x2F;li&gt;
&lt;li&gt;Arithmetic operators: to perform arithmetic operations on C pointers, addition (+), subtraction (-), increment (++), and decrement (--)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;u&quot;&gt;Use cases for C pointers:&lt;&#x2F;h2&gt;
&lt;p&gt;All modern programming languages have pointers in some form or other. Pointers are used everywhere there is a program, even when we don&#x27;t see them. Let&#x27;s explore some of those use cases.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a&quot;&gt;Manipulating array and string elements:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to access and manipulate elements in arrays and strings. C Pointers provide a way to efficiently iterate over arrays and perform operations on each item of the sequence.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;aptr = arr;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using array indices
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#608b4e;&quot;&gt;&#x2F;&#x2F; print elements of the array using pointer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;aptr);
&lt;&#x2F;span&gt;&lt;span&gt;  aptr++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using pointer arithmetic
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and the fact that arr is actually a pointer to the first item of the arr
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;arr+i);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; str[] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world from West Africa&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;sptr = str; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a pointer to the first element of the array
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; while i is less than 28, print the character at i-th index 
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str[i]);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment i to go to the next index
&lt;&#x2F;span&gt;&lt;span&gt;  i++;
&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#608b4e;&quot;&gt;&#x2F;&#x2F; while the value that is pointed to is different from the &amp;quot;\0&amp;quot; character
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#608b4e;&quot;&gt;&#x2F;&#x2F; print the char
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment pointer (to go to the next character)
&lt;&#x2F;span&gt;&lt;span&gt;  sptr = sptr + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; m = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(m &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; str is actually a pointer to the first item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; so str+m is the address of the m-ieth item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;(str+m));
&lt;&#x2F;span&gt;&lt;span&gt;  m++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; array of pointers to characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;names[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Alice&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bob&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Charlie&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;David&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Emma&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer to the first element of the first element of the array of strings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char **&lt;&#x2F;span&gt;&lt;span&gt;ptr_names = names; 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; j = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; j &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; j++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print elements of the array of strings using indices
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, names[j]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; x &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; x++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print the element currently pointed to
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr_names);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr_names = ptr_names + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;p&quot;&gt;Passing arguments by reference:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to pass arguments by reference to functions, allowing the function to modify the value of the original variable. This is particularly useful in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;working with large data structures&lt;&#x2F;li&gt;
&lt;li&gt;you need to modify the value of a variable in a function&lt;&#x2F;li&gt;
&lt;li&gt;you need to optimize code by reducing the number of copies of data that need to be made&lt;&#x2F;li&gt;
&lt;li&gt;you need to return more than one value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s suppose this is a laaaaaarge struct
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; id;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; salary;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Employee&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:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;update_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary *= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; 10% raise
&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; We create the large structure once
&lt;&#x2F;span&gt;&lt;span&gt;  Employee e1 = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;John Doe&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5000&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e1.name, e1.salary);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; We pass the large structure by reference
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; to avoid the overhead of copying the entire structure.
&lt;&#x2F;span&gt;&lt;span&gt;  update_employee(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;e1);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee after update: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e1.name, e1.salary);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;m&quot;&gt;Allocating memory:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are also used to allocate memory dynamically at run-time using functions like &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;malloc.3.html&quot;&gt;malloc()&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;calloc.3p.html&quot;&gt;calloc()&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;realloc.3p.html&quot;&gt;realloc()&lt;&#x2F;a&gt;. Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a huuuuuuuge structure
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; id;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; salary;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Employee&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; thanks to pointer &amp;amp; to malloc,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; we can create the structure inside the create_employee function
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and use the structure even after the function goes out of scope
&lt;&#x2F;span&gt;&lt;span&gt;Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;create_employee(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Allocate memory space on heap, size should be the same as width of Employee struct
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Allocate a pointer on stack,
&lt;&#x2F;span&gt;&lt;span&gt;  Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; e2 = malloc(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(Employee));
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; always verify the allocation worked fine
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(e2 == nullptr) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Memory allocation failed!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the ptr e2 contains the value of the memory address of the struct that is on the heap  
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; e2;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;init_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;id, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const char* &lt;&#x2F;span&gt;&lt;span&gt;name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float &lt;&#x2F;span&gt;&lt;span&gt;salary) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;id = id;
&lt;&#x2F;span&gt;&lt;span&gt;  strcpy(emp-&amp;gt;name, name);
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary = salary;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;update_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary *= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; 10% raise
&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; e2 = create_employee();
&lt;&#x2F;span&gt;&lt;span&gt;  init_employee(e2, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nsukami Patrick&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6000&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e2-&amp;gt;name, e2-&amp;gt;salary);
&lt;&#x2F;span&gt;&lt;span&gt;  update_employee(e2);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee after update: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e2-&amp;gt;name, e2-&amp;gt;salary);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; never forget to free the allocated memory
&lt;&#x2F;span&gt;&lt;span&gt;  free(e2);
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;s&quot;&gt;Implementing data structures:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;#&quot;&gt;Linked lists&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Stacks&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Queues&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Trees&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Graphs&lt;&#x2F;a&gt; and many other data structures are implemented using C Pointers. Example:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;f&quot;&gt;Calling functions:&lt;&#x2F;h3&gt;
&lt;p&gt;A function pointer, is a pointer which point to the memory address of a function instead of pointing to the address of a data object. They are used to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;store functions in data structures&lt;&#x2F;li&gt;
&lt;li&gt;pass functions as arguments to other functions&lt;&#x2F;li&gt;
&lt;li&gt;call functions dynamically at runtime&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here are some &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fp&#x2F;&quot;&gt;examples&lt;&#x2F;a&gt; on how to use function pointers in C.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;h&quot;&gt;Interfacing with hardware:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are often used in low-level programming to interact with hardware devices and memory-mapped registers. They provide a way to access specific memory addresses and manipulate hardware directly. This part goes way beyond what my brain is able to understand. Hopefully, I&#x27;ll be able to show you an example in another article.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;g&quot;&gt;Going further:&lt;&#x2F;h2&gt;
&lt;p&gt;To learn more about C pointers, we recommend the following &lt;strong&gt;pointers&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;SIN2jJm.png&quot;&gt;0x7ffc6155fd68&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(dog_breed)&quot;&gt;0x7ffc6155fd69&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(computer_programming)&quot;&gt;0x7ffc6155fd70&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;playlist?list=PLdo5W4Nhv31a8UcMN9-35ghv8qyFWD9_S&quot;&gt;0x7ffc6155fd71&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;setleds.1.html&quot;&gt;0x7ffc6155fd72&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.adafruit.com&#x2F;product&#x2F;2264&quot;&gt;0x7ffc6155fd73&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;ptrs.jpg&quot; alt=&quot;Pointers&quot; title=&quot;Pointers&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>C</title>
        <published>2023-09-25T00:00:00+00:00</published>
        <updated>2023-09-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/cp/"/>
        <id>https://nskm.xyz/posts/cp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/cp/">&lt;p&gt;I spent some time adding &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.fr&#x2F;blogentry&#x2F;13884378&quot;&gt;type annotations&lt;&#x2F;a&gt; to some Python code. Shoutout to all the people at &lt;a href=&quot;https:&#x2F;&#x2F;logilab.fr&quot;&gt;Logilab&lt;&#x2F;a&gt;, a really awesome team doing really awesome things. All those type annotations made me more and more interested in static typing... and in C programming.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Target audience&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: people who already have an experience with programming. People who may have written some C programs in the past and who want to refresh their memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: I&#x27;m working on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I&#x27;m working on &lt;code&gt;Linux 5.13.0-52-generic #59-Ubuntu SMP Wed Jun 15 20:17:13 UTC 2022 x86_64&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;And I&#x27;m using &lt;code&gt;GCC (Ubuntu 11.2.0-7ubuntu2) 11.2.0&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=6YSNKq-6SjM&quot;&gt;Music please&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;force.jpg&quot; alt=&quot;Force&quot; title=&quot;Force&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#primitive&quot;&gt;Primitive types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#integers&quot;&gt;integers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#floats&quot;&gt;floats&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#bool&quot;&gt;booleans&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#void&quot;&gt;void&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#composite&quot;&gt;Composite types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#structs&quot;&gt;structs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#enums&quot;&gt;enums&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#unions&quot;&gt;unions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#arrays&quot;&gt;arrays&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#strings&quot;&gt;strings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#constants&quot;&gt;Constants&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;The setup:&lt;&#x2F;h2&gt;
&lt;p&gt;To write C programs, we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;a href=&quot;#&quot;&gt;operating system&lt;&#x2F;a&gt; that respect your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;A C compiler such as &lt;a href=&quot;https:&#x2F;&#x2F;gcc.gnu.org&#x2F;&quot;&gt;gcc&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;&quot;&gt;clang&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;text editor&lt;&#x2F;a&gt; that &lt;a href=&quot;&#x2F;images&#x2F;trollface.jpg&#x2F;&quot;&gt;&lt;em&gt;respects&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a Bash script to generate the project &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;boilerplate&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;Makefile&lt;&#x2F;a&gt; to format, build, install and run the program quickly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h2 id=&quot;types&quot;&gt;Types:&lt;&#x2F;h2&gt;
&lt;p&gt;Variable, a named location in the computer&#x27;s memory where data can be stored and accessed. Type, define the size, the format, the behavior, the operations that can be performed on the variable. Let&#x27;s talk about the common types in C programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;primitive&quot;&gt;Primitive types:&lt;&#x2F;h2&gt;
&lt;p&gt;Primitive data types, or &quot;basic data types&quot; or &quot;fundamental data types&quot; are the most basic data types that can be used for representing simple values such as numbers, characters, etc... The primitive data types are...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;integers&quot;&gt;Integer types&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;char: represents a single character (usually 1 byte)&lt;&#x2F;li&gt;
&lt;li&gt;short: represents a small integer&lt;&#x2F;li&gt;
&lt;li&gt;int: represents an integer&lt;&#x2F;li&gt;
&lt;li&gt;long: represents a long integer&lt;&#x2F;li&gt;
&lt;li&gt;long long: represents a very long integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned short: represent a small positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned int: represents a positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long: represents a long positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long long: represents a very long positive integer&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This list is not exhaustive, there is also what we call &lt;strong&gt;fixed width integer types&lt;&#x2F;strong&gt; and what we call &lt;strong&gt;minimum width integer types&lt;&#x2F;strong&gt;. We won&#x27;t talk about them here, please browse this &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdint.h.html&quot;&gt;link&lt;&#x2F;a&gt; for reference.&lt;&#x2F;p&gt;
&lt;p&gt;To find the range of a particular type, we can look for the &lt;code&gt;limits.h&lt;&#x2F;code&gt; file  &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;limits.h.html&quot;&gt;online&lt;&#x2F;a&gt;. Or, we can also look for the same file inside our computer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;limits.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;perl5&#x2F;5.32&#x2F;Tk&#x2F;pTk&#x2F;compat&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we open, let&#x27;s say, the file &lt;code&gt;&#x2F;usr&#x2F;include&#x2F;limits.h&lt;&#x2F;code&gt;, we can see interesting informations like :&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     UCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MIN     SCHAR_MIN
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     SCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed short int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MIN      (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32768&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32767
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned short int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define USHRT_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65535
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MIN       (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;INT_MAX &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MAX       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define UINT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4294967295&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;U
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed long int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  if __WORDSIZE == 64
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;9223372036854775807&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;floats&quot;&gt;Floating-point types:&lt;&#x2F;h3&gt;
&lt;p&gt;Used to represent real numbers with decimal points. More informations &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;float.h.html&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;float: represents a single-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;double: represents a double-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;long double: represents an extended-precision floating-point number&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is an example showing how to use float values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; radius, area;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter the radius of the circle: &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:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    radius = strtof(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    area = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Area of the circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, area);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have found the file containing all the constants definitions for float values, but I am not (yet) able to correctly understand what&#x27;s going on in this header file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;float.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is a snippet of things that may be of interest for anyone looking for the ranges:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defined&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt; __STDC_VERSION__ &amp;amp;&amp;amp; __STDC_VERSION__ &amp;gt; 201710L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum finite positive value with MANT_DIG digits in the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   significand taking their maximum value.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_NORM_MAX    __FLT_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_NORM_MAX    __DBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_NORM_MAX   __LDBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Whether each type matches an IEC 60559 format (1 for format, 2 for
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   format and operations).  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_IS_IEC_60559        __FLT_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_IS_IEC_60559        __DBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_IS_IEC_60559       __LDBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;bool&quot;&gt;Boolean type:&lt;&#x2F;h3&gt;
&lt;p&gt;The data type that can have two possible values: true or false. Include the &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdbool.h.html&quot;&gt;&quot;stdbool.h&quot;&lt;&#x2F;a&gt; header file in your program to use this data type. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdbool.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;strtobool(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const char* &lt;&#x2F;span&gt;&lt;span&gt;str) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;return true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;false&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;return false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    fprintf(stderr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Invalid input: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; answer[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; is_learning;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &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:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Are you learning C programming: &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:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(answer, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; answer, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    is_learning = strtobool(answer);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(is_learning)
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Very good, keep learning.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;You should learn C programming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;void&quot;&gt;Void type:&lt;&#x2F;h3&gt;
&lt;p&gt;Void is a keyword to use as a placeholder where you would put a data type, to represent &quot;no data&quot;. The void data type represents the absence of type. Void types are used in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;to state that the specific type of the variable is not known &lt;em&gt;yet&lt;&#x2F;em&gt; (void pointers).&lt;&#x2F;li&gt;
&lt;li&gt;to state that the function returns no result (void functions).&lt;&#x2F;li&gt;
&lt;li&gt;to state that the function has no parameters.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT: We can&#x27;t directly dereference void pointers because the compiler doesn&#x27;t know the size or type of data being pointed to. We need to explicitly cast them to the correct type before dereferencing.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here&#x27;s an example to illustrate the usage of void type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns no result
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes an unkown&#x2F;undefined list of arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice how we can pass all the arguments we want
&lt;&#x2F;span&gt;&lt;span&gt;  greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A function declared with the void data type can&#x27;t return a value, we cannot use the return keyword inside a void function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘greet’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:10: warning: ‘return’ with a value, in function returning void
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   return&lt;&#x2F;span&gt;&lt;span&gt; 5432&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|          &lt;&#x2F;span&gt;&lt;span&gt;^~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:56:6: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   56 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;void greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^~~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns an int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes no arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&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:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Because greet returns a result, I can retrieve and print it
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet());
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}                                                                                                            
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we try to pass an argument to the greet function, we will receive an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:44: error: too many arguments to function ‘greet’
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: %d\n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|                                            &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:52:5: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   52 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;int greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|     &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Last example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt; name = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nsukami_&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:#608b4e;&quot;&gt;&#x2F;&#x2F; foo is a pointer that point to a not yet knwon data type
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void*&lt;&#x2F;span&gt;&lt;span&gt; foo;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to an integer
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;age;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;age is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int*&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to something else, for ex, a string
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;name;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char**&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;composite&quot;&gt;Composite types&lt;&#x2F;h2&gt;
&lt;p&gt;Any data type which can be constructed using the language&#x27;s primitive data types and other composite types.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;structs&quot;&gt;Structures:&lt;&#x2F;h3&gt;
&lt;p&gt;Structs (short for structure), a user-defined data type that allows us to group together related data items of different types. Those data items are known as members or fields.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; An address is something with 2 attributes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a city street AND an house number
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; address {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; citystreet[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; housenumber;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&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:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Address my_address = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Planet 42, Rue de la Liberté&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:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  };
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; how to update one of the fields
&lt;&#x2F;span&gt;&lt;span&gt;  my_address.housenumber = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;443&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;enums&quot;&gt;Enum data type:&lt;&#x2F;h3&gt;
&lt;p&gt;An enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type defined by the user. An enumeration consists of a set of constant &lt;em&gt;integers&lt;&#x2F;em&gt; that are named by the user.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef enum&lt;&#x2F;span&gt;&lt;span&gt; Level {
&lt;&#x2F;span&gt;&lt;span&gt;  LOW = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  MEDIUM,
&lt;&#x2F;span&gt;&lt;span&gt;  HIGH
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Level level = MEDIUM;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch &lt;&#x2F;span&gt;&lt;span&gt;(level) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Low level&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:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Medium level&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:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;High level&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:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Unkown level value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We said earlier an enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type because.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;unions&quot;&gt;Unions:&lt;&#x2F;h3&gt;
&lt;p&gt;An union is a user-defined data type that allows different data types to be stored in the same memory location. It enables us to create a variable that can hold different types of data, but only one type at a time.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Struct that combines an enum and a union
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; The type of our object could be either INT, either FLOAT, either STRING
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    INT,
&lt;&#x2F;span&gt;&lt;span&gt;    FLOAT,
&lt;&#x2F;span&gt;&lt;span&gt;    STRING
&lt;&#x2F;span&gt;&lt;span&gt;  } type;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; all 3 values share the same memory location, only one can be set
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; value can be a int OR a float OR a string
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;union &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; intValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; floatValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; stringValue[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&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 style=&quot;color:#4ec9b0;&quot;&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Function to print the object based on its type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(Object o) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check the type of our object 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch&lt;&#x2F;span&gt;&lt;span&gt;(o.type) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;INT:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; then access the correct value
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Integer: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.intValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;FLOAT:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Float: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.floatValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case&lt;&#x2F;span&gt;&lt;span&gt; STRING:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;String: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.stringValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Creating objects of different types
&lt;&#x2F;span&gt;&lt;span&gt;  Object o1, o2, o3;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.type = INT;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.value.intValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.type = FLOAT;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.value.floatValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o3.type = STRING;
&lt;&#x2F;span&gt;&lt;span&gt;  strcpy(o3.value.stringValue, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&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:#608b4e;&quot;&gt;&#x2F;&#x2F; Printing the data objects
&lt;&#x2F;span&gt;&lt;span&gt;  print(o1);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o2);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o3);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;arrays&quot;&gt;Arrays:&lt;&#x2F;h3&gt;
&lt;p&gt;A type consisting of nonempty items of the same nature stored using contiguous memory location. The number of items (the size) never changes during the array lifetime. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; numbers[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2.5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4.2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.9&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5.6&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; size = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers) &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; sum = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, average;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        sum += numbers[i];
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    average = sum &#x2F; size;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Average: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, average);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;strings&quot;&gt;Strings:&lt;&#x2F;h3&gt;
&lt;p&gt;A string is just a sequence of characters stored inside an array and ending with the null character: &#x27;\0&#x27;. We don&#x27;t have strings as we have them in Python programming.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &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:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To know what are the functions available for string manipulation, Python developers will type &lt;code&gt;help(str)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;Help on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;module builtins:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt; |  str(object=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |  str(bytes_or_buffer[, encoding[, errors]]) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Create a new string object &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;the given object. If encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;or
&lt;&#x2F;span&gt;&lt;span&gt; |  errors &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is &lt;&#x2F;span&gt;&lt;span&gt;specified, then the object must expose a data buffer
&lt;&#x2F;span&gt;&lt;span&gt; |  that will be decoded using the given encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;error handler.
&lt;&#x2F;span&gt;&lt;span&gt; |  Otherwise, returns the result of object.__str__() (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;defined)
&lt;&#x2F;span&gt;&lt;span&gt; |  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;or &lt;&#x2F;span&gt;&lt;span&gt;repr(object).
&lt;&#x2F;span&gt;&lt;span&gt; |  encoding defaults to sys.getdefaultencoding().
&lt;&#x2F;span&gt;&lt;span&gt; |  errors defaults to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;strict&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Methods defined here:
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __add__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self+value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __contains__(self, key, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return bool(key &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self).
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __eq__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self==value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __format__(self, format_spec, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;C developers will look inside the &lt;code&gt;&amp;lt;string.h&amp;gt;&lt;&#x2F;code&gt; header &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;009695399&#x2F;basedefs&#x2F;string.h.html&quot;&gt;file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; find &#x2F;usr&#x2F;include -type f -name &amp;quot;string.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They can also read the man pages, &lt;code&gt;man string&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;STRING(3)                                  Linux Programmer&amp;#39;s Manual                                 STRING(3)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;NAME
&lt;&#x2F;span&gt;&lt;span&gt;       stpcpy,  strcasecmp, strcat, strchr, strcmp, strcoll, strcpy, strcspn, strdup, strfry, strlen, strncat,
&lt;&#x2F;span&gt;&lt;span&gt;       strncmp, strncpy, strncasecmp, strpbrk, strrchr, strsep, strspn, strstr, strtok, strxfrm, index, rindex
&lt;&#x2F;span&gt;&lt;span&gt;       - string operations
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SYNOPSIS
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;strings.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strcasecmp(const char *s1, const char *s2);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strncasecmp(const char *s1, const char *s2, size_t n);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the first n bytes of the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *index(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the first occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *rindex(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the last occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *stpcpy(char *dest, const char *src);
&lt;&#x2F;span&gt;&lt;span&gt;              Copy a string from src to dest, returning a pointer to the end of the resulting string at dest.
&lt;&#x2F;span&gt;&lt;span&gt; Manual page string(3) line 1 (press h for help or q to quit)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;constants&quot;&gt;Constants:&lt;&#x2F;h2&gt;
&lt;p&gt;A fixed value that cannot be, &lt;em&gt;that should not&lt;&#x2F;em&gt; be changed during the execution of a program.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If we have a fixed value that is used in calculations, we can define it as a constant to avoid hard-coding the value multiple times.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s define PI as a constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; PI = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14159&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; radius = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s reuse our constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; area = PI &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Trying to modify our constant will give us an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:129:6: error: assignment of read-only variable ‘PI’
&lt;&#x2F;span&gt;&lt;span&gt;  129 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;PI = 4.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Another way to use constants is this one. Instead of using arbitrary numbers directly in your code, you can define them as constants with meaningful names to improve code readability and maintainability.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; LENGTH = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MIN_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;18&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MAX_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[LENGTH];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your age: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  age = strtol(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(age &amp;lt; MIN_AGE || age &amp;gt; MAX_AGE) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; is an invalid age! Please enter an age between &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, age, MIN_AGE, MAX_AGE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;When declaring an array, we can use a constant to specify its size, making it easier to modify if needed.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; In this example, `ARRAY_SIZE` is declared as a constant to specify the size of an array. By using a
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; constant, you can easily change the size of the array by modifying the constant&amp;#39;s value in a single place.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; ARRAY_SIZE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[ARRAY_SIZE];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;We can also declare function parameters as &lt;code&gt;const&lt;&#x2F;code&gt; to ensure that the function does not modify the parameter:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; This helps prevent accidental modifications and indicates that the function is read-only.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int &lt;&#x2F;span&gt;&lt;span&gt;arr[], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;size) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;I really hope you&#x27;ve learned something. I did \o&#x2F; In the next episode, I will try to write about header files or pointers or something else depending on the current moon, the weather and the stars alignment. Also, thanks to &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@orbifx&quot;&gt;Orbifx&lt;&#x2F;a&gt; for taking the time to answer all my questions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hal.inria.fr&#x2F;hal-02383654&#x2F;file&#x2F;ModernC.pdf&quot;&gt;Modern C, Jens Gustedt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gnu-c-manual&#x2F;gnu-c-manual.pdf&quot;&gt;The GNU C Reference Manual&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;amjadmajid&#x2F;Makefile&quot;&gt;Explanation about how to write a Makefile&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n2655.pdf&quot;&gt;Make false and true first-class language features v4
proposal for C23&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;on-a-completely-differnt-note&quot;&gt;On a completely differnt note:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=snvzAfYOFks&quot;&gt;Des organismes aux algorithmes, l&#x27;odyssée computationnelle du vivant | Xavier Berthet | TEDxINPENSAT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;2023.djangocon.africa&#x2F;&quot;&gt;The first DjangoCon Africa, in Zanzibar, Tanzania.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decorators</title>
        <published>2023-02-06T00:00:00+00:00</published>
        <updated>2023-02-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/decor/"/>
        <id>https://nskm.xyz/posts/decor/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/decor/">&lt;p&gt;I was watching a &lt;em&gt;really&lt;&#x2F;em&gt; interesting &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=RL7BECNn-RI&quot;&gt;video&lt;&#x2F;a&gt; about buildings architecture in New York, when one of my &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;DIT&lt;&#x2F;a&gt; student asked me to explain to him what was happening in this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;flask-user-authentication-example&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;main&#x2F;utils.py#L7&quot;&gt;piece of code&lt;&#x2F;a&gt;. A function I have written few months ago to check for valid authentication tokens. In this post, I will try to show how decorators in &lt;a href=&quot;https:&#x2F;&#x2F;python.org&quot;&gt;Python&lt;&#x2F;a&gt;, a powerful concept, allows us to apply new functionality without modifying the existing structure of an object. &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=cDk9L72ZkuE&quot;&gt;Music please&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;decorated.png&quot; alt=&quot;&quot; title=&quot;Somewhere in Africa&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#f&quot;&gt;1 A function doing one thing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#g&quot;&gt;2 A decorator, modifying the behaviour of the function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#h&quot;&gt;3 A decorator should keep important informations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#i&quot;&gt;4 A decorator should receive a flexible number of argument&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#j&quot;&gt;5 A decorator can also have parameters&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#k&quot;&gt;6 We are still able to access the decorated function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#l&quot;&gt;7 An interesting example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#m&quot;&gt;8 Even more interesting, how decorators are used elsewhere&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;f&quot;&gt;1. A function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we want to join 2 paths:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pathlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]: a = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: a
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;]: b = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: a.joinpath(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s suppose we usually combine 2 paths together. So much that we created a function for that purpose:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;]: path_t = str | Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;22&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bar&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a, b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;g&quot;&gt;2. A decorator modifying the behaviour of the function:&lt;&#x2F;h1&gt;
&lt;p&gt;While it may seem confusing at first, a decorator is really just &lt;em&gt;a function that takes a function and returns a function&lt;&#x2F;em&gt;. Let me explain.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose we usually combine our home path with another path. Let&#x27;s suppose the first parameter is often our home path. Let&#x27;s suppose we can&#x27;t modify the original function. Python functions are &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_citizen&quot;&gt;first-class citizens&lt;&#x2F;a&gt;. That means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can pass a function as an argument of another function.&lt;&#x2F;li&gt;
&lt;li&gt;We can assign a function to a variable.&lt;&#x2F;li&gt;
&lt;li&gt;We can return a function as a value from another function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func: Callable[[path_t, path_t], path_t]) -&amp;gt; Callable[[path_t], path_t]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A wrapper that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;39&lt;&#x2F;span&gt;&lt;span&gt;]: f = homeprefix(jp)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: f(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: f(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: f(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;spam&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;spam&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As strange as it may seems, we could have done the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: jp = homeprefix(jp) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# there is an alternative syntax
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foobar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foobar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of &lt;code&gt;jp = homeprefix(jp)&lt;&#x2F;code&gt; we could use the following syntax which better vehicle our intent: &lt;strong&gt;modifying the behaviour of an existing function&lt;&#x2F;strong&gt;. Simply put: &lt;strong&gt;decorating&lt;&#x2F;strong&gt; our original function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;51&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here we are, decorating jp function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;56&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;h&quot;&gt;3. A decorator should keep important informations:&lt;&#x2F;h1&gt;
&lt;p&gt;Now we have another problem. Because we are literally replacing one function with another, we&#x27;re also losing important informations like the docstring and the name:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(m)
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that takes one parameter.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;59&lt;&#x2F;span&gt;&lt;span&gt;-b4f67b1e800d&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;wrapper&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s the reason we have &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html#functools.wraps&quot;&gt;functools.wraps&lt;&#x2F;a&gt;. &lt;code&gt;Wraps&lt;&#x2F;code&gt; takes the decorated function and adds the functionality of copying over the function name, docstring, arguments list, etc to &lt;strong&gt;the returned function&lt;&#x2F;strong&gt;. And since wraps is itself a decorator:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(path1: str | pathlib.Path, path2: str | pathlib.Path) -&amp;gt; str | pathlib.Path
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that join &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;paths together.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;-1703cd8a40dc&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;jp&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;68&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;i&quot;&gt;4. A decorator should receive a flexible number of argument:&lt;&#x2F;h1&gt;
&lt;p&gt;Now, let&#x27;s suppose our original function can take many arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;101&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&#x2F;abc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;abc&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous decorator is not flexible enough because the returned function can&#x27;t take more than 1 parameter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;106&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;107&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&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:#569cd6;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;a&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;---------------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;TypeError                                 Traceback (most recent call last)
&lt;&#x2F;span&gt;&lt;span&gt;Cell In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;], line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;----&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TypeError: jp() takes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;positional argument but &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;were given
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;110&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s rewrite our decorator so that the returned function can take an infinte number or arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;113&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(*args):  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here is our update: using *args 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;114&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: jp()
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;119&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the help of the special parameters *args and **kwargs, decorators become more generic. That way if we need the same kind of decorator in different functions with different arguments, we can write just one decorator. In general, a decorator is written like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;decorator(func):
&lt;&#x2F;span&gt;&lt;span&gt;    @wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;        func(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;j&quot;&gt;5. A decorator can also have parameters:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose people using the decorator want to be able to set what should the prefix used as the first parameter of our jp function. Let&#x27;s suppose we want the decorator to receive one parameter, which is the prefix:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;70&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(prefix): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function builds and returns a decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(func): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function is the decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the function wrapping the original function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(prefix, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;71&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&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:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We understand better what&#x27;s going on when we do this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: decorator = homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;patrick&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup a prefix 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;decorator  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# decorate 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;quux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;79&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;k&quot;&gt;6. We are still able to access the decorated function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose for some reason we want to test the function as if it was not decorated. Let&#x27;s suppose we still want to use the underlying function. To achieve that, we&#x27;ll use the &lt;code&gt;__wrapped__&lt;&#x2F;code&gt; attribute (assuming we used the &lt;code&gt;functools.wrap&lt;&#x2F;code&gt; function). &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html?highlight=__wrapped__&quot;&gt;Somewhere&lt;&#x2F;a&gt; in the documentation, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The original underlying function is accessible through the &lt;strong&gt;wrapped&lt;&#x2F;strong&gt; attribute. This is useful for introspection, for bypassing the cache, or for rewrapping the function with a different cache.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__wrapped__(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# original function 
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;129&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;l&quot;&gt;7. An interesting example:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;csv
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(db):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to connect to an SQLite database and execute a query.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            rset = conn.execute(query).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rset
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;columns, limit=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to specify what columns should be retrieved.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cols = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.join(columns)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            start, end = query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].strip(), query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].strip()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{start} {cols} {end}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; limit &lt;&#x2F;span&gt;&lt;span&gt;{limit}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;as_csv(where=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;result.csv&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:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to save the result as a csv file.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            rset = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(where, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;w&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, newline=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;dest:
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer = csv.writer(
&lt;&#x2F;span&gt;&lt;span&gt;                    dest, delimiter=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;,&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, quoting=csv.QUOTE_ALL, lineterminator=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                )
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer.writerows(rset)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;len(rset)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;###
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@as_csv()
&lt;&#x2F;span&gt;&lt;span&gt;@connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;@columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;artistId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;run(table=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;albums&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    query = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{table}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;query
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    print(run())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;8-even-more-interesting&quot;&gt;8. Even more interesting:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# sqlite3.IMMEDIATE
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;conn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, conn)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls.conn.execute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{cls.__name__}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, select)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@select
&lt;&#x2F;span&gt;&lt;span&gt;@connect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Albums:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    a = Albums()
&lt;&#x2F;span&gt;&lt;span&gt;    print(a.select())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;m&quot;&gt;8. Even more interesting, how decorators are used elsewhere:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cubicweb.org&#x2F;&quot;&gt;Cubicweb&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubes&#x2F;api&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;cubicweb_api&#x2F;routes.py#L137&quot;&gt;decorator&lt;&#x2F;a&gt; used to raise an AuthenticationError if no user is detected.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pallets&#x2F;flask&#x2F;blob&#x2F;afc13b9390ae2e40f4731e815b49edc9ef52ed4b&#x2F;examples&#x2F;tutorial&#x2F;flaskr&#x2F;auth.py#L19&quot;&gt;decorator&lt;&#x2F;a&gt;  that redirects anonymous users to the login page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;patterns&#x2F;viewdecorators&#x2F;#templating-decorator&quot;&gt;Templating decorator&lt;&#x2F;a&gt; invented by the &lt;a href=&quot;https:&#x2F;&#x2F;turbogears.org&#x2F;&quot;&gt;TurboGears&lt;&#x2F;a&gt; guys a while back to automatically render a template.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;main&#x2F;django&#x2F;views&#x2F;decorators&#x2F;http.py&quot;&gt;decorators&lt;&#x2F;a&gt; to manipulate &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Headers&quot;&gt;http headers&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;9-more-on-this-topic&quot;&gt;9. More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I hope that you found this post helpful. To learn about this topic, please, browse the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0318&#x2F;&quot;&gt;PEP 318 – Decorators for Functions and Methods&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;wiki.python.org&#x2F;moin&#x2F;PythonDecoratorLibrary&quot;&gt;PythonDecoratorLibrary&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html&quot;&gt;functools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;glossary.html#term-decorator&quot;&gt;decorator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;sqlite3.html#&quot;&gt;DB-API 2.0 interface for SQLite databases&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;15357776&#x2F;what-is-the-difference-between-functools-wraps-and-update-wrapper&quot;&gt;The difference between wraps and update_wrapper&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.artima.com&#x2F;weblogs&#x2F;viewpost.jsp?thread=241209&quot;&gt;Python Decorators III: A Decorator-Based Build System&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;2692&#x2F;&quot;&gt;Interior decorating&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Test driven interview</title>
        <published>2022-10-16T00:00:00+00:00</published>
        <updated>2022-10-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/tdi/"/>
        <id>https://nskm.xyz/posts/tdi/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/tdi/">&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Test Driven Development &lt;em&gt;TDD&lt;&#x2F;em&gt; is a method of implementing software that rely on software requirements being converted to test cases before software is fully developed.&lt;&#x2F;p&gt;
&lt;p&gt;Red, Green and Refactor is the 3 phases of TDD. When followed, this order of steps helps ensure that you have tests for the code you are writing and you are writing only the code that you have to test for.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;context&quot;&gt;Context:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we should implement some requirements. Let&#x27;s suppose all the requirements and specifications are written using unit tests. See this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&quot;&gt;repository&lt;&#x2F;a&gt;. Our mission is to write enough code to make all the tests pass. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=gptoH8rzG14&quot;&gt;dive in&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#tests&quot;&gt;Tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Requirements&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#firstreq&quot;&gt;First requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#secondreq&quot;&gt;Second requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#thirdreq&quot;&gt;Third requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fourthreq&quot;&gt;Fourth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fifthreq&quot;&gt;Fifth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#lastreq&quot;&gt;Last requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git create-branch feat-1  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a new branch for feature work
&lt;&#x2F;span&gt;&lt;span&gt;Basculement sur la nouvelle branche &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; python3.10 -m venv .env  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; source .env&#x2F;bin&#x2F;activate  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# activate virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; pip install -r requirements.txt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# install requirements
&lt;&#x2F;span&gt;&lt;span&gt;Collecting django&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.2,&amp;gt;=3.1
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached Django-3.1.14-py3-none-any.whl (7.8 MB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting djangorestframework&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.13,&amp;gt;=3.12
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached djangorestframework-3.12.4-py3-none-any.whl (957 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting sqlparse&amp;gt;=0.2.2
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached sqlparse-0.4.3-py3-none-any.whl (42 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting asgiref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;,&amp;gt;=3.2.10
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached asgiref-3.5.2-py3-none-any.whl (22 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting pytz
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached pytz-2022.4-py2.py3-none-any.whl (500 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Installing collected packages: pytz, sqlparse, asgiref, django, djangorestframework
&lt;&#x2F;span&gt;&lt;span&gt;Successfully installed asgiref-3.5.2 django-3.1.14 djangorestframework-3.12.4 pytz-2022.4 sqlparse-0.4.3
&lt;&#x2F;span&gt;&lt;span&gt;WARNING: You are using pip version 22.0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;however, version 22.3 is available.
&lt;&#x2F;span&gt;&lt;span&gt;You should consider upgrading via the &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;.env&#x2F;bin&#x2F;python3.10 -m pip install --upgrade pip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; command.
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;tests&quot;&gt;How to launch tests ?&lt;&#x2F;h2&gt;
&lt;p&gt;According to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;#running-tests&quot;&gt;documentation&lt;&#x2F;a&gt;, we can run tests using the test command of your project&#x27;s manage.py utility. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;eradman.com&#x2F;entrproject&#x2F;&quot;&gt;run that command&lt;&#x2F;a&gt; when any of the Python files changes. We also tell Django to stop running the test suite after first failed test. In a different terminal, let&#x27;s type one of the following commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask git ls-files command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; git ls-files&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt; -- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.py&amp;#39; &amp;#39;:!:*__.py&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask find command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; find src -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -not -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__*&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the ack command seems more readable
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; ack -f --python &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Here is our first error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;django.db.utils.OperationalError: no such table: inventory_product
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;firstreq&quot;&gt;1. First requirements: we need a Product model.&lt;&#x2F;h2&gt;
&lt;p&gt;We need to create a model named Product inside an application named inventory. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L12&quot;&gt;Somewhere&lt;&#x2F;a&gt; within the tests file, we can read:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create_coke(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Product.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;            description=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            unit_price=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            stock=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;models.py#L4&quot;&gt;open&lt;&#x2F;a&gt; the &lt;code&gt;models.py&lt;&#x2F;code&gt; file and write the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After running the migration scripts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py makemigrations &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;python src&#x2F;manage.py migrate
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The tests tells us to return an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;201&quot;&gt;http status 201&lt;&#x2F;a&gt; after Product creation. Right now, we have a 404. We need to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;create a REST API.&lt;&#x2F;li&gt;
&lt;li&gt;we should be able to create a Product via the API.&lt;&#x2F;li&gt;
&lt;li&gt;and the returned http status should be 201 _created.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 45, in test_create_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 1 test in 0.010s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;secondreq&quot;&gt;We need a REST API for managing a Product.&lt;&#x2F;h2&gt;
&lt;p&gt;Another &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L44&quot;&gt;part&lt;&#x2F;a&gt; of the tests is telling us we need an url named &lt;code&gt;api&#x2F;products&#x2F;&lt;&#x2F;code&gt;. Let&#x27;s create a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;serializers&#x2F;#modelserializer&quot;&gt;serializer&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;viewsets&#x2F;#modelviewset&quot;&gt;viewset&lt;&#x2F;a&gt; and a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;routers&#x2F;&quot;&gt;router&lt;&#x2F;a&gt;. Here is the code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;modules&#x2F;inventory&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Product
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Product
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__all__&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;pos&#x2F;urls.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;path, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.inventory.views &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;products&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, ProductsViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;api&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After the changes, we notice some progress. The test tells us that if we attempt to delete a Product, we should receive an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;405&quot;&gt;http status 405&lt;&#x2F;a&gt; instead of 204. Litteraly, we have been able to delete a Product while it shouldn&#x27;t be allowed:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_delete_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 142, in test_delete_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 405)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 204 != 405
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 2 tests in 0.011s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;thirdreq&quot;&gt;A Product cannot be deleted.&lt;&#x2F;h2&gt;
&lt;p&gt;I should have take the time to carefully read all the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L139&quot;&gt;Indeed&lt;&#x2F;a&gt;, one of them clearly states that we can&#x27;t delete a Product. Obviously, the ModelViewSet is not a good choice. We should update our viewset in a way that forbids product deletion. The operations: &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L36&quot;&gt;creating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L18&quot;&gt;listing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L95&quot;&gt;updating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L57&quot;&gt;getting one product&lt;&#x2F;a&gt; should still be permitted. To achieve that, we&#x27;ll use some &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;generic-views&#x2F;#mixins&quot;&gt;mixins&lt;&#x2F;a&gt; offered by the framework. The product viewset becomes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets, mixins
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.UpdateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;let-s-commit-what-have-been-done-so-far&quot;&gt;Let&#x27;s commit what have been done so far.&lt;&#x2F;h3&gt;
&lt;p&gt;All the tests related to Product are passing. We can commit and push what we&#x27;ve done so far.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git commit -m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Add Product API&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;[feat-1 a11ffeb] Add Product API
&lt;&#x2F;span&gt;&lt;span&gt; 5 files changed, 76 insertions(+), 6 deletions(-)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;inventory&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt; rewrite src&#x2F;modules&#x2F;inventory&#x2F;views.py (98%)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;orders&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git push origin feat-1 
&lt;&#x2F;span&gt;&lt;span&gt;Énumération des objets: 25, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Décompte des objets: 100% (24&#x2F;24), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Compression par delta en utilisant jusqu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;à 4 fils d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;exécution
&lt;&#x2F;span&gt;&lt;span&gt;Compression des objets: 100% (14&#x2F;14), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Écriture des objets: 100% (14&#x2F;14), 1.80 Kio &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;1.80 Mio&#x2F;s, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Total 14 (delta 6), réutilisés 0 (delta 0), réutilisés du pack 0
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: Create a new pull request for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;remote:   https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;compare&#x2F;master...feat-1
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: . Processing 1 references
&lt;&#x2F;span&gt;&lt;span&gt;remote: Processed 1 references in total
&lt;&#x2F;span&gt;&lt;span&gt;To https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview.git
&lt;&#x2F;span&gt;&lt;span&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;new branch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;      feat-1 -&amp;gt; feat-1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width:100; height:100&quot; src=&quot;&#x2F;images&#x2F;ofcourse.gif&quot; alt=&quot;Of course&quot; title=&quot;Of course&quot;&#x2F;&gt;
&lt;h2 id=&quot;fourthreq&quot;&gt;We need another model named Order.&lt;&#x2F;h2&gt;
&lt;p&gt;All the tests located in the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&quot;&gt;inventory&lt;&#x2F;a&gt; application are passing. This is why we decided to commit and push. There is one test currently failing, it it located inside the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&quot;&gt;orders&lt;&#x2F;a&gt; application. The test tells us we need to create a model named Order:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_order (modules.orders.tests.OrdersTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 87, in test_create_order
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 7 tests in 0.054s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s continue reading the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L90&quot;&gt;Line 90&lt;&#x2F;a&gt;, we read that an item should have 4 attributes: &lt;code&gt;description, quantity, unit_price, total&lt;&#x2F;code&gt;. We also read that an Order has 2 attributes: &lt;code&gt;items&lt;&#x2F;code&gt; and &lt;code&gt;total&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;order = Order.objects.get()
&lt;&#x2F;span&gt;&lt;span&gt;expected = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;id&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: order.id,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;items&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;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&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:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&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:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Potato Chips&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:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2000&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:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, our models may look like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Order(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this field is just a sum, depending on all the items in the current Order
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([x.total &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.items.all()])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderItem(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    order = models.ForeignKey(Order, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, on_delete=models.CASCADE)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# For being able to retrieve the description and the unit_price fields ?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I add Product as a foreign key ? 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I duplicate the fields ?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the total is obviouly a property that will be calculated 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# based on the number of items in the Order &amp;amp; the unit price for each item 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;float(self.unit_price * self.quantity)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;fifthreq&quot;&gt;We should be able to update the stock depending on the number of items ordered:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L114&quot;&gt;Line 114&lt;&#x2F;a&gt; of the tests tells us, a Product should have a method to refresh its stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;pyhon&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-pyhon &quot;&gt;&lt;code class=&quot;language-pyhon&quot; data-lang=&quot;pyhon&quot;&gt;&lt;span&gt;self.chips.refresh_from_db()
&lt;&#x2F;span&gt;&lt;span&gt;self.assertEqual(self.chips.stock, 8)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s update our Product model and add the new method. This method will substract the number of Product ordered from the current stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;refresh_from_db(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.orders.models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        self.stock = self.stock - sum(
&lt;&#x2F;span&gt;&lt;span&gt;            oi.quantity &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;oi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;OrderItem.objects.filter(id=self.id)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        self.save()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;lastreq&quot;&gt;We should be able to update a Product without modifiying already made Orders:&lt;&#x2F;h2&gt;
&lt;p&gt;After reading the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L141&quot;&gt;Line 141&lt;&#x2F;a&gt;, we know that the fields &lt;code&gt;description and unit_price&lt;&#x2F;code&gt; will be duplicated inside the OrderItem model. During the OrderItem creation, we should copy those fields from the Product model. This task will be achieved using our serializers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ItemSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    quantity = serializers.IntegerField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = serializers.FloatField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    description = serializers.CharField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&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:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unit_price&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&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:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    items = ItemSerializer(many=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create(self, validated_data):
&lt;&#x2F;span&gt;&lt;span&gt;        order = Order.objects.create()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I want to be able to access the id, the id represent the Product id
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# So, I&amp;#39;m using initial_data instead of validated_data
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I&amp;#39;ll need to find a proper way
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;item_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.initial_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]:
&lt;&#x2F;span&gt;&lt;span&gt;            product = Product.objects.get(id=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;            OrderItem.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;                id=product.id,
&lt;&#x2F;span&gt;&lt;span&gt;                order=order,
&lt;&#x2F;span&gt;&lt;span&gt;                description=product.description,
&lt;&#x2F;span&gt;&lt;span&gt;                unit_price=product.unit_price,
&lt;&#x2F;span&gt;&lt;span&gt;                quantity=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;order
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Order
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&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:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrdersViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&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;    queryset = Order.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = OrderSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s been a long time since I&#x27;ve written Django and DRF code. I really enjoyed the exercise. The final result can be found &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py test src --failfast
&lt;&#x2F;span&gt;&lt;span&gt;Creating test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;............
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 12 tests in 0.093s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;OK
&lt;&#x2F;span&gt;&lt;span&gt;Destroying test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;while-i-still-have-your-attention&quot;&gt;While I still have your attention:&lt;&#x2F;h1&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;djangochat.com&#x2F;episodes&#x2F;django-unicorn-adam-hill&quot;&gt;conversation&lt;&#x2F;a&gt; with Adam Hill about writing software, the perfect settings file set up, and more. Adam is a software engineer at The Motley Fool and the author of multiple open source packages including &lt;a href=&quot;https:&#x2F;&#x2F;www.django-unicorn.com&#x2F;&quot;&gt;Django Unicorn&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The videos for the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0kOLsFQGxyk&amp;amp;list=PLY_che_OEsX3eIKKLUKvQXfVJhCHYWATM&quot;&gt;DjangoCon Europe 2022&lt;&#x2F;a&gt; are available. Can someone tell me please when the &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;weblog&#x2F;2019&#x2F;nov&#x2F;18&#x2F;introducing-djangocon-africa&#x2F;&quot;&gt;DjangoCon Africa&lt;&#x2F;a&gt; event will be held ? So I can prepare myself ?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you have learned something. To dive even more deeper in the topic, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;125&#x2F;&quot;&gt;Marketing interview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Test-driven_development&quot;&gt;Test Driven Development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;unittest.html&quot;&gt;Unit testing framework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Learn&#x2F;Server-side&#x2F;Django&#x2F;Testing&quot;&gt;Testing a Django web application&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;test-driven-django-development.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Test Driven Web Development with Django&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;&quot;&gt;Writing and running tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;google.aip.dev&#x2F;&quot;&gt;API Improvement Proposal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfpa&#x2F;&quot;&gt;Django single file project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=rR4n-0KYeKQ&quot;&gt;How we write&#x2F;review code in big tech companies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Linear regression</title>
        <published>2022-07-24T00:00:00+00:00</published>
        <updated>2022-07-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/linreg/"/>
        <id>https://nskm.xyz/posts/linreg/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/linreg/">&lt;p&gt;For the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Technology&lt;&#x2F;a&gt;, I give Python introductory classes. During one of my sessions I was asked about simple linear regression with Python. Let the music &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=adBfKzfemtI&quot;&gt;play&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;disclaimer_not_ds.0eb9147b61b70fa9.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#introduction&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#first-solution&quot;&gt;First solution&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#reading-the-data-set&quot;&gt;Reading the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#plotting-the-data-set&quot;&gt;Plotting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#splitting-the-data-set&quot;&gt;Splitting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#ordinary-least-squares&quot;&gt;Least squares estimates&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#mean&quot;&gt;Mean&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#variance&quot;&gt;Variance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#covariance&quot;&gt;Covariance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#estimates&quot;&gt;Estimates&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#prediction&quot;&gt;Prediction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#error&quot;&gt;How good is the model&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#final-plot&quot;&gt;Regression line&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#class&quot;&gt;The complete program&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#statistics&quot;&gt;Another solution using the statistics module&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#code&quot;&gt;Just give me the code please&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Simple linear regression is a commonly used type of predictive analysis. The idea of regression is to examine if a set of predictor variables do a good job in predicting an outcome variable.&lt;&#x2F;p&gt;
&lt;p&gt;Linear regression models are used in many industries such as healthcare (predicting disease from biological factors), economics (predicting growth), businesses (predicting product sales), etc ...&lt;&#x2F;p&gt;
&lt;p&gt;For simple linear regression, the relationship between the independent variable &lt;strong&gt;x&lt;&#x2F;strong&gt; and the dependent variable &lt;strong&gt;y&lt;&#x2F;strong&gt; is expressed as: &lt;code&gt;y = slope * x + intercept + noise&lt;&#x2F;code&gt;, where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;slope&lt;&#x2F;em&gt; and &lt;em&gt;intercept&lt;&#x2F;em&gt; are the regression parameters that are estimated&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;noise&lt;&#x2F;em&gt; is the variability of the data (difference between predicted and actual values of &lt;strong&gt;y&lt;&#x2F;strong&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;first-solution&quot;&gt;First solution:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s write a Python program to achieve this task. We&#x27;ll use the following &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reading-the-data-set&quot;&gt;1. Reading the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;To read the data, we&#x27;ll write a function in charge of opening and reading the file containing our data. We assume each line will consist of an int value, followed by a tabulation and a float value. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;open the file&lt;&#x2F;li&gt;
&lt;li&gt;get all the lines except the first one (the header)&lt;&#x2F;li&gt;
&lt;li&gt;convert first column to int, convert second column to float&lt;&#x2F;li&gt;
&lt;li&gt;return a tuple containing 2 things:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;read_text(
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, t.AnyStr],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[t.Collection[float], t.Collection[float]]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;        slines = [line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]]
&lt;&#x2F;span&gt;&lt;span&gt;        nlines = [(int(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;        X, Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X, Y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Bonjour&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plotting-the-data-set&quot;&gt;2. Plotting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll have to do some plotting. The following program is just one we use to setup our &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.subplots.html#matplotlib-pyplot-subplots&quot;&gt;plots&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;_, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first step in finding a linear regression equation is to determine if there is a relationship between the two variables. To determine if there is a relationship between x and y we can scatter plot the data set.&lt;&#x2F;p&gt;
&lt;p&gt;Scatter plots are used to observe relationships between variables. We&#x27;ll need one function to do a scatter plot: put dots on our graph and see each individual data point.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(
&lt;&#x2F;span&gt;&lt;span&gt;    x: t.Collection[float], y: t.Collection[float], ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    ax.scatter(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this function with our &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;, we can see the following chart:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;scatter_plot.04b695a96b3966b3.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ll need a function to draw a line. If we correctly find estimates for our regression parameters (slope and the intercept), we should be able to draw a line that will go through the cloud of data points:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(a: int, b: int, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;    ax.plot(x, y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;splitting-the-data-set&quot;&gt;3. Splitting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We don’t want our model to over learn from the data and perform poorly when presented data never seen before. We also need to have a mechanism to assess how well our model is generalizing. Hence, we&#x27;ll need to separate our input data into &lt;em&gt;at least&lt;&#x2F;em&gt; 2 sets: training and testing:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-training-data-set&quot;&gt;1. Training data set:&lt;&#x2F;h4&gt;
&lt;p&gt;This is the set of data that will be used only for learning. We will use only one part of the data set to find the best parameters for our model.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-testing-data-set&quot;&gt;2. Testing data set:&lt;&#x2F;h4&gt;
&lt;p&gt;It would be best if we evaluate the model with new data that hasn’t been seen by the model before. So we need a set of data used to provide an evaluation without bias of the model that was fitted on the training data set.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s write a function that will split our data. We&#x27;ll keep 80% for the training and 20% for testing. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;randomly pick 20% of all the indexes in our collection&lt;&#x2F;li&gt;
&lt;li&gt;with those 20% indexes, create a list containing 20% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;from those 20% indexes, create a list containing 80% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;return all the sets&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;split_seq = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;split_train_test(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float], Y: t.Collection[float], frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; split_seq:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    indexes = list(range(len(X)))
&lt;&#x2F;span&gt;&lt;span&gt;    indexes_test = set(random.sample(indexes, int(frac * len(X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X_train, X_test, Y_train, Y_test
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s visualize how the 2 sets are rendered in a scatter plot:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;train_test_split.01769c608aeb949a.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;ordinary-least-squares&quot;&gt;4. Least squares for the slope and the intercept:&lt;&#x2F;h1&gt;
&lt;p&gt;How do we estimate our parameters α and β ? That’s the learning procedure. There are different optimization techniques to implement this part. To determine the optimum values of these two parameters, we should find the line that best fit the data set.&lt;&#x2F;p&gt;
&lt;p&gt;To determine the optimum values of these two parameters, we need to find the &lt;strong&gt;slope&lt;&#x2F;strong&gt; and the &lt;strong&gt;intercept&lt;&#x2F;strong&gt; so that when we sum all the errors between the predicted y values and the observed y values, this sum should be the least possible.&lt;&#x2F;p&gt;
&lt;p&gt;The following chart will show us all the distances (or all the differences, or all the errors) between each point on the dataset and the regression line:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_OLS.9924776937a70e5c.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s see how the chart looks like when the parameters are not correctly estimated &lt;em&gt;(the regression line does not &quot;fit&quot; the data set)&lt;&#x2F;em&gt; :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_bad_OLS.3f873a7960094d1f.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;And here is the function used to plot the errors. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Take the estimated coefficients α and β&lt;&#x2F;li&gt;
&lt;li&gt;Take the list of X and the list of Y&lt;&#x2F;li&gt;
&lt;li&gt;For all points in our data set:
&lt;ul&gt;
&lt;li&gt;predict &lt;code&gt;y&lt;&#x2F;code&gt; based on α and β&lt;&#x2F;li&gt;
&lt;li&gt;draw a dashed line between 2 points: &lt;code&gt;(x, y)&lt;&#x2F;code&gt; and &lt;code&gt;(x, y_pred)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_errors(
&lt;&#x2F;span&gt;&lt;span&gt;    a: float,
&lt;&#x2F;span&gt;&lt;span&gt;    b: float,
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        y_pred = a * x + b
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot([x, x], [y, y_pred], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Errors&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dashed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;the-total-error-of-this-model-is-the-sum-of-all-the-errors-for-each-point&quot;&gt;The total error of this model is the sum of all the errors for each point:&lt;&#x2F;h1&gt;
&lt;p&gt;We should sum all the errors and look for the least error. Here is the formula:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The SSE (Sum of Squared Errors) is equal to the sum of the square of Y observed - Y calculated, for all point in the data set.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;lse_formula.1b56ea6087956cd1.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;If we do all the correct &lt;a href=&quot;&#x2F;assets&#x2F;Simple_Linear_Regression_Leastsquares.pdf&quot;&gt;algebraic manipulation&lt;&#x2F;a&gt;, we should find that:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;slope_intercept_formulas.4b449a01bfa75294.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;p&gt;Seeing those formulas, those familiar with statistics already know we&#x27;ll need to define a function to calculate a mean, another function to calculate a variance and a function to calculate a covariance. βeta hat can be defined as Covariance(X, Y) &#x2F; Variance(X).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mean&quot;&gt;5.1 Mean:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;arithmetic&lt;&#x2F;em&gt; mean, is a measure of central tendency of a finite set of numbers: specifically, the sum of the values divided by the number of values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;mean(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;variance&quot;&gt;5.2 Variance:&lt;&#x2F;h2&gt;
&lt;p&gt;The variance  is the measure of the &lt;strong&gt;spread&lt;&#x2F;strong&gt; in a data set. The variance is a measure of how far each number in the data set is from the mean, and thus from every other number in the data set. The higher the variance, the more spread out the variables are.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;variance(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    m = mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;variance: 582.8381391772394
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is 2 ways to plot the variance. We can do it manually, or we can use a &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.boxplot.html#matplotlib-pyplot-boxplot&quot;&gt;box plot&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_variance.b71e17d987149681.png&quot; &#x2F;&gt;

&lt;&#x2F;center&gt;
  &lt;img style=&quot;display: block; margin: 0 auto&quot; src=&quot;&#x2F;assets&#x2F;jcvd_split.gif&quot; alt=&quot;Jean-Claude Van Damme split looks like a box plot&quot; title=&quot;Jean-Claude Van Damme split looks like a box plot&quot;&#x2F;&gt;
&lt;br&gt;
&lt;p&gt;Here is the function used to plot the variance:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_variance(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    _, ax = plt.subplots(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of variance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&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:#608b4e;&quot;&gt;# box plot
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].boxplot([X], vert=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;, showmeans=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&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:#608b4e;&quot;&gt;# mean line
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].axvline(x=mean(X), ymin=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, ymax=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;orange&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:#608b4e;&quot;&gt;# distance from point to mean line
&lt;&#x2F;span&gt;&lt;span&gt;    x_mean = mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].plot(
&lt;&#x2F;span&gt;&lt;span&gt;            [x, x_mean],
&lt;&#x2F;span&gt;&lt;span&gt;            [y, y],
&lt;&#x2F;span&gt;&lt;span&gt;            marker=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;o&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Mean&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dotted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;    plt.show()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;covariance&quot;&gt;5.3 Covariance:&lt;&#x2F;h2&gt;
&lt;p&gt;The covariance is a measure of the relationship between two variables. Covariance is the extent to which the variance in one variable depends on another variable. The higher the covariance, the stronger the relationship.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;covariance(X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_x, mean_y, length_x = mean(X), mean(Y), len(X)
&lt;&#x2F;span&gt;&lt;span&gt;    covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;        covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; length_x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;covariance: 2059.003344867359
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;estimates&quot;&gt;5.4 Estimates:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a function for calculating the variance and another one for calculating the covariance, we can write a function that will calculate our slope and our intercept using this 2 formulas seen earlier:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(X: t.Collection[float], Y: t.Collection[float]) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    b1 = covariance(X, Y) &#x2F; variance(X)
&lt;&#x2F;span&gt;&lt;span&gt;    b0 = mean(Y) - b1 * mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;prediction&quot;&gt;5.5. Prediction:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have extracted our coefficients, let&#x27;s see if we can make a prediction, we&#x27;ll use the testing data set:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;b, a = estimate_coefficients(X_train, Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;Y_predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;X_test]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(Y_test, Y_predicted):
&lt;&#x2F;span&gt;&lt;span&gt;    print(i, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, j)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# print Y observed in testing set next to Y predicted using our coefficients
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt; python3 script.py
&lt;&#x2F;span&gt;&lt;span&gt;392.5 	 389.8167994835544
&lt;&#x2F;span&gt;&lt;span&gt;15.7 	 65.88576964183908
&lt;&#x2F;span&gt;&lt;span&gt;48.8 	 45.426967757099156
&lt;&#x2F;span&gt;&lt;span&gt;113.0 	 99.98377278307227
&lt;&#x2F;span&gt;&lt;span&gt;48.7 	 52.246568385345796
&lt;&#x2F;span&gt;&lt;span&gt;40.3 	 38.607367128852516
&lt;&#x2F;span&gt;&lt;span&gt;59.6 	 76.11517058420904
&lt;&#x2F;span&gt;&lt;span&gt;152.8 	 147.72097718079874
&lt;&#x2F;span&gt;&lt;span&gt;73.4 	 161.360178437292
&lt;&#x2F;span&gt;&lt;span&gt;21.3 	 59.066169013592436
&lt;&#x2F;span&gt;&lt;span&gt;55.6 	 48.83676807122248
&lt;&#x2F;span&gt;&lt;span&gt;194.5 	 123.85237498193551
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;error&quot;&gt;5.6. How good is our model:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to able to measure how good our model is. Among the methods available to achieve this task, let&#x27;s use the most common and the most used: the &lt;a href=&quot;#&quot;&gt;Root mean squared error&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rmse&quot;&gt;RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;One way (the most common way?) to assess how well our model fits our data set is to calculate the Root Mean Squared Error. The RMSE is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the square root&lt;&#x2F;li&gt;
&lt;li&gt;of the mean&lt;&#x2F;li&gt;
&lt;li&gt;of the square of all of the errors&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s write a function to calculate the RMSE:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(actual: t.Sequence[float], predicted: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    sum_error = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual)):
&lt;&#x2F;span&gt;&lt;span&gt;        prediction_error = predicted[i] - actual[i]
&lt;&#x2F;span&gt;&lt;span&gt;        sum_error += prediction_error**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum_error &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we develop mutliple models, and we want to verify which one performs better:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Calculate the RMSE value for each model&lt;&#x2F;li&gt;
&lt;li&gt;The lower the RMSE value, the better the model.&lt;&#x2F;li&gt;
&lt;li&gt;A RMSE value of 0 indicate a perfect fit.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The data set we&#x27;re working with has a range: [Y_min, Y_max]. This range is important in determining whether a given RMSE value is &quot;low&quot; or &quot;high&quot;. There is no &quot;good&quot; or no &quot;bad&quot; RMSE value. It always depends on the range of the data set we&#x27;re working with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;normalized-rmse&quot;&gt;Normalized RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;The NRMSE is the RMSE divided by Y_max - Y_min. The result will be between 0 and 1, where values closer to 0 represent better fitting models. The normalization facilitates the comparison between data sets with different scales:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(
&lt;&#x2F;span&gt;&lt;span&gt;    actual: t.Sequence[float], predicted: t.Sequence[float]
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum([(predicted[i] - actual[i])**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]) &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;    nrmse = rmse &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python3 script.py 
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE is 23.27666203730159
&lt;&#x2F;span&gt;&lt;span&gt;Normalized RMSE is 0.06371542339113609
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;final-plot&quot;&gt;5.7. Regression line:&lt;&#x2F;h2&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plot_regression_line.156ebbadc8a6d8e7.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;class&quot;&gt;The complete program:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;math
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;random
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;requests  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;mpl  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib.pyplot &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;plt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dataclasses &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;dataclass, field
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup plots
&lt;&#x2F;span&gt;&lt;span&gt;fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;fig, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;splits = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&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;@dataclass
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;SimpleLinearRegression:
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, str] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;dataset.txt&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    __X: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    __Y: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__post_init__(self) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(self.filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;            slines = [
&lt;&#x2F;span&gt;&lt;span&gt;                line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]
&lt;&#x2F;span&gt;&lt;span&gt;            ]
&lt;&#x2F;span&gt;&lt;span&gt;            nlines = [(float(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;            self.__X, self.__Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;            self.__split_train_test()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(self, ax: mpl.axes.Axes, color: str = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        ax.scatter(self.__X, self.__Y, color=color, label=label)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(self, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__mean(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__var(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        m = self.__mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__cov(self, X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x = self.__mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;        mean_y = self.__mean(Y)
&lt;&#x2F;span&gt;&lt;span&gt;        covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;            covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; len(X)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__split_train_test(self, frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        indexes = list(range(len(self.__X)))
&lt;&#x2F;span&gt;&lt;span&gt;        indexes_test = set(random.sample(indexes, int(frac * len(self.__X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(
&lt;&#x2F;span&gt;&lt;span&gt;        self,
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x, mean_y = self.__mean(self.X_train), self.__mean(self.Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;        b1 = self.__cov(self.X_train, self.Y_train) &#x2F; self.__var(  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;            self.X_train
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        b0 = mean_y - b1 * mean_x
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(self) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.X_test]
&lt;&#x2F;span&gt;&lt;span&gt;        actual = self.Y_test
&lt;&#x2F;span&gt;&lt;span&gt;        mean_error = sum(
&lt;&#x2F;span&gt;&lt;span&gt;            [(predicted[i] - actual[i]) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;        ) &#x2F; float(
&lt;&#x2F;span&gt;&lt;span&gt;            len(actual)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;        nrmse = math.sqrt(mean_error) &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# program entry point
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;main() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        model = SimpleLinearRegression()
&lt;&#x2F;span&gt;&lt;span&gt;        model.scatter_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        model.line_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = model.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        rmse, nrmse = model.rmse()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The slope is &lt;&#x2F;span&gt;&lt;span&gt;{a}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, the intercept is &lt;&#x2F;span&gt;&lt;span&gt;{b}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The RMSE and NRMSE are: &lt;&#x2F;span&gt;&lt;span&gt;{rmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span&gt;{nrmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        plt.show()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    main()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;The slope is 3.426108589853597, the intercept is 20.478117458572427
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE and NRMSE are: 27.82841276749733 and 0.07520791645397
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;statistics&quot;&gt;Another solution, using the statistics module:&lt;&#x2F;h1&gt;
&lt;p&gt;Before jumping to big and powerful libraries such as &lt;a href=&quot;https:&#x2F;&#x2F;numpy.org&#x2F;doc&#x2F;stable&#x2F;reference&#x2F;routines.statistics.html&quot;&gt;NumPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.scipy.org&#x2F;doc&#x2F;scipy&#x2F;reference&#x2F;stats.html&quot;&gt;SciPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pandas-dev&#x2F;pandas&quot;&gt;Pandas&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raphaelvallat&#x2F;pingouin&quot;&gt;Pingouin&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;statsmodels&#x2F;statsmodels&quot;&gt;Statsmodel&lt;&#x2F;a&gt;, and all the others. We have to notice, Python provides us with a module named &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html&quot;&gt;statistics&lt;&#x2F;a&gt;. Even though the statistics module is not intended to be a competitor to the ones listed above, it&#x27;s interesting to see that inside, there is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.mean&quot;&gt;mean&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.variance&quot;&gt;variance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.covariance&quot;&gt;covariance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;even a &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.linear_regression&quot;&gt;linear regression&lt;&#x2F;a&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Our program will suddenly become shorter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;statistics &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;lestat
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# load dataset
&lt;&#x2F;span&gt;&lt;span&gt;X, Y = read_text(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dataset.txt&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:#608b4e;&quot;&gt;# extract coefficients
&lt;&#x2F;span&gt;&lt;span&gt;a, b = lestat.linear_regression(X, Y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;code&quot;&gt;Source code:&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;a5n5GalczLsAAAAM&#x2F;relief-phew.gif&quot;&gt;&lt;em&gt;Phew&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;. All the cool devs today will share the source code via a Jupyter notebook stored on Github or on Colab. According to the &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;&quot;&gt;Software Freedom Conservancy&lt;&#x2F;a&gt;, we should all &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;GiveUpGitHub&#x2F;&quot;&gt;Give Up GitHub&lt;&#x2F;a&gt;. And as a free software advocate, I agree with them. The source code can be found &lt;a href=&quot;&#x2F;assets&#x2F;script.py&quot;&gt;here&lt;&#x2F;a&gt; and the data set &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;here&lt;&#x2F;a&gt;. You&#x27;re welcome.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, really. Talking about the whole subject won&#x27;t be possible in this tiny article. To dive deeper and learn even more, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;datasette&#x2F;&quot;&gt;Datasette&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;&quot;&gt;Matplotlib&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;378&#x2F;&quot;&gt;Real programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sciencedirect.com&#x2F;topics&#x2F;engineering&#x2F;root-mean-squared-error&quot;&gt;Root-Mean-Squared Error&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;posit.co&#x2F;&quot;&gt;RStudio is becoming Posit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;scikit-learn.org&#x2F;stable&#x2F;modules&#x2F;generated&#x2F;sklearn.linear_model.LinearRegression.html&quot;&gt;Ordinary least squares Linear Regression with scikit learn&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Wall of Fame</title>
        <published>2022-07-04T00:00:00+00:00</published>
        <updated>2022-07-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/wall/"/>
        <id>https://nskm.xyz/wall/</id>
        
        <content type="html" xml:base="https://nskm.xyz/wall/">&lt;p&gt;Here it is, the Wall of Fame.&lt;&#x2F;p&gt;
&lt;div&gt;

    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_a_core_dev_followed_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_a_core_dev_followed_me.8e8245579593b0f8.jpg&quot; alt=&quot;foo&quot; title=&quot;a core dev followed me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_ashwinvis_enjoyed_my_mypy_article.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_ashwinvis_enjoyed_my_mypy_article.574457f975fea21d.png&quot; alt=&quot;foo&quot; title=&quot;ashwinvis enjoyed my mypy article&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Bash_aliases_and_functions.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Bash_aliases_and_functions.3ca5c8e249e0a455.png&quot; alt=&quot;foo&quot; title=&quot;Bash aliases and functions&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Current_status.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Current_status.d406aaba585359c1.jpg&quot; alt=&quot;foo&quot; title=&quot;Current status&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_customized_Hugo_hermit_theme.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_customized_Hugo_hermit_theme.8ae1ad770e1b0734.png&quot; alt=&quot;foo&quot; title=&quot;customized Hugo hermit theme&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Django_donator.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Django_donator.bef05b8e403fe16a.png&quot; alt=&quot;foo&quot; title=&quot;Django donator&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Djibril_being_grateful_to_me.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Djibril_being_grateful_to_me.85ea81234fa4fcbd.png&quot; alt=&quot;foo&quot; title=&quot;Djibril being grateful to me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_donkirby_reusing_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_donkirby_reusing_my_work.b8f37fd3c4e90ef5.png&quot; alt=&quot;foo&quot; title=&quot;donkirby reusing my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Dont_introduce_yourself.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Dont_introduce_yourself.6772b572b264769c.png&quot; alt=&quot;foo&quot; title=&quot;Dont introduce yourself&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Efficacite_de_la_creation.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Efficacite_de_la_creation.f366ac3a8200fb9d.png&quot; alt=&quot;foo&quot; title=&quot;Efficacite de la creation&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Emacs_massive_find_replace.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Emacs_massive_find_replace.1e9e80f82f0c3d1c.png&quot; alt=&quot;foo&quot; title=&quot;Emacs massive find replace&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Exploring_PyPolars.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Exploring_PyPolars.41f3d0e4b395fc6d.png&quot; alt=&quot;foo&quot; title=&quot;Exploring PyPolars&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Figthing_against_Mypy.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Figthing_against_Mypy.de7f548ae09b45f4.png&quot; alt=&quot;foo&quot; title=&quot;Figthing against Mypy&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_First_day_on_Mastodon.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_First_day_on_Mastodon.38d18dd00f5e2a42.png&quot; alt=&quot;foo&quot; title=&quot;First day on Mastodon&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gandi_API.2e4372b1327a02b5.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API_again.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gandi_API_again.847b2968e784e92c.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API again&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gnus_once_upon_a_time.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gnus_once_upon_a_time.8dac3ebd9b08dca3.png&quot; alt=&quot;foo&quot; title=&quot;Gnus once upon a time&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Hercules.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Hercules.8a20d66567588c01.png&quot; alt=&quot;foo&quot; title=&quot;Hercules&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_I_am_a_libertarian_leftist.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_I_am_a_libertarian_leftist.e9c7235b551f63e7.png&quot; alt=&quot;foo&quot; title=&quot;I am a libertarian leftist&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Julien_Palard_reacted_to_my_toot.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Julien_Palard_reacted_to_my_toot.02c9b51bdf84c818.png&quot; alt=&quot;foo&quot; title=&quot;Julien Palard reacted to my toot&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_kingbuzzman_reused_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_kingbuzzman_reused_my_work.8584a39a6c706df8.png&quot; alt=&quot;foo&quot; title=&quot;kingbuzzman reused my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Konami_code.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Konami_code.6edf6e64efe8be15.png&quot; alt=&quot;foo&quot; title=&quot;Konami code&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Logilab_thanks_me_for_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Logilab_thanks_me_for_my_work.374fce72f1aadf39.png&quot; alt=&quot;foo&quot; title=&quot;Logilab thanks me for my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_me.4e54225d2209fa39.jpg&quot; alt=&quot;foo&quot; title=&quot;me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Mercurial_aliases.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Mercurial_aliases.7e0820558947e9a7.png&quot; alt=&quot;foo&quot; title=&quot;Mercurial aliases&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Never_knew_I_was_one_of_the_creators_of_Python_Idle.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Never_knew_I_was_one_of_the_creators_of_Python_Idle.538d0f244bd173d0.png&quot; alt=&quot;foo&quot; title=&quot;Never knew I was one of the creators of Python Idle&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Delta_Chat.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Delta_Chat.a3710e84afed5bb2.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Delta Chat&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Git_hooks.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Git_hooks.d0e265d8ee5507c9.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Git hooks&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Quarto.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Quarto.b1953381cb548b9a.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Quarto&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PR_accepted_to_typeshed_repo.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_PR_accepted_to_typeshed_repo.c7b86067ce4b5ac5.png&quot; alt=&quot;foo&quot; title=&quot;PR accepted to typeshed repo&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_Stackexchange_User.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Proud_Emacs_Stackexchange_User.c664f068e88bbb13.png&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs Stackexchange User&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_user.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Proud_Emacs_user.4ea7bae1980d4fda.jpg&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs user&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PSF_member_yes.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_PSF_member_yes.8a574b3de6c0aed4.png&quot; alt=&quot;foo&quot; title=&quot;PSF member yes&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_pycon_africa_speaker.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_pycon_africa_speaker.9bfe680412266c97.jpg&quot; alt=&quot;foo&quot; title=&quot;pycon africa speaker&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_release_meassages_are_the_bests.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Python_release_meassages_are_the_bests.f36dffb844ed6e2f.png&quot; alt=&quot;foo&quot; title=&quot;Python release meassages are the bests&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_subprocess_example.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Python_subprocess_example.64a643f6d69895bb.png&quot; alt=&quot;foo&quot; title=&quot;Python subprocess example&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Reading.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Reading.e1323ecf5a19501c.jpg&quot; alt=&quot;foo&quot; title=&quot;Reading&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Rules_for_a_good_life.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Rules_for_a_good_life.d6c4185e1ab08970.jpg&quot; alt=&quot;foo&quot; title=&quot;Rules for a good life&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_sqlite_select_as_CSV.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_sqlite_select_as_CSV.1f30c9897fc1bb83.png&quot; alt=&quot;foo&quot; title=&quot;sqlite select as CSV&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Taking_stance.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Taking_stance.a14757f3246d4612.png&quot; alt=&quot;foo&quot; title=&quot;Taking stance&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Time_to_upgrade_distribution.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Time_to_upgrade_distribution.8e5e464c1d4dad81.png&quot; alt=&quot;foo&quot; title=&quot;Time to upgrade distribution&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_dealing_with_Paypox_wtf.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_When_I_was_dealing_with_Paypox_wtf.13ea33a6beb67dd2.png&quot; alt=&quot;foo&quot; title=&quot;When I was dealing with Paypox wtf&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_working_on_Vialegal.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_When_I_was_working_on_Vialegal.a471c4021dd87533.png&quot; alt=&quot;foo&quot; title=&quot;When I was working on Vialegal&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Why_I_dont_use_social.media.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Why_I_dont_use_social.media.a93363674756712b.png&quot; alt=&quot;foo&quot; title=&quot;Why I dont use social.media&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Yasnippets_to_send_a_resume.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Yasnippets_to_send_a_resume.9f43176f3144c85c.png&quot; alt=&quot;foo&quot; title=&quot;Yasnippets to send a resume&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_You_are_your_own_timezone.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_You_are_your_own_timezone.ebbd3ce55e8bf6ff.jpg&quot; alt=&quot;foo&quot; title=&quot;You are your own timezone&quot;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing</title>
        <published>2022-05-20T00:00:00+00:00</published>
        <updated>2022-05-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/blg/"/>
        <id>https://nskm.xyz/posts/blg/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/blg/">&lt;p&gt;I often receive resumes from people looking for a job and asking me for help. To all of them I always ask: &quot;Do you have a website ?&quot;, &quot;Do you write ?&quot;. And most of the time, the answer is negative.&lt;&#x2F;p&gt;
&lt;p&gt;Writing skills are important because they allow the reader to get their first impression of who is the writer. For example: writing skills displayed in resume, cover letter email communications, website. In my humble opinion, if you&#x27;re looking for a job as a software engineer, you should have a tiny space on the internet. A space in which you write about what you experiment, what you code, what you build.&lt;&#x2F;p&gt;
&lt;p&gt;This article is an attempt to answer, why I think everybody (every software engineer)  should have a website. Or at least, why everybody should write. This article is also &lt;em&gt;kind of&lt;&#x2F;em&gt; a recap of a talk I gave for the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Tecnology&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;wr.45c3c0f8e7026afa.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;some-reasons-for-you-to-start-writing&quot;&gt;&lt;u&gt;Some reasons for you to start writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;1-improve-your-knowledge-on-a-topic&quot;&gt;&lt;em&gt;1. Improve your knowledge on a topic&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;ll often have to write about subjects that you are not familiar with, so finding quality sources quickly is a skill you&#x27;ll develop. Before you write a single word, you need to do your research about the topic you&#x27;re writing on. The more you do research, the more you find quality sources, the more you improve your knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-organize-your-thoughts&quot;&gt;&lt;em&gt;2. Organize your thoughts&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can write down more than you can easily remember, so that your capacity to consider a number of ideas at the same time is broadened. Once those ideas are written down, you can move them around, change them. You can also reject those that are finally not good enough. You will stay with good, original clearly defined ideas. And you will be able to organize and communicate them easily.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-share-your-expertise-meet-fellow-specialist-and-grow-your-knowledge&quot;&gt;&lt;em&gt;3. Share your expertise, meet fellow specialist and grow your knowledge&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Knowledge is the only thing that grows when shared. Sharing your knowledge helps you grow your knowledge by doing research, synthesizing multiple and different viewpoints. Sharing your expertise means inviting people to read you, inviting people to a new conversation. A conversation is always an occasion to meet new people and to grow as a human.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-make-money&quot;&gt;&lt;em&gt;4. Make money&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Even professions that don&#x27;t focus on writing require written communication skills. The tech industry for example, is more and more looking for people who are able to write. Those writings include things like instruction manuals, user manuals, journal articles, product descriptions, memos, wikis, documentations, etc...&lt;&#x2F;p&gt;
&lt;p&gt;You can have a look :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.indeed.com&#x2F;q-Technical-Writer-jobs.html?vjk=1e9cd66778e25548&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.upwork.com&#x2F;freelance-jobs&#x2F;technical-writing&#x2F;&quot;&gt;then here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glassdoor.com&#x2F;Job&#x2F;technical-writer-jobs-SRCH_KO0,16.htm&quot;&gt;here again&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;careers.google.com&#x2F;jobs&#x2F;results&#x2F;93728821645058758-technical-writer-google-cloud&#x2F;?distance=50&amp;amp;q=technical%20writer&quot;&gt;also  here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By the way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;realpython.com&#x2F;write-for-us&#x2F;&quot;&gt;Real Python is hiring&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;895695&#x2F;&quot;&gt;LWN is hiring too&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;disclaimer: I&#x27;m not paid by anybody to share those job offers&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-are-the-topic-to-write-about&quot;&gt;&lt;u&gt;What are the topic to write about: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Coming up with writing inspiration is tough. My advice would be, &lt;strong&gt;in all the cases, always write about something you really like, or something you really enjoy.&lt;&#x2F;strong&gt; As a technical writer, you can write different kinds of articles:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-story&quot;&gt;&lt;em&gt;1. Story&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Human beings are interested in stories about people. If your reader knows you a little through your blog, the reader will remember who you are and the reader will be more interested by your technical articles. &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;ask&quot;&gt;Here&lt;&#x2F;a&gt; you&#x27;ll find different kinds of stories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-opinion&quot;&gt;&lt;em&gt;2. Opinion&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Giving an opinion is a common way of interacting with other people. Of course you don&#x27;t simply share an opinion, you&#x27;ll also share the compelling and interesting argument that support this opinion. Also, please don&#x27;t spend your time attacking others people or spreading controversial ideas. Here is an &lt;a href=&quot;https:&#x2F;&#x2F;drewdevault.com&#x2F;2019&#x2F;12&#x2F;09&#x2F;Developers-shouldnt-distribute.html&quot;&gt;axample&lt;&#x2F;a&gt; of a shared opinion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-how-tos&quot;&gt;&lt;em&gt;3. HOW-TOs&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An how-to is a document providing detailed and practical step-by-step guide on how to do something. In a precise, step-by-step approach, you should walk your reader through the process. You should make sure your reader can reproduce the same results by following the provided steps.  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;howto&#x2F;pyporting.html&quot;&gt;Example&lt;&#x2F;a&gt; of an HOWTO.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-how-something-work&quot;&gt;&lt;em&gt;4. How something work&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are people &lt;em&gt;like me&lt;&#x2F;em&gt; who want to know how almost everything works. This kind of article is suitable when you want to deep dive into a very specific topic. For example, somebody already using Django sessions, may be suddenly wondering how does Django sessions work under the hood ? Here is an &lt;a href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2011&#x2F;06&#x2F;24&#x2F;how-django-sessions-work-introduction&quot;&gt;article&lt;&#x2F;a&gt; showing how Django sessions work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-reviews&quot;&gt;&lt;em&gt;5. Reviews&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You have read, used, tested, played with something. In a review, your attempt will be to write about what was your experience. You&#x27;ll describe the thing, you&#x27;ll share what were your feelings about the thing, you&#x27;ll show the strengths and the weaknesses of the thing. Example of &lt;a href=&quot;https:&#x2F;&#x2F;emptysqua.re&#x2F;blog&#x2F;review-of-autotools-a-practitioners-guide&#x2F;&quot;&gt;review&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;identifying-the-target-audience&quot;&gt;&lt;u&gt;Identifying the target audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Identifying your intended audience will help you write effective content that achieves your goals. What are you writing ? Who are you writing for ? Knowing your audience will help you adapt your content accordingly. And if you don&#x27;t know who to write for, then the following is a serie of questions you can ask yourself:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Who am I writing for ?&lt;&#x2F;li&gt;
&lt;li&gt;What subject am I writing about ?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience already know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience want to know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What are the questions will my audience have?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;finding-the-audience&quot;&gt;&lt;u&gt;Finding the audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;For example, &lt;strong&gt;as a Python specialist&lt;&#x2F;strong&gt;, the audience can be found in different places. Pycoder weekly news want to hear from you about projects you are working on, conferences you are running, and articles you want to &lt;a href=&quot;https:&#x2F;&#x2F;pycoders.com&#x2F;submissions&quot;&gt;share&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Awesome Python is another newsletter who want you to &lt;a href=&quot;https:&#x2F;&#x2F;python.libhunt.com&#x2F;contribute&quot;&gt;contribute&lt;&#x2F;a&gt; links to blog posts, tutorials, libraries, events, videos, books.&lt;&#x2F;p&gt;
&lt;p&gt;You can als share your posts on &lt;a href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;&quot;&gt;Lobsters&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;tilde.news&#x2F;&quot;&gt;Tilde News&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;&quot;&gt;dev.to&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;about&quot;&gt;towardsdatascience&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;improving-your-writing&quot;&gt;&lt;u&gt;Improving your writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The following is what I recommend. In all the cases, you should find what is best for you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-practice&quot;&gt;&lt;em&gt;1. Practice&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most effective writers write every day, &lt;em&gt;at least a bit&lt;&#x2F;em&gt;.  The more you write, the more your brain form connections between neurons. Those connections get stronger the more often you write. After some time and regular practice, you no longer have to think about it. This is when writing becomes a habit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-make-time&quot;&gt;&lt;em&gt;2. Make time&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Prepare to spend between 90 minutes and 3 hours writing. But hey, 15 minutes can be useful if you do it every day. Don&#x27;t fool yourself, thinking you&#x27;ll wait for a big chunk of free time to start. That will never happen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-when&quot;&gt;&lt;em&gt;3. When&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You are much smarter and more resilient after you have slept properly and ate. Again, find what suits you best. According to some studies, creativity peaks in the morning. My experience tells me that&#x27;s true.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-frequency&quot;&gt;&lt;em&gt;4. Frequency&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Write only when you feel it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;tools-for-writing-ssg&quot;&gt;&lt;u&gt;Tools for writing... SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You should provide yourself with the right technology. Here again, I can tell you what I do, but there are plenty of differents tools, you &lt;a href=&quot;https:&#x2F;&#x2F;app.hackernoon.com&#x2F;signup&quot;&gt;should&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pages.github.com&#x2F;&quot;&gt;always&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;jekyllrb.com&#x2F;&quot;&gt;find&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;substack.com&#x2F;for-bloggers&quot;&gt;what&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;write.as&#x2F;start&quot;&gt;suits&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.blogger.com&#x2F;about&#x2F;?bpli=1&quot;&gt;you&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;creators&quot;&gt;best&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve choosen to build my website using a Static Site Generator (SSG). An ssg is a tool that generates a full static HTML website based on raw data (text files) and a set of templates (html, css, js files). :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;ssg2.3f40eef587b8186f.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p style=&quot;text-align:center&quot;&gt; &lt;a href=&quot;https:&#x2F;&#x2F;devopedia.org&#x2F;static-site-generators&quot;&gt;Image source&lt;&#x2F;a&gt; &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;why-ssg&quot;&gt;&lt;u&gt;Why SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;No need for internet for writing, no need to login somewhere before writing.&lt;&#x2F;li&gt;
&lt;li&gt;no need for a particular environment, just a text editor, and a browser.&lt;&#x2F;li&gt;
&lt;li&gt;No vendor lock in, no dependency on any product for writing or migrating your content.&lt;&#x2F;li&gt;
&lt;li&gt;No need for a program to dynamically generate webpages. Web pages load faster.&lt;&#x2F;li&gt;
&lt;li&gt;No dependencies running on the server, just a web server. Increased security&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;i-m-convinced-can-you-show-me-an-example-please&quot;&gt;&lt;u&gt;I&#x27;m convinced, can you show me an example please:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;blg&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; you&#x27;re reading right now, was generated from a &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;markdown.md&quot;&gt;markdown file&lt;&#x2F;a&gt; using an SSG named &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; and a theme named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;barlog-m&#x2F;oceanic-zen&quot;&gt;Oceanic Zen&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;To finish this article, I would like to quote &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Leslie_Lamport&quot;&gt;Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&quot;If you’re thinking without writing, you only think you’re thinking.&quot;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;— Leslie Lamport&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h1 id=&quot;links&quot;&gt;Links:&lt;&#x2F;h1&gt;
&lt;p&gt;To learn more on this topic, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yieldcode.blog&#x2F;post&#x2F;why-engineers-should-write&#x2F;&quot;&gt;Why engineers should focus on writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=RnY5iJea5ww&amp;amp;t=77s&quot;&gt;Think and write, with Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=HOXwDWCoqQg&quot;&gt;Jordan Peterson on the importance of reading and writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=vyVpRiqOvt4&quot;&gt;How writing online made me a millionaire&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=tod1sraj8we&quot;&gt;How to improve your clarity of thought (&quot;writing is thinking&quot;)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=fxLFjOa-9UY&quot;&gt;Programmers that don&#x27;t blog should start right now&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=p8dve3MqQW4&quot;&gt;Benefits of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=mmU25Xd0BGs&quot;&gt;Technical blogging for Python programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=aTgPJQ9Dy7Q&quot;&gt;Look deeper -- write -- the wonders of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=t4vKPhjcMZg&quot;&gt;What nobody tells you about documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Verba_volant,_scripta_manent&quot;&gt;Spoken words fly away, written words remain&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Circadian_rhythm&quot;&gt;Circadian rythm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;links-again&quot;&gt;Links again:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jamstack.org&#x2F;generators&#x2F;&quot;&gt;Static Site Generators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;blog&#x2F;2022&#x2F;04&#x2F;18&#x2F;comparing-static-site-generators&#x2F;&quot;&gt;How to choose the right static site generator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola, your one-stop static site engine&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;getpublii.com&#x2F;&quot;&gt;Publii, Static Site Generator with GUI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo, the world’s fastest framework for building websites&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;orbifx&#x2F;logarion&quot;&gt;Logarion, a suite of tools, for discovering, collecting &amp;amp; exchanging texts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;even-more-links&quot;&gt;Even more links:&lt;&#x2F;h1&gt;
&lt;p&gt;Things that were discussed during the talk:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Literate_programming&quot;&gt;Literate programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=Mr3WTR0a5SM&quot;&gt;Knuth on Literate Programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;orgmode.org&#x2F;worg&#x2F;org-contrib&#x2F;babel&#x2F;&quot;&gt;Babel: active code in Org-mode&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;Pandoc, a universal document converter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;&quot;&gt;Quarto, open-source scientific and technical publishing system built on Pandoc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;wr2.c2d34d34c2abf8e1.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Function pointers</title>
        <published>2022-04-29T16:15:50+00:00</published>
        <updated>2022-04-29T16:15:50+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/fp/"/>
        <id>https://nskm.xyz/posts/fp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/fp/">&lt;p&gt;In Python, we say, functions are &lt;em&gt;first class citizen&lt;&#x2F;em&gt;. This means, functions can be used like any other objects. They can be stored inside variables, they can be passed as argument to a function, they can be returned from a function. The following is a very basic example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;square = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x
&lt;&#x2F;span&gt;&lt;span&gt;cube = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x * x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;operations = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: square, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: cube}
&lt;&#x2F;span&gt;&lt;span&gt;choice = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;value = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;print(operations[choice](value))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s start with a very simple function to print out a simple &quot;hello world&quot; using a function pointer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function taking no argument and returning nothing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;slowly-please&quot;&gt;&lt;strong&gt;Slowly please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a &lt;em&gt;pointer to a function&lt;&#x2F;em&gt;, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should receive no argument: &lt;strong&gt;()&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr()&lt;&#x2F;strong&gt;, a function returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;greet_ptr&lt;&#x2F;code&gt; is a pointer, so it should receive &lt;em&gt;the address&lt;&#x2F;em&gt; of a function.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet&lt;&#x2F;code&gt; is a function, taking no argument, and returning void.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet_ptr()&lt;&#x2F;code&gt;: let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-if-the-function-pointed-to-takes-arguments&quot;&gt;&lt;strong&gt;What if the function pointed to, takes arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Simple example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a pointer to a function, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should take one argument of type char pointer &lt;strong&gt;(char *)&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr(char *)&lt;&#x2F;strong&gt;, a function taking a string and returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;greet_ptr still points to greet function.&lt;&#x2F;li&gt;
&lt;li&gt;let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;li&gt;This executable, &lt;code&gt;greet&lt;&#x2F;code&gt; is waiting for a parameter of type &lt;code&gt;char *&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;So the parameter &lt;code&gt;&quot;foo&quot;&lt;&#x2F;code&gt; will be passed to the function &lt;code&gt;greet&lt;&#x2F;code&gt; before execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-is-the-address-of-a-function&quot;&gt;&lt;strong&gt;What is the address of a function?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Before going further, we have to keep one thing in mind. &lt;strong&gt;a function name (label) is the address of the function.&lt;&#x2F;strong&gt; Yes. A &lt;code&gt;function name (label)&lt;&#x2F;code&gt; is converted to a &lt;code&gt;pointer to itself&lt;&#x2F;code&gt;. This means that function names can be assigned to a function pointer without using &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; to pass an address. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hello_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr = greet; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice, there is no &amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(greet_ptr == hello_ptr)
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Pointers containing the same address.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;function-pointers-as-arguments&quot;&gt;&lt;strong&gt;Function pointers as arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Remember, a function name (label) is converted to a pointer to itself, so it can be passed whenever we need a function pointer. So, we can write function taking function pointers as arguments. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHi(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hey &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function that takes a function and a string as parameters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greetBar(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHi, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;baz&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greetBar();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a function, named &lt;code&gt;greet&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;greet&lt;&#x2F;code&gt;  function takes 2 arguments:
&lt;ol&gt;
&lt;li&gt;a function pointer: &lt;code&gt;void (*fctPtr)(char *)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;a char pointer: &lt;code&gt;char *name&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should be called with an argument of type &lt;code&gt;char *&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to is then called: &lt;code&gt;fctPtr(name)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sayHello&lt;&#x2F;code&gt; is a function name (label)
&lt;ol&gt;
&lt;li&gt;that will be converted to a pointer to itself.&lt;&#x2F;li&gt;
&lt;li&gt;then, that pointer will be passed to &lt;code&gt;greet&lt;&#x2F;code&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function &lt;code&gt;sayHello&lt;&#x2F;code&gt; will be called with &lt;code&gt;&quot;foo&quot;&lt;&#x2F;code&gt; as parameter.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;we-can-also-use-function-pointers-as-return-values&quot;&gt;&lt;strong&gt;We can also use function pointers as return values.&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We &lt;em&gt;already&lt;&#x2F;em&gt; know a pointer can be returned from a function. A function pointer, &lt;em&gt;is&lt;&#x2F;em&gt; a &lt;em&gt;pointer&lt;&#x2F;em&gt;, so there is no big deal here.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;the-original-python-example-in-c&quot;&gt;&lt;strong&gt;The original Python example in C?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;square (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;cube (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; choice, value;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of pointers to functions
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; those functions should take an int and return an int
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) = {square, cube};
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;choice);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;value);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[choice-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&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;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;any-real-life-examples&quot;&gt;&lt;strong&gt;Any real life examples?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Function pointers gives C programmers, &lt;strong&gt;first-class citizen&lt;&#x2F;strong&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_function&quot;&gt;functionality&lt;&#x2F;a&gt;: being able to pass functions as argument to other functions, and being able to return functions as value from other functions.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;more-on-the-topic&quot;&gt;&lt;strong&gt;More on the topic:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;10758811&#x2F;c-syntax-for-functions-returning-function-pointers&#x2F;10759352#10759352&quot;&gt;C syntax for functions returning function pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My journey to type checking 7521 lines of Python</title>
        <published>2021-11-08T03:40:17+00:00</published>
        <updated>2021-11-08T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/stcmp2/"/>
        <id>https://nskm.xyz/posts/stcmp2/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/stcmp2/">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp&#x2F;&quot;&gt;first&lt;&#x2F;a&gt; part, I talked you &lt;strong&gt;the reasons&lt;&#x2F;strong&gt; I think Mypy may be useful. In this part, I&#x27;ll talk about the &lt;strong&gt;process I&#x27;ve followed&lt;&#x2F;strong&gt; for adding type annotations to RQL.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recap-of-the-first-part&quot;&gt;Recap of the first part:&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;outline&quot;&gt;Outline:&lt;&#x2F;h2&gt;
&lt;p&gt;First, I&#x27;ll talk about what &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#mypy&quot;&gt;Mypy&lt;&#x2F;a&gt; is and what should be it&#x27;s initial &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#initial-setup&quot;&gt;setup&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, I&#x27;ll briefly show you how I deconstructed the project (&lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#import-structure&quot;&gt;import structure&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#classes-hierarchy&quot;&gt;classes hierarchy&lt;&#x2F;a&gt;) to have another perspective of how the project is built.&lt;&#x2F;p&gt;
&lt;p&gt;I will also show 3 different ways to &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-hints-generation&quot;&gt;generate&lt;&#x2F;a&gt; type annotations and &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-information-inline-or-via-stubs&quot;&gt;where&lt;&#x2F;a&gt; I think those type annotations should reside.&lt;&#x2F;p&gt;
&lt;p&gt;Finaly, I&#x27;ll talk about things that still need to be &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#improvements&quot;&gt;improved&lt;&#x2F;a&gt;. Mainly, the use of &lt;code&gt;Any&lt;&#x2F;code&gt; and &lt;code&gt;type:ignore&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to jump straight to the part that&#x27;s most interesting.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;mypy&quot;&gt;Mypy:&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;Mypy&lt;&#x2F;a&gt; is a library that provides optional static type checking. Unlike other programming languages, where the static type-checking takes place at compilation time, Mypy CLI does the type-check on-demand. At Logilab, the type-check was done, locally when developing, but also in the Continuous Integration pipeline, using Gitlab and Tox.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;initial-setup&quot;&gt;Initial setup:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to ensure that Mypy is really being run everywhere it should be and everytime someone pushes code. We don&#x27;t want to spend time applying type annotations that won&#x27;t be checked. If you don&#x27;t check type annotations on a regular basis, they may become wrong after a certain period of time. That means:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-configuring-mypy&quot;&gt;1. Configuring Mypy&lt;&#x2F;h3&gt;
&lt;p&gt;Configuration is done using a &lt;code&gt;mypy.ini&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;532de9f4788887a4c5ff315ad9a515033979c822&#x2F;mypy.ini&quot;&gt;file&lt;&#x2F;a&gt;. At the begining, we do not want strict typing checks. Then, we&#x27;ll try to work towards more strigency, for example: &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#disallow-dynamic-typing&quot;&gt;dissallowing dynamic typing&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#untyped-definitions-and-calls&quot;&gt;disallowing untyped definitions&lt;&#x2F;a&gt;. We&#x27;re working with a legacy code base with no type definitions, let&#x27;s start with more relaxed options.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-ignoring-external-libraries&quot;&gt;2. Ignoring external libraries:&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve done it many weeks later, but I could have done it right from the beginning: tell Mypy to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;66c3196a4d2925183b6f6c943f6368943c3e4522&quot;&gt;ignore&lt;&#x2F;a&gt; missing type hints from &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;running_mypy.html#missing-type-hints-for-third-party-library&quot;&gt;external libraries&lt;&#x2F;a&gt;. Maybe in another phase, we&#x27;ll annotate them, but for now, they should be ignored.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-set-a-tox-environment-and-ci-job&quot;&gt;3. Set a Tox environment and CI job:&lt;&#x2F;h3&gt;
&lt;p&gt;Add Tox environment to automate the boring stuff and reduce the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;tox.ini#L44&quot;&gt;boilerplate&lt;&#x2F;a&gt;. And add a Gitlab CI &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;.gitlab-ci.yml#L39&quot;&gt;job&lt;&#x2F;a&gt;. that will be in charge of running Mypy every time a new changeset is sent to the Gitlab server.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;import-structure&quot;&gt;Import structure&lt;&#x2F;h2&gt;
&lt;p&gt;I thought a diagram showing the import structure would help me understand the project. I also thought making a graph of the RQL&#x27;s import structure would help me add types a bit faster. My idea was to add annotations from bottom to top. I was wrong. More than once, after adding type annotations to a module, I was obliged to go back to where it was already done. For example, method &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;common_issues.html#incompatible-overrides&quot;&gt;overrides&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thebjorn&#x2F;pydeps&quot;&gt;PyDeps&lt;&#x2F;a&gt; is the module dependency visualization I used, the result being:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;import_structure2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you open the diagram in another tab, you&#x27;ll notice that we can see external libraries too, for example: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;open-source&#x2F;logilab-database&quot;&gt;logilab-database&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;smurfix&#x2F;yapps&quot;&gt;yapps&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pygments&#x2F;pygments&quot;&gt;pygments&lt;&#x2F;a&gt;. Those are the ones that need to be ignored during type checking.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;classes-hierachy&quot;&gt;Classes hierachy:&lt;&#x2F;h2&gt;
&lt;p&gt;Within &lt;a href=&quot;https:&#x2F;&#x2F;pylint.org&#x2F;&quot;&gt;Pylint&lt;&#x2F;a&gt;, there is a tool named &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.org&#x2F;blogentry&#x2F;6883&quot;&gt;Pyreverse&lt;&#x2F;a&gt; that analyses Python code and extracts UML class diagrams and package dependencies. Using Pyreverse, we can have a clear view of all the classes and the relation between them:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;classes_RQL2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-hints-addition&quot;&gt;Type hints addition:&lt;&#x2F;h2&gt;
&lt;p&gt;There are different options for adding type annotations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-manual&quot;&gt;1. Manual&lt;&#x2F;h3&gt;
&lt;p&gt;We can do it manually: finding what are the types flowing through our program, &lt;em&gt;I&#x27;ve been there, it&#x27;s painful&lt;&#x2F;em&gt;. Literally:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Adding breakpoints here and there&lt;&#x2F;li&gt;
&lt;li&gt;Running the function or running the tests&lt;&#x2F;li&gt;
&lt;li&gt;Once inside PDB, asking the &lt;code&gt;type&lt;&#x2F;code&gt; function to tell me who is who&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;  
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     breakpoint()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s assume we launched the tests and somewhere, g is called
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: g([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;34&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(x)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the parameter x?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;list&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the returned value?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;int&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After that first run, we may be temped to write our function like one that takes a list and returns an integer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# g takes a list and return an integer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;81&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x: list) -&amp;gt; int:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;I said &lt;em&gt;&quot;temped&quot;&lt;&#x2F;em&gt; because, maybe the function takes a dictionary and returns an integer. Only an extensive set of tests will tell us what&#x27;s the best answer.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-reveal&quot;&gt;2. Reveal:&lt;&#x2F;h3&gt;
&lt;p&gt;I never really use them, but another option is to use &lt;code&gt;reveal_type&lt;&#x2F;code&gt; or &lt;code&gt;reveal_locals&lt;&#x2F;code&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;latest&#x2F;common_issues.html#displaying-the-type-of-an-expression&quot;&gt;functions&lt;&#x2F;a&gt;. You just put a &lt;code&gt;reveal_type(expr)&lt;&#x2F;code&gt; in the code, and run it with Mypy. I never really use those 2 functions because most of the time, the revealed type is &lt;code&gt;Any&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;reveal.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-pyannotate&quot;&gt;3. PyAnnotate:&lt;&#x2F;h3&gt;
&lt;p&gt;The third &lt;em&gt;and really helpful&lt;&#x2F;em&gt; option I want to suggest is, using a tool that will give you an &lt;strong&gt;exhaustive list of suggestions&lt;&#x2F;strong&gt;, for example PyAnnotate. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&quot;&gt;PyAnnotate&lt;&#x2F;a&gt; will help you list all the &lt;strong&gt;call arguments and all the return types observed at runtime&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Similar projects exists, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Instagram&#x2F;MonkeyType&quot;&gt;MonkeyType&lt;&#x2F;a&gt; created by Instagram. &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;Pytype&lt;&#x2F;a&gt; from Google. And &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;Pyre&lt;&#x2F;a&gt; created at Facebook... &lt;em&gt;Hem, I mean, Meta&lt;&#x2F;em&gt;. I&#x27;ve used PyAnnotate just because it felt like the most easiest to setup and to use. I should probably give a try to the other options.&lt;&#x2F;p&gt;
&lt;p&gt;In the repository, there is a configuration  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&#x2F;blob&#x2F;master&#x2F;example&#x2F;example_conftest.py&quot;&gt;example&lt;&#x2F;a&gt; you can use with Pytest. And after running your tests, you should find a new file named &lt;code&gt;type_info.json&lt;&#x2F;code&gt;. This file will contain a json that looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&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:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.compute_solutions&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:#d69d85;&quot;&gt;&amp;quot;type_comments&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; Set&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; Set&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], None, int) -&amp;gt; Set&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Delete, None, None, int) -&amp;gt; Set&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Set, None, None, int) -&amp;gt; Set&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], Dict[str, str], int) -&amp;gt; Set[str]&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&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:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65
&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:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&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:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;152&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.simplify&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:#d69d85;&quot;&gt;&amp;quot;type_comments&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:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union) -&amp;gt; None&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:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;14
&lt;&#x2F;span&gt;&lt;span&gt;    },    
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those generated type-hints are &lt;strong&gt;suggestions&lt;&#x2F;strong&gt;. You will have to tweak them first, then apply them. Once applied, you should run mypy on the updated files to verify that everything stays green.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;how-much-should-be-typed&quot;&gt;How much should be typed?&lt;&#x2F;h2&gt;
&lt;p&gt;I won&#x27;t deny, I was &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;gradually&lt;&#x2F;a&gt; adding annotation to everything, everywhere. There was a feeling of endlessness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;everywhere.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then I asked myself: &lt;em&gt;&quot;How do I know the RQL package has enough annotations? How do I know that I&#x27;ve done enough?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;68f034d32bb10d8ce8c7244c361afe219cc0cca8&quot;&gt;follow&lt;&#x2F;a&gt; a path: adding Mypy &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#cmdoption-mypy-txt-report&quot;&gt;coverage reports&lt;&#x2F;a&gt; to the project. The lower the percentage, the happier you should be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Mypy Type Check Coverage Summary
&lt;&#x2F;span&gt;&lt;span&gt;================================
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Script: index
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Module              | Imprecision       | Lines    |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| rql                 |  29.63% imprecise |  324 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql._exceptions     |   0.00% imprecise |   48 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.analyze         |  62.35% imprecise |  603 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.base            |  13.19% imprecise |  288 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.interfaces      |  11.54% imprecise |   78 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.nodes           |  24.20% imprecise | 1438 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser          |  77.19% imprecise | 1245 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser.__main__ |  19.30% imprecise |   57 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.pygments_ext    |  23.21% imprecise |   56 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqlgen          |   1.62% imprecise |  247 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqltypes        |  12.92% imprecise |  178 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stcheck         |  49.25% imprecise |  867 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stmts           |  30.98% imprecise | 1372 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.undo            |  27.39% imprecise |  387 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.utils           |  20.72% imprecise |  333 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Total               |  38.64% imprecise | 7521 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Mypy does &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;type_inference_and_annotations.html#type-inference&quot;&gt;type inference&lt;&#x2F;a&gt;, it can guess the types of values based on the context. We see in the picture below that even though there is no type annotations, the program is not flagged as 100% imprecise:
&lt;img src=&quot;&#x2F;images&#x2F;mypy_reports_one.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I finally &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;00efe84a7e18f71cf4741dbd71736b6549dfbd0b&quot;&gt;gave up&lt;&#x2F;a&gt;, to focus on what other &lt;em&gt;Logilabians&lt;&#x2F;em&gt;, suggested: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;snippets&#x2F;61#LC41&quot;&gt;find&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;issues&#x2F;218&quot;&gt;list&lt;&#x2F;a&gt; what are the &lt;strong&gt;RQL&#x27;s most imported&#x2F;used classes and functions&lt;&#x2F;strong&gt;. If those classes and functions are typed, we&#x27;ll consider we&#x27;ve reach a milestone.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-information-inline-or-via-stubs&quot;&gt;Type information inline or via stubs?&lt;&#x2F;h2&gt;
&lt;p&gt;Mypy gives you the ability to add type annotations to your project without ever modifying the original source code. You do it using what&#x27;s called &quot;stub files&quot;. &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubs.html&quot;&gt;Stub&lt;&#x2F;a&gt; files are python-like files, that only contain type-checked variable, function, and class definitions. Nothing else.&lt;&#x2F;p&gt;
&lt;p&gt;I went the other way, I&#x27;ve added type annotations directly within the original source code. In the beginning, it really felt like the easiest thing to do, having everything in the same file. But now that there is more and more types, I think I&#x27;m better improve readability.&lt;&#x2F;p&gt;
&lt;p&gt;I can for example write &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;kinds_of_types.html#type-aliases&quot;&gt;type aliases&lt;&#x2F;a&gt; whenever &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stcheck.py#L158&quot;&gt;necessary&lt;&#x2F;a&gt;. Interesting inspiration can be found &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;incubator-superset-internal&#x2F;blob&#x2F;4cf3f99ee881a10995212828494f0b126dd5415e&#x2F;superset&#x2F;typing.py&quot;&gt;here&lt;&#x2F;a&gt;. I can also write a snippet that will strip all those annotations and put them inside &lt;code&gt;.pyi&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;
&lt;p&gt;From now on, I think I&#x27;ll always use stub files.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-checking&quot;&gt;Type Checking:&lt;&#x2F;h2&gt;
&lt;p&gt;The typing module defines a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#typing.TYPE_CHECKING&quot;&gt;TYPE_CHECKING&lt;&#x2F;a&gt; constant that is &lt;code&gt;False&lt;&#x2F;code&gt; at runtime but treated as &lt;code&gt;True&lt;&#x2F;code&gt; while type checking. This technique is used to tell mypy something without the code being evaluated at runtime, for example resolving import cycles. Example &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;nodes.py#L51&quot;&gt;here&lt;&#x2F;a&gt;, another one &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stmts.py#L243&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;improvements&quot;&gt;Improvements:&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-less-any&quot;&gt;&lt;em&gt;1. Less Any:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve been into situations where I&#x27;m not sure what should be the correct type annotation. Instead of leaving an empty type annotation, I put &lt;code&gt;Any&lt;&#x2F;code&gt;, to show other developers that the lack of a restrictive type hint is a conscious choice: either I don&#x27;t know, either I&#x27;m not sure.&lt;&#x2F;p&gt;
&lt;p&gt;Normally, I should use &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;Any&lt;&#x2F;a&gt; only if it&#x27;s impossible for me to know what the type is going to be.&lt;&#x2F;p&gt;
&lt;p&gt;From the documentation we can &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;read&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Notice that no type checking is performed when assigning a value of type Any to a more precise type. For example, the static type checker did not report an error when assigning a to s even though s was declared to be of type str and receives an int value at runtime!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, to take advantage of Mypy, I should really avoid using &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;repository_ref=branch%2Fdefault&amp;amp;scope=&amp;amp;search=%3A+Any&amp;amp;search_code=true&amp;amp;snippets=false&quot;&gt;Any&lt;&#x2F;a&gt; and see if I can replace it with a proper annotation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-less-type-ignore-comments&quot;&gt;&lt;em&gt;2. Less type: ignore comments:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It was also impossible to progress without using &lt;code&gt;# type: ignore&lt;&#x2F;code&gt; comments, to work around the trickier cases. There are still too many &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;search=%3A+ignore&quot;&gt;type: ignore&lt;&#x2F;a&gt; comments. I should have another look and see if I can improve the type annotations and remove some of those type: ignore comments.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h2&gt;
&lt;p&gt;Special thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;romaricst&quot;&gt;Romaric&lt;&#x2F;a&gt; who took the time to read this article and provide insightful critiques.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h2&gt;
&lt;p&gt;Really hope you&#x27;ve learned something reading this article. As always, the topic is wide and cannot be completely covered here. To discover more about this subject, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typeddjango&#x2F;awesome-python-typing&quot;&gt;Awesome typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=8wjntHrTGPs&quot;&gt;Liskov Substitution Principle with Johan Vergeer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;Our journey to type checking 4 million lines of Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;instagram-engineering.com&#x2F;static-analysis-at-scale-an-instagram-story-8f498ab71a0c&quot;&gt;Static analysis at scale: an Instagram story&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>To type or not to type? That is the question</title>
        <published>2021-08-22T03:40:17+00:00</published>
        <updated>2021-08-22T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/stcmp/"/>
        <id>https://nskm.xyz/posts/stcmp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/stcmp/">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In this first part, I&#x27;ll try to tell you &lt;strong&gt;when&lt;&#x2F;strong&gt; I think Mypy may be useful. In a &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;second part&lt;&#x2F;a&gt;, I&#x27;ll talk about the &lt;strong&gt;how&lt;&#x2F;strong&gt;, the process I&#x27;ve followed for adding type annotations to RQL. In a last part, I&#x27;ll talk about what I&#x27;ve &lt;strong&gt;learned&lt;&#x2F;strong&gt; during the process.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;&#x2F;h2&gt;
&lt;p&gt;Yes, in case you were living under a rock, here are the news: you can now write Python &lt;strong&gt;as if&lt;&#x2F;strong&gt; it was a static programming language. The official &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;&quot;&gt;PEP&lt;&#x2F;a&gt;, the official &lt;a href=&quot;http:&#x2F;&#x2F;www.mypy-lang.org&#x2F;&quot;&gt;website&lt;&#x2F;a&gt;. The official &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt;. And the official &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;python&#x2F;mypy&quot;&gt;repository&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The &lt;a href=&quot;http:&#x2F;&#x2F;www.alorelang.org&#x2F;&quot;&gt;Alore&lt;&#x2F;a&gt; programming language, the project Mypy borrows heavily from.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;I remember when I was asked to work on this task. The (my) skepticism was real. Around me, reactions were mixed (confused, disgusted, interesed). I won&#x27;t deny, sometimes, I&#x27;m really wondering if I&#x27;m not better go and learn to write &lt;a href=&quot;https:&#x2F;&#x2F;ocaml.org&#x2F;learn&#x2F;&quot;&gt;OCaml&lt;&#x2F;a&gt;. Python devs are so used to quickly prototype their programs, without worrying about the types of their variables, without worrying about their return types, etc. You cannot just come and tell them that type hints are nice! They need to be convinced.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;More than once, the discussion ended with the &quot;explicit vs implicit&quot;, &quot;static vs dynamic&quot; holy wars, etc... I&#x27;m not trying to fuel those debates. There are pros and cons on each sides. You have to know what are the tools, what suits you best, depending on what you&#x27;re trying to achieve, depending on what is your position (user, author, maintainer).&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you&#x27;re a person who already write Python programs, and you want to discover more about Mypy. If you only look at some introductory examples, they will help you understand &lt;strong&gt;what&#x27;s going on.&lt;&#x2F;strong&gt; They won&#x27;t &lt;strong&gt;convince&lt;&#x2F;strong&gt; you to jump on the type-hints band wagon. The problem with most of the examples is, they&#x27;re too short, or too basic.&lt;&#x2F;p&gt;
&lt;p&gt;No disrepect to the authors, I guess, the intent was to make things easier to understand. Short and simple to get to the point. But short and simple would barely convince you to try.&lt;&#x2F;p&gt;
&lt;p&gt;So, what are the situations in which adding types to your program will be useful, necessary, not a waste of time, priceless, meaningful? To this question, I would say this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-need-to-know-the-types&quot;&gt;I need to know the types:&lt;&#x2F;h2&gt;
&lt;p&gt;When you read&#x2F;debug&#x2F;maintain a large software system you&#x27;ve not written, you&#x27;ll often be in the position in which you ask yourself: &quot;Those function arguments, those variables, what are their types?&quot;, or &quot;Is this function returning something?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Remember, you were reading the source code, now you need to: modifiy the source code, add a couple of: &lt;code&gt;print(foo)&lt;&#x2F;code&gt;, &lt;code&gt;type(bar)&lt;&#x2F;code&gt;, &lt;code&gt;isinstance(baz)&lt;&#x2F;code&gt;, &lt;code&gt;qux.__class__&lt;&#x2F;code&gt;, &lt;code&gt;corge.__dict__&lt;&#x2F;code&gt;. You will probably add &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functions.html#breakpoint&quot;&gt;breakpoints&lt;&#x2F;a&gt; here and there, to dive inside &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;pdb.html&quot;&gt;pdb&lt;&#x2F;a&gt;. Then start a REPL, then launch the program, then do some instrospection, then see what&#x27;s going on. And finally, discover that the type is not what you were expecting.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;vZrArZhxAUoAAAAd&#x2F;hugh-laurie-facepalm.gif&quot; alt=&quot;phew&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what-about-just-reading-the-type&quot;&gt;What about just reading the type?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s be honest, as a &lt;em&gt;reader&lt;&#x2F;em&gt;, as the one who review millions of lines of code, you just want to be able to &lt;em&gt;read&lt;&#x2F;em&gt; what are the types. And I&#x27;m not talking about &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0257&#x2F;&quot;&gt;docstrings&lt;&#x2F;a&gt;. Everybody should document their programs and write docstrings. But let&#x27;s face it, docstrings may be missing, misleading, out of date, not clear enough, etc.... Let&#x27;s compare the 2 following &lt;em&gt;shorts&lt;&#x2F;em&gt; snippets:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# What is tr ???
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ah, tr is a function. What&amp;#39;s returned by tr?
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The method seems to return a string
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine having to find answers to those questions many times in a day?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]:
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You see that in the second snippet, all the important informations are on the function header. You don&#x27;t even read the function body and you already know that: &lt;strong&gt;&quot;get_description is a method that takes a function as its only parameter and return a string or nothing&quot;&lt;&#x2F;strong&gt;. That&#x27;s a game changer when you&#x27;re a maintainer.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a surprise, &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;all&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;the&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;pyright&quot;&gt;big&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;monkeytype.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;companies&lt;&#x2F;a&gt;, the ones with large software systems, are already using type annotations.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;too-verbose-and-confusing-to-read&quot;&gt;Too verbose and confusing to read?&lt;&#x2F;h2&gt;
&lt;p&gt;Adding type annotation can quickly lead to a source code that is too verbose and disgusting to read. The following is something I&#x27;ve written for RQL. I think I can do better (define type aliases, use stub files, use dataclasses, refactor, ...)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ScopeNode(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;BaseNode&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__init__(self):
&lt;&#x2F;span&gt;&lt;span&gt;        self.defined_vars: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.Variable&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;span&gt;        self.with_: List[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.SubQuery&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = []
&lt;&#x2F;span&gt;&lt;span&gt;        self.solutions: rt.SolutionsList = []
&lt;&#x2F;span&gt;&lt;span&gt;        self._varmaker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.where: Optional[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.having: Iterable[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = ()
&lt;&#x2F;span&gt;&lt;span&gt;        self.schema: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.aliases: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.ColumnAlias&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;stub-files&quot;&gt;Stub files?&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to keep your source code free of type annotations, but still want to use type annotations, you can write &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;#stub-files&quot;&gt;stub files&lt;&#x2F;a&gt;. A stub file is just a file that will contain all your variables, function signatures, &lt;em&gt;annotated&lt;&#x2F;em&gt;. &lt;strong&gt;Function bodies in stub files are just a single ellipsis.&lt;&#x2F;strong&gt; Another really short example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.py
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr):
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&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:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.pyi &amp;lt;--- notice the extension used for stub files
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-want-type-annotations-what-s-next&quot;&gt;I want type annotations, what&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;introduction.html#introduction&quot;&gt;Mypy&lt;&#x2F;a&gt; is a static type checker for Python. Let&#x27;s see what Mypy can to for us.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;1-generating-type-annotations&quot;&gt;1. Generating type annotations:&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s suppose you want to add type annotations to your code base. How do you proceed?&lt;&#x2F;p&gt;
&lt;p&gt;Mypy includes the &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubgen.html&quot;&gt;stubgen&lt;&#x2F;a&gt; tool that can automatically generate stub files. For example, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LeMeteore&#x2F;typeshed&#x2F;blob&#x2F;b2e1083560e223ec415fcb4dd155366e2984b2a5&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;here&lt;&#x2F;a&gt; is an example of a &lt;code&gt;.pyi&lt;&#x2F;code&gt; file generated by the stubgen tool for the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrapinghub&#x2F;dateparser&quot;&gt;dateparser&lt;&#x2F;a&gt; package.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Any, Optional
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: Any, 
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    languages: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    locales: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    region: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    settings: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Keep in mind, most types annotations will default to &lt;code&gt;Any&lt;&#x2F;code&gt;. You&#x27;ll need to update &lt;code&gt;pyi&lt;&#x2F;code&gt; files and write more precise types (We agree that &lt;code&gt;Any&lt;&#x2F;code&gt; everywhere is not really useful). &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hoefling&#x2F;typeshed&#x2F;blob&#x2F;855acb4da416375b0d4791be51bf0934b0ee9e29&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;Here&lt;&#x2F;a&gt; is an example of the same stub file with more precise type annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;datetime
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Set, Tuple
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dateparser.date &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;sys.version_info &amp;gt;= (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing_extensions &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;__version__: str
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_default_parser: DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_Part = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;day&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;month&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;_ParserKind = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;timestamp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;relative-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;custom-formats&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;absolute-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;no-spaces-time&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:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;_Settings(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;TypedDict&lt;&#x2F;span&gt;&lt;span&gt;, total=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    DATE_ORDER: str
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_LOCALE_DATE_ORDER: bool
&lt;&#x2F;span&gt;&lt;span&gt;    TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    TO_TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_AS_TIMEZONE_AWARE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DAY_OF_MONTH: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;first&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;last&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DATES_FROM: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current_period&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;future&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;past&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    RELATIVE_BASE: datetime.datetime
&lt;&#x2F;span&gt;&lt;span&gt;    STRICT_PARSING: bool
&lt;&#x2F;span&gt;&lt;span&gt;    REQUIRE_PARTS: list[_Part]
&lt;&#x2F;span&gt;&lt;span&gt;    SKIP_TOKENS: list[str]
&lt;&#x2F;span&gt;&lt;span&gt;    NORMALIZE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_TIME_AS_PERIOD: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PARSERS: list[_ParserKind]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: str,
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    languages: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    locales: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    region: str | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    settings: _Settings | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; datetime.datetime | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do we agree that the :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;parse function parameters are more precise.&lt;&#x2F;li&gt;
&lt;li&gt;settings parameter is annotated with a more detailed type.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;returned value is more precise.&lt;&#x2F;li&gt;
&lt;li&gt;refactoring of this function will be easier.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;2-type-checking&quot;&gt;2. Type checking:&lt;&#x2F;h3&gt;
&lt;p&gt;Before running your tests, before running your program, Mypy can detect &lt;em&gt;some types&lt;&#x2F;em&gt; of bugs:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I pretend &lt;code&gt;foo&lt;&#x2F;code&gt; should return a &lt;code&gt;string&lt;&#x2F;code&gt;, yet, there are cases where foo does return &lt;code&gt;None&lt;&#x2F;code&gt;. That should be fixed. Notice how, the program is running fine. Mypy will type check the program and tell you what&#x27;s wrong. Mypy won&#x27;t stop you from running the program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;Most people, including myself, don&#x27;t work on projects of this size (&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;4 million lines of Python code&lt;&#x2F;a&gt;), and hence have not to deal with the constraints of such a big code base.&lt;&#x2F;p&gt;
&lt;p&gt;Most people can perfectly write their Python programs without using type annotations. Mypy is just another tool inside your toolbox. I just want you to try, that will certainly make you a better software developer.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt;, I will talk a little bit more about the actual process I&#x27;ve followed for adding type annotations to the RQL package.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-learn-more-about-this-topic&quot;&gt;To learn more about this topic:&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html&quot;&gt;Python typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tube.incognet.io&#x2F;watch?v=pJOmlFf5Je4&quot;&gt;What Python can learn from Haskell&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hTrjTAPnA_k&quot;&gt;Type hinting (and mypy)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Which, by the way, is where you&#x27;ll find more interesting answers than what&#x27;s inside the documentation, imho.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Yes. I won&#x27;t deny, there is suddenly more lines to &lt;strong&gt;read&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Elephant in the room (part 1)</title>
        <published>2021-05-25T03:40:17+00:00</published>
        <updated>2021-05-25T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/eitr/"/>
        <id>https://nskm.xyz/posts/eitr/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/eitr/">&lt;p&gt;I&#x27;m living in a Continent where (&lt;em&gt;it sounds like&lt;&#x2F;em&gt;) nobody really cares about software freedom, data privacy, surveillance. I guess, people here are simply too busy trying to stay &lt;a href=&quot;https:&#x2F;&#x2F;www.africanews.com&#x2F;2021&#x2F;05&#x2F;29&#x2F;second-volcano-erupts-in-eastern-democratic-republic-of-congo&#x2F;&quot;&gt;alive&lt;&#x2F;a&gt;, not enough time to think about FOSS. Or maybe they&#x27;re simply confused, maybe they simply don&#x27;t know.&lt;&#x2F;p&gt;
&lt;p&gt;The topic is wide, it&#x27;s easy to digress, and I&#x27;m not sure about the best way to tackle it (&lt;em&gt;consider this to be a first draft, updates will come&lt;&#x2F;em&gt;). Let&#x27;s say it&#x27;s just an attempt, an effort, to &lt;em&gt;at least&lt;&#x2F;em&gt; address the issue.&lt;&#x2F;p&gt;
&lt;br&gt;
Okay. Let me put you in the context...
&lt;br&gt;
&lt;h1 id=&quot;will-you-be-okay-with-anybody-trying-to&quot;&gt;&lt;em&gt;Will you be okay with anybody trying to:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Fix any of your furnitures.&lt;&#x2F;li&gt;
&lt;li&gt;Take you anywhere you want.&lt;&#x2F;li&gt;
&lt;li&gt;Offer you any food you want.&lt;&#x2F;li&gt;
&lt;li&gt;Pay for all your phone, sms, mail bills.&lt;&#x2F;li&gt;
&lt;li&gt;Let you watch any movie, any film, any show.&lt;&#x2F;li&gt;
&lt;li&gt;Alert you about something every 5mn.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;and-in-exchange-the-same-person&quot;&gt;&lt;em&gt;And in exchange the same person:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Won&#x27;t ask you for any money, nothing, he&#x27;ll just keep a tiny tiny list of all:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the furnitures in your house?&lt;&#x2F;li&gt;
&lt;li&gt;the places you visit?&lt;&#x2F;li&gt;
&lt;li&gt;the foods you eat?&lt;&#x2F;li&gt;
&lt;li&gt;the conversations you had?&lt;&#x2F;li&gt;
&lt;li&gt;the movies you watched?&lt;&#x2F;li&gt;
&lt;li&gt;the time he notified you? The reason he notified you?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-we-agree-that-you-won-t-be-okay&quot;&gt;&lt;em&gt;Do we agree that you won&#x27;t be okay?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;In standard conditions for temperature and pressure&lt;&#x2F;em&gt;, you won&#x27;t be okay with anybody offering you the deal above because (&lt;em&gt;among many other reasons&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you don&#x27;t want anybody to access your &lt;strong&gt;private space&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;you want to keep a certain level of &lt;strong&gt;autonomy&lt;&#x2F;strong&gt;, &lt;strong&gt;independance&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;you want to preserve your physical &lt;strong&gt;integrity&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interestingly&quot;&gt;&lt;em&gt;Interestingly:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It sounds like, nobody want me to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;put a webcam and a microphone in their house.&lt;&#x2F;li&gt;
&lt;li&gt;have the key to their house.&lt;&#x2F;li&gt;
&lt;li&gt;follow them.&lt;&#x2F;li&gt;
&lt;li&gt;take picture of them or recording them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Yet, most of the same people are using all kinds of &lt;em&gt;&quot;privacy invading&quot;&lt;&#x2F;em&gt; technologies on a daily basis:  &lt;a href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;kateoflahertyuk&#x2F;2019&#x2F;07&#x2F;28&#x2F;apple-siri-eavesdropping-puts-millions-of-users-at-risk&quot;&gt;Siri&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.cnet.com&#x2F;home&#x2F;smart-home&#x2F;alexa-and-google-voice-assistants-app-exploits-left-it-vulnerable-to-eavesdropping&#x2F;&quot;&gt;Alexa&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.vrt.be&#x2F;vrtnws&#x2F;en&#x2F;2019&#x2F;07&#x2F;10&#x2F;google-employees-are-eavesdropping-even-in-flemish-living-rooms&#x2F;&quot;&gt;Google&lt;&#x2F;a&gt;. I won&#x27;t even talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.dw.com&#x2F;en&#x2F;samsung-admits-smart-tv-may-be-eavesdropping&#x2F;a-18246372&quot;&gt;smart TVs&lt;&#x2F;a&gt;, nor &lt;a href=&quot;https:&#x2F;&#x2F;www.reuters.com&#x2F;article&#x2F;us-eu-facebook-dataprotection-idUSKCN1UO1B4&quot;&gt;Facebook&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;any-reasons-that-let-us-give-our-datas-to-the-tech-giants&quot;&gt;&lt;em&gt;Any reasons that let us give our datas to the Tech Giants?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;People use privacy invading software for maaaaany reasons that can be understood.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There is the &quot;I need to figure out what to eat today&quot; reason. Present all over the world, especially for the poorer people. Even more true in the Black continent.&lt;&#x2F;p&gt;
&lt;p&gt;There is the fact that &lt;strong&gt;implications&lt;&#x2F;strong&gt; (of using privacy invading software) &lt;strong&gt;are invisible&lt;&#x2F;strong&gt;, not obvious. While the benefits are immediate, concrete, observable.&lt;&#x2F;p&gt;
&lt;p&gt;Terms of Service are, &lt;em&gt;most of the time&lt;&#x2F;em&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;en&#x2F;service&#x2F;182&quot;&gt;confusing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;217&quot;&gt;difficult&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;198&quot;&gt;blurry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is also the &quot;I use it because people around me are using it&quot; reason. People are moved by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Network_effect&quot;&gt;those around&lt;&#x2F;a&gt; them and wish to fit in as quickly as possible, as simply as possible.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Henrik_Ibsen&quot;&gt;Henrik Ibsen&lt;&#x2F;a&gt; said &lt;em&gt;&quot;A thousand words leave not the same deep impression as does a single deed&quot;&lt;&#x2F;em&gt;. And I definitely agree with him:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;vicious-cycle.42e644fb1aedfddb.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;theconversation.com&#x2F;heres-how-tech-giants-profit-from-invading-our-privacy-and-how-we-can-start-taking-it-back-120078&quot;&gt;Source&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-you-know-that&quot;&gt;&lt;em&gt;Do you know that:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Your right to physical integrity was &lt;em&gt;already&lt;&#x2F;em&gt; affirmed in 1222, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kouroukan_Fouga#Contents&quot;&gt;inside the Manden Charter&lt;&#x2F;a&gt;, article 5:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Everybody has a right to life and to the &lt;strong&gt;preservation of physical integrity&lt;&#x2F;strong&gt;. [...]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Your right to privacy was affirmed in 1948 by the &lt;a href=&quot;https:&#x2F;&#x2F;www.un.org&#x2F;en&#x2F;about-us&#x2F;universal-declaration-of-human-rights&quot;&gt;Universal Declaration of Human Rights&lt;&#x2F;a&gt;, article 12:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;No one shall be subjected to &lt;strong&gt;arbitrary interference&lt;&#x2F;strong&gt; with his privacy, family, home or correspondence, nor to attacks upon his honour and reputation. Everyone has the right to the protection of the law against such interference or attacks.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Within the &lt;a href=&quot;https:&#x2F;&#x2F;www.echr.coe.int&#x2F;documents&#x2F;convention_eng.pdf&quot;&gt;European Convention on Human Rights&lt;&#x2F;a&gt;, in the article 8, we can read:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Right to respect for private and family life.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Everyone has the right to respect for his private and family life, his home and his correspondence.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;There shall be &lt;strong&gt;no interference by a public authority&lt;&#x2F;strong&gt; with the exercise of this right except such as is in accordance with the law and is necessary in a democratic society in the interests of national security, public safety or the economic well-being of the country, for the prevention of disorder or crime, for the protection of health or morals, or for the protection of the rights and freedoms of others.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.law.cornell.edu&#x2F;constitution&quot;&gt;U.S. constitution&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;constitution.congress.gov&#x2F;constitution&#x2F;amendment-4&#x2F;&quot;&gt;Fourth Amendment&lt;&#x2F;a&gt; states that:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The right of the people to be secure in their persons, houses, papers, and effects, &lt;strong&gt;against unreasonable searches and seizures&lt;&#x2F;strong&gt;, shall not be violated, and no Warrants shall issue, but upon probable cause, supported by Oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;The point seems to be: &lt;strong&gt;Every human being has a right to privacy, and this right should not be violated.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-privacy&quot;&gt;&lt;em&gt;What is privacy?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I was not able to find a fixed, simple, perfect, static definition of &lt;a href=&quot;https:&#x2F;&#x2F;www.nolo.com&#x2F;dictionary&#x2F;right-to-privacy-term.html&quot;&gt;privacy&lt;&#x2F;a&gt;. The definition may vary from one country to another, from one constitution to another, from one period of time to another.&lt;&#x2F;p&gt;
&lt;p&gt;But I guess we can agree that privacy is any information that intrudes into the intimacy of the individual. &lt;em&gt;Right&lt;&#x2F;em&gt;? Privacy is that thing which is essential to the protection of our dignity as Human Being. &lt;em&gt;Right&lt;&#x2F;em&gt;?  Anything that is directly related to :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;your personal space, your house, your image,&lt;&#x2F;li&gt;
&lt;li&gt;your financial status, your medical status,&lt;&#x2F;li&gt;
&lt;li&gt;your religious, political, &lt;em&gt;or even sexual&lt;&#x2F;em&gt; orientations,&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Privacy is the fundamental way to protect yourself&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-of-the-solutions-we-can-explore&quot;&gt;&lt;em&gt;Some of the solutions we can explore:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;How do we defend ourselves and our friends from privacy invading technologies? What can we do to safeguard our personal privacy. What are the ways we can use to better protect ourselves when going online? What are the alternatives to the privacy invading software? I&#x27;ll talk about the solutions in the next &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;wmdop&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; (&lt;em&gt;coming soon&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;no-i-m-not&quot;&gt;&lt;em&gt;No, I&#x27;m not:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Saying that I&#x27;ve all the answers.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that you should do as I say.&lt;&#x2F;li&gt;
&lt;li&gt;Asking you to close all your accounts.&lt;&#x2F;li&gt;
&lt;li&gt;Asking you to go back to the stone age.&lt;&#x2F;li&gt;
&lt;li&gt;Trying to make you affraid of technology.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that I&#x27;ve found all the alternatives.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that migrating from privacy invading software will be an easy task.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-i-m-asking-you&quot;&gt;&lt;em&gt;What I&#x27;m asking you:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Completely shuting down all the Tech Giants won&#x27;t be an easy task. It cannot be done within the snap of a finger &lt;em&gt;(I wish it &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=TWB31WFomz4&quot;&gt;could&lt;&#x2F;a&gt;)&lt;&#x2F;em&gt;. Let&#x27;s stay optimistic, there is still some actionable steps we can take to help:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ask yourself :
&lt;ul&gt;
&lt;li&gt;Why are you using those platforms?&lt;&#x2F;li&gt;
&lt;li&gt;What are the services you really need?&lt;&#x2F;li&gt;
&lt;li&gt;Is there any alternatives? (Respecting your privacy).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Be aware:
&lt;ul&gt;
&lt;li&gt;of the risks, of the pros &amp;amp; cons.&lt;&#x2F;li&gt;
&lt;li&gt;that if it&#x27;s free, you&#x27;re probably the &lt;a href=&quot;https:&#x2F;&#x2F;ethannonsequitur.com&#x2F;wp-content&#x2F;uploads&#x2F;2011&#x2F;09&#x2F;facebook-and-you-pigs.jpg&quot;&gt;product&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Ask for more:
&lt;ul&gt;
&lt;li&gt;Transparency to all those platforms.&lt;&#x2F;li&gt;
&lt;li&gt;Regulation &amp;amp; protection to your leaders, your governments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spark conversation, everywhere.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interesting-links&quot;&gt;Interesting links:&lt;&#x2F;h1&gt;
&lt;p&gt;This topic is too wide to be covered entirely in this tiny article. I really hope you&#x27;re learned something. I strongly recommend the following links for a better exploration and understanding of the topic.&lt;&#x2F;p&gt;
&lt;p&gt;The following is a list of resources you should &lt;em&gt;download, browse &amp;amp; share&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Enemy of the State&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.killswitchthefilm.com&#x2F;&quot;&gt;Killswitch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=ZHl0WI32XkY&quot;&gt;We are legion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Terms and conditions may apply&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;citizenfourfilm.com&#x2F;&quot;&gt;Citizenfour&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thesocialdilemma.com&#x2F;&quot;&gt;Social dilemma&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thegreathack.com&#x2F;&quot;&gt;The great hack&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;snowdenfilm.com&#x2F;&quot;&gt;Snowden&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=YXmMtbgdces&quot;&gt;Nos données personnelles valent de l&#x27;or&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;activism.net&#x2F;cypherpunk&#x2F;manifesto.html&quot;&gt;A Cypherpunk&#x27;s Manifesto&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=IWzmYE60_dc&quot;&gt;Macron trahit la « start-up nation », les gafam raflent la mise&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h1&gt;
&lt;p&gt;Special &lt;a href=&quot;https:&#x2F;&#x2F;www.meme-arsenal.com&#x2F;memes&#x2F;379eb2a9776a3bbaac72286e3d857cbf.jpg&quot;&gt;thanks&lt;&#x2F;a&gt; to Orbifx, &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.scot&#x2F;@orbifx&quot;&gt;the Nature&#x27;s emissary&lt;&#x2F;a&gt;, and  &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@travis_kalanick&quot;&gt;Travis Kalanick&lt;&#x2F;a&gt;. They both gave me interesting ideas to help me finish this article.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-not-forget&quot;&gt;Do not forget:&lt;&#x2F;h1&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;real-power-is-people.815a6f16ec1b60fc.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Django single file project. Again</title>
        <published>2020-07-10T01:09:16+00:00</published>
        <updated>2020-07-10T01:09:16+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/dsfpa/"/>
        <id>https://nskm.xyz/posts/dsfpa/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/dsfpa/">&lt;p&gt;This article is a follow up on the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfp&#x2F;&quot;&gt;one&lt;&#x2F;a&gt; I&#x27;ve written few years
ago. Special shoutout and thanks and hugs and kudos to &lt;a href=&quot;http:&#x2F;&#x2F;buzzi.me&#x2F;&quot;&gt;Javier
Buzzi&lt;&#x2F;a&gt; for taking the time to &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;kingbuzzman&#x2F;d7859d9734b590e52fad787d19c34b52&quot;&gt;improve&lt;&#x2F;a&gt; the original script.&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;ee784daff75aae62&quot;&gt;download old version&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;c4434741122bec0f&quot;&gt;download new version&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br &#x2F;&gt;
&lt;h2 id=&quot;very-important-disclaimer&quot;&gt;VERY IMPORTANT DISCLAIMER&lt;&#x2F;h2&gt;
&lt;p&gt;The content associated with mlvin.xyz may be very offensive to some people. I&#x27;ve lost the ownership of mlvin.xyz a very long time ago, sad situation. I&#x27;m not anymore linked to this domain name, nor to the content hosted on this website. &lt;em&gt;By the way F*** OVH&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-those-improvements&quot;&gt;What are those improvements?&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;application-label&quot;&gt;Application label?&lt;&#x2F;h3&gt;
&lt;p&gt;Our models are not defined as in a classical Django application. So,
each model should declare which app it belongs to. You can read more
about app_label Meta option &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;3.0&#x2F;ref&#x2F;models&#x2F;options&#x2F;#django.db.models.Options.app%5Flabel&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with the first script was duplication:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to define app_label once and for all our models:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The current name of the file, which will be the name of our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL, _ = os.path.splitext(os.path.basename(os.path.abspath(__file__)))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we need to overwrite the Django function in charge of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;looking for an application configuration&lt;&#x2F;li&gt;
&lt;li&gt;attach the model to the found&#x2F;correct application configuration.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This function is named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;apps&#x2F;registry.py#L243&quot;&gt;get_containing_app_config&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_containing_app_config(module):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;module == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__main__&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:#608b4e;&quot;&gt;# if inside single file project,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# retrieve the application configuration using APP_LABEL variable
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps.get_app_config(APP_LABEL)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# otherwise, do as you always do
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# save the original function
&lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config = apps.get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ask Django to use our custom function
&lt;&#x2F;span&gt;&lt;span&gt;apps.get_containing_app_config = get_containing_app_config
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;migrations-folder&quot;&gt;Migrations folder?&lt;&#x2F;h3&gt;
&lt;p&gt;There is a Django settings named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;conf&#x2F;global_settings.py#L616&quot;&gt;MIGRATION_MODULE&lt;&#x2F;a&gt;. According to the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;docs&#x2F;ref&#x2F;settings.txt#L2021&quot;&gt;documentation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A dictionary specifying the package where migration modules can be found on a per-app basis. The  default value of this setting is an empty dictionary, but the default package name for migration modules is ``migrations``.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;In the first version of the script, all the migrations were put in a folder named &lt;code&gt;migrations&lt;&#x2F;code&gt;. With the following configuration, we can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;name the migration folder how we want.&lt;&#x2F;li&gt;
&lt;li&gt;make sure that we have one migration folder per application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Where migrations folder need to be created
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_MODULE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;_migrations&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_PATH = os.path.join(BASE_DIR, APP_MIGRATION_MODULE)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create the migration folder
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# and a __init__.py file if necessary:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if not &lt;&#x2F;span&gt;&lt;span&gt;os.path.exists(APP_MIGRATION_PATH):
&lt;&#x2F;span&gt;&lt;span&gt;    os.makedirs(APP_MIGRATION_PATH)
&lt;&#x2F;span&gt;&lt;span&gt;    open(os.path.join(APP_MIGRATION_PATH, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__init__.py&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;w&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).close()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also took the time to update the Django settings, somewhere inside the call to &lt;code&gt;settings.configure function&lt;&#x2F;code&gt;, you&#x27;ll find:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Django needs to be told where is the migration module
&lt;&#x2F;span&gt;&lt;span&gt;MIGRATION_MODULES={APP_LABEL: APP_MIGRATION_MODULE},
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;fake-modules&quot;&gt;Not so fake modules?&lt;&#x2F;h3&gt;
&lt;p&gt;A correctly configured Django application should normally have a &lt;code&gt;model modules&lt;&#x2F;code&gt;, a &lt;code&gt;urls modules&lt;&#x2F;code&gt; and a &lt;code&gt;tests module&lt;&#x2F;code&gt;. Python provides us with an interesting  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;types.html#types.ModuleType&quot;&gt;class&lt;&#x2F;a&gt;: &lt;code&gt;types.ModuleType&lt;&#x2F;code&gt;, that will help us create a module, &lt;em&gt;you guessed it&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Used so you can do &amp;#39;from &amp;lt;name of file&amp;gt;.models import *&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;models_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.models&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;tests_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.tests&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;urls_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.urls&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# we created the urlpatterns list earlier,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s attach this variable to the urls_module:
&lt;&#x2F;span&gt;&lt;span&gt;urls_module.urlpatterns = urlpatterns
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# A model module needs to have classes that inherits from models.Model
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s correctly add all our models we defined earlier
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# as attributes to the models_module:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;variable_name, value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;list(locals().items()):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# We are only interested in models
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;inspect.isclass(value) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;issubclass(value, models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;        setattr(models_module, variable_name, value)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Setup the fake modules
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[models_module.__name__] = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[urls_module.__name__] = urls_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].models = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].urls = urls_module
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;going-further&quot;&gt;Going further?&lt;&#x2F;h3&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, I did \o&#x2F;. You may want to browse some of the gists kept by &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;search?q=mlvin&quot;&gt;Javier Buzzi&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;
You may also be really interested by the work done for  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;django-micro&lt;&#x2F;a&gt; a lightweight wrapper around Django that turns it into a microframework.
&lt;br&gt;&lt;br&gt;
If you have any kind of interesting improvements, advices, suggestions, please send me an email, or post a comment on &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@lemeteore&#x2F;104489090816400323&quot;&gt;Mastodon&lt;&#x2F;a&gt;. &lt;em&gt;Still not took the time to install a comment system, shame on me&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;o&#x2F;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Free and Open Source Software</title>
        <published>2017-04-04T00:00:00+00:00</published>
        <updated>2017-04-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/foss/"/>
        <id>https://nskm.xyz/posts/foss/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/foss/">&lt;p&gt;I&#x27;m often asked why do I prefer to use free software in places (Dakar, Libreville, Kinshasa, ...), where basically every human being is using closed source and proprietary software? Here are some of the reasons.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;not-being-able-to-pay-for-a-license&quot;&gt;&lt;strong&gt;Not being able to pay for a license&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Learning informatics was equivalent to installing a bunch of software requiring me to pay for a license. And coming from a very modest family, paying for a license was not an option. I&#x27;ve never really been able to explain to my parent that&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I need to pay, via internet, using a credit card&lt;&#x2F;li&gt;
&lt;li&gt;a company located somewhere in the world, I don&#x27;t even know where&lt;&#x2F;li&gt;
&lt;li&gt;to get the permission to use such an abstract thing like a software&lt;&#x2F;li&gt;
&lt;li&gt;for some time, then I&#x27;ll have to pay again, to renew the permission&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;tired-of-looking-for-the-crack&quot;&gt;&lt;strong&gt;Tired of looking for the crack&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Not being able to pay for the license, the remaining choice was to look for the crack. that was the most easy way to get the software you want to use. But in the mean time, That was a very difficult task, always browsing the internet, looking for the product keys, the key generator, the patch, the full activator, etc... It was time consuming, and boring as editors are always trying to make it more and more difficult.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;trying-to-be-a-good-citizen&quot;&gt;&lt;strong&gt;Trying to be a good citizen&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Even if they should, most people often do not feel bad about using cracked software. After all, there were no physical harm, no shoplifting, no unlawful entry into a building, no indiscriminate taking of goods. Why feeling bad about it?&lt;&#x2F;p&gt;
&lt;p&gt;Theft, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Theft&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In common usage, a theft is the illegal taking of another person&#x27;s property or services without that person&#x27;s permission or consent with the intent to deprive the rightful owner of it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Property, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Property#Types_of_property&quot;&gt;Wikepedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Important widely recognized types of property include real property (the combination of land and any improvements to or on the land), personal property (physical possessions belonging to a person), private property (property owned by legal persons, business entities or individual natural persons), public property (state owned or publicly owned and available possessions) and intellectual property (exclusive rights over artistic creations, inventions, etc.), although the last is not always as widely recognized or enforced.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
Above are the main reasons why I chose free and open source software. You can actually close this page, and go back to your awesome life, **thanks for reading**. But there is more.
&lt;br&gt;
&lt;h3 id=&quot;the-free-and-open-source-software-philosophy-promotes-values-that-go-beyond-software&quot;&gt;&lt;strong&gt;The free and open source software philosophy promotes values that go beyond software&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;own&lt;&#x2F;em&gt; an item, &lt;em&gt;to use it for any purpose&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;study&lt;&#x2F;em&gt; how this item is made&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;customize&lt;&#x2F;em&gt; this item&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;share&lt;&#x2F;em&gt; the item modified or not, with whoever you want&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;fine-can-we-have-some-real-life-examples-please&quot;&gt;&lt;strong&gt;Fine, can we have some real life examples please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;From &lt;a href=&quot;https:&#x2F;&#x2F;www.softwareheritage.org&#x2F;mission&#x2F;heritage&#x2F;&quot;&gt;Software Heritage&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software controls the electronic equipment embedded in the machines we use to travel, communicate, trade and exchange. Software is just crucial for the proper operation of every large organizations. Software has enabled the emergence of new forms of social and political organizations. Software is essential to understand our society.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Maybe it&#x27;s not perceptible enough, but free and open source software is already &lt;a href=&quot;http:&#x2F;&#x2F;embedded-computing.com&#x2F;articles&#x2F;open-source-software-everywhere&#x2F;&quot;&gt;everywhere&lt;&#x2F;a&gt;. Here you are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Aerospace: Open Source Software projects from &lt;a href=&quot;https:&#x2F;&#x2F;code.nasa.gov&#x2F;&quot;&gt;NASA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Automotive: &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&quot;&gt;AGL&lt;&#x2F;a&gt; group, including lots of &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&#x2F;about&#x2F;members&quot;&gt;automakers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Robotics: &lt;a href=&quot;https:&#x2F;&#x2F;www.osrfoundation.org&#x2F;osrf-projects&#x2F;&quot;&gt;Open Source Robotics Foundation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Healthcare: &lt;a href=&quot;http:&#x2F;&#x2F;www.open-emr.org&#x2F;&quot;&gt;Open-EMR&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;openmrs.org&#x2F;&quot;&gt;OpenMRS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Education: &lt;a href=&quot;http:&#x2F;&#x2F;open-sankore.org&#x2F;en&quot;&gt;Open Sankoré&lt;&#x2F;a&gt;, an interactive whiteboard software.&lt;&#x2F;li&gt;
&lt;li&gt;Films: &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=eRsGyueVLvQ&quot;&gt;Sintel&lt;&#x2F;a&gt;, and many other open movies by &lt;a href=&quot;https:&#x2F;&#x2F;www.blender.org&#x2F;features&#x2F;projects&#x2F;&quot;&gt;Blender Foundation&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
It is no more about software, it is about **openess and freedom**.
&lt;br&gt;
The topic is actually very huge and deep, I&#x27;ve not even mentioned privacy, nor surveillance. I obviously won&#x27;t be able to cover the whole thing. 
&lt;h3 id=&quot;for-those-who-want-to-go-further-i-strongly-recommands-the-following-links&quot;&gt;&lt;strong&gt;For those who want to go further, I strongly recommands the following links:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xKsR5jWl1Tk&quot;&gt;Threats of data mining&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8vOF8VsUwbA&quot;&gt;Freedom in the cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;modernfarmer.com&#x2F;2016&#x2F;07&#x2F;right-to-repair&#x2F;&quot;&gt;Right to fix their own dang tractors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opensource.com&#x2F;article&#x2F;17&#x2F;4&#x2F;become-open-source-sustainer&quot;&gt;Why you should become an open source sustainer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;anybox.fr&#x2F;blog&#x2F;pourquoi-l-open-source&quot;&gt;Pourquoi l&#x27;open source&lt;&#x2F;a&gt; (French)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Threads</title>
        <published>2017-03-08T04:30:25+00:00</published>
        <updated>2017-03-08T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/an-overwiew-on-threads/"/>
        <id>https://nskm.xyz/posts/an-overwiew-on-threads/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/an-overwiew-on-threads/">&lt;p&gt;I&#x27;ve written something about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;processes&lt;&#x2F;a&gt; Let&#x27;s write some notes about threads. This is not really an introduction to threads. It&#x27;s more like a little bit of introspection, so we can have an interesting perspective of what are threads.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;what-s-really-a-thread&quot;&gt;&lt;strong&gt;What&#x27;s really a thread?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Processes each have their own address space. Threads exist as subsets of a process. Threads are just multiple workers in the same &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;virtual address space&lt;&#x2F;a&gt; all threads in a process share the same memory. They can also share open files and other resources. Within that VAS, each thread has its own ID, its own stack, its own program counter, its own independent flow of control, its own registers set. A thread is just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;threads-example.gif&quot; alt=&quot;Threads&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;mooneegee.blogspot.sn&#x2F;2015&#x2F;01&#x2F;os-thread.html&quot;&gt;mooneegee.blogspot.sn&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Next is a c script spawning two &lt;em&gt;posix&lt;&#x2F;em&gt; threads:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define _GNU_SOURCE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;pthread.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; sleep
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;syscall.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void * &lt;&#x2F;span&gt;&lt;span&gt;say_hello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void* &lt;&#x2F;span&gt;&lt;span&gt;data){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;str = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt;)data;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; howmany = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; r = (rand() % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pid_t thread_id = syscall(__NR_gettid);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(howmany &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    sleep(r);
&lt;&#x2F;span&gt;&lt;span&gt;    howmany = howmany - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,str);
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;from thread &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and process &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;           thread_id, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return NULL&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:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_t t1,t2;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(getpid() &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unable to get pid&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:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The main process id is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;howdy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;If we &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;strace&lt;&#x2F;a&gt; the execution of our c script:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ strace -f .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output will display lots of informations. And for what we are doing, the most interesting lines will look like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;clone(child_stack=0x7f30fa9b8ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa9b99d0, tls=0x7f30fa9b9700, child_tidptr=0x7f30fa9b99d0) = 7450
&lt;&#x2F;span&gt;&lt;span&gt;Process 7450 attached
&lt;&#x2F;span&gt;&lt;span&gt;[pid  7449] clone(child_stack=0x7f30fa1b7ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa1b89d0, tls=0x7f30fa1b8700, child_tidptr=0x7f30fa1b89d0) = 7451
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-clone-system-call&quot;&gt;&lt;strong&gt;The clone() system call:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;Processes&lt;&#x2F;a&gt; are created with the &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;fork()&lt;&#x2F;a&gt; system call. However, there is a separate system call, named &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;clone()&lt;&#x2F;a&gt; which is used for creating threads. It works like fork(), but it accepts a number of flags for adjusting its behavior so the child can share some parts of the parent&#x27;s execution context. Our c script made a call to clone() twice. And looking at &lt;em&gt;some&lt;&#x2F;em&gt; of the flags that have been passed, we can see that:&lt;&#x2F;p&gt;
&lt;p&gt;the caller and the child process:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CLONE_VM: run in the &lt;strong&gt;same memory space&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FS: share the &lt;strong&gt;same filesystem information&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FILES: share the &lt;strong&gt;same file descriptor table&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_THREAD: are placed in the &lt;strong&gt;same thread group&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;p&gt;Another interesting arguments passed to clone system call are &lt;code&gt;child_stack&lt;&#x2F;code&gt; and &lt;code&gt;tls&lt;&#x2F;code&gt;. From the man page, we can read &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;somewhere&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The child_stack argument specifies the location of the stack used by the child process.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And in &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;set_thread_area.2.html&quot;&gt;another part&lt;&#x2F;a&gt; of the man page:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;set a thread local storage (TLS) area&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Basically, we&#x27;re allocating a &lt;em&gt;personal stack&lt;&#x2F;em&gt; to each of our threads. But, we also give each thread, an access to a region of memory which is &lt;em&gt;not shared&lt;&#x2F;em&gt; with all other threads. Like one may do with Python using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;threading.html#thread-local-data&quot;&gt;threading.local&lt;&#x2F;a&gt; class.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gdb-to-the-rescue&quot;&gt;&lt;strong&gt;GDB to the rescue&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let&#x27;s have a confirmation using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ gdb .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;First, we set two breakpoints, one at the start of the main function, another one at the start of the say_hello function:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;insert-breakpoints.png&quot; alt=&quot;insert breakpoints&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then we start the debugged program: &lt;code&gt;r&lt;&#x2F;code&gt;, and list the mapped memory regions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map1.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So far, we see only one stack segment, the one used by the main process, that is because our threads are not yet created. Let&#x27;s continue a little bit (twice) with &lt;code&gt;c&lt;&#x2F;code&gt;, and you should be able to see something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map2.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This time, we can see three stacks in the same virtual address space. The ones used by our threads are &lt;code&gt;[stack:15074]&lt;&#x2F;code&gt; and &lt;code&gt;[stack:15075]&lt;&#x2F;code&gt;. GDB to inspect each thread&#x27;s stack:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;stacks.png&quot; alt=&quot;thread&amp;#39;s stack&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LWP is an acronym and stands for Light Weight Process. Next to LWP is the thread ID assigned by the kernel to this thread. We see that each thread has its own stack, and inside each stack, the progress is different, while thread 3 is entering the say_hello function, thread 2 is in &lt;em&gt;nanosleep&lt;&#x2F;em&gt;. By the way nanosleep is also a &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;nanosleep.2.html&quot;&gt;system call&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we are, a thread is indeed just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t be able to cover the whole topic as it&#x27;s not an easy and small one. So you may find &lt;em&gt;really&lt;&#x2F;em&gt; interesting the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;pthreads.7.html&quot;&gt;Pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;7577&#x2F;&quot;&gt;Making Linux safe for pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.linfo.org&#x2F;context_switch.html&quot;&gt;Context switch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;0xax.gitbooks.io&#x2F;linux-insides&#x2F;content&#x2F;SyncPrim&#x2F;sync-3.html&quot;&gt;Semaphores&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;dont-share-mutable-state&#x2F;&quot;&gt;The real reason not to share a mutable state&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Django single file project</title>
        <published>2017-01-12T17:17:17+00:00</published>
        <updated>2017-01-12T17:17:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/dsfp/"/>
        <id>https://nskm.xyz/posts/dsfp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/dsfp/">&lt;h4 id=&quot;disclaimer&quot;&gt;&lt;strong&gt;Disclaimer?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The main purpose of this post is learning. Like any tool we should explore and find ways to bend it until it breaks. You should &lt;em&gt;normally&lt;&#x2F;em&gt; not use those techniques in real life projects &lt;em&gt;right&lt;&#x2F;em&gt;? For this post, I&#x27;m assuming you&#x27;re using Django 1.10.4, and Python3.6.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;single-file&quot;&gt;&lt;strong&gt;Single file?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Before reading &lt;a href=&quot;http:&#x2F;&#x2F;shop.oreilly.com&#x2F;product&#x2F;0636920032502.do&quot;&gt;Lightweight Django&lt;&#x2F;a&gt;, I never tought it was possible to build a Django project in a single python file. For that kind of stuff, I usually think, &lt;a href=&quot;http:&#x2F;&#x2F;flask.pocoo.org&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt;, or &lt;a href=&quot;http:&#x2F;&#x2F;bottlepy.org&#x2F;docs&#x2F;dev&#x2F;&quot;&gt;Bottle&lt;&#x2F;a&gt;. And in fact, there are many &lt;a href=&quot;http:&#x2F;&#x2F;codecondo.com&#x2F;14-minimal-web-frameworks-for-python&#x2F;&quot;&gt;others&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After reading the first chapter, I was a little bit disappointed. There were no Django &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;topics&#x2F;db&#x2F;models&#x2F;&quot;&gt;models&lt;&#x2F;a&gt; involved in the shown example. So, I try to find out if it was possible: &lt;strong&gt;a single file Django project with at least one application containing one model&lt;&#x2F;strong&gt;. I found some interesting links on the topic. But either it was for a very old version of Django, either I was obliged to install another package besides Django. After few days reading others people code, this is what I&#x27;ve done:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;settings
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the current folder name will also be our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;settings.configure(
&lt;&#x2F;span&gt;&lt;span&gt;    DEBUG=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEBUG&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    SECRET_KEY=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;SECRET_KEY&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, os.urandom(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;)),
&lt;&#x2F;span&gt;&lt;span&gt;    ALLOWED_HOSTS=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ALLOWED_HOSTS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;,&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ROOT_URLCONF=__name__,
&lt;&#x2F;span&gt;&lt;span&gt;    MIDDLEWARE=[
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.security.SecurityMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions.middleware.SessionMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.middleware.common.CommonMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.middleware.csrf.CsrfViewMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.middleware.AuthenticationMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.middleware.MessageMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.middleware.clickjacking.XFrameOptionsMiddleware&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:#d69d85;&quot;&gt;&amp;#39;django.middleware.locale.LocaleMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&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:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;static&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    STATICFILES_DIRS=[
&lt;&#x2F;span&gt;&lt;span&gt;        os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static_root&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;media&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;media&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&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:#d69d85;&quot;&gt;&amp;#39;BACKEND&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.backends.django.DjangoTemplates&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:#d69d85;&quot;&gt;&amp;#39;DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;templates&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:#d69d85;&quot;&gt;&amp;#39;APP_DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;OPTIONS&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:#d69d85;&quot;&gt;&amp;#39;context_processors&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:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.debug&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:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.i18n&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:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.request&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.context_processors.auth&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:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.tz&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.context_processors.messages&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;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    DATABASES={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&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:#d69d85;&quot;&gt;&amp;#39;ENGINE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.db.backends.sqlite3&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:#d69d85;&quot;&gt;&amp;#39;NAME&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;db.sqlite3&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;span&gt;    REST_FRAMEWORK={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEFAULT_PERMISSION_CLASSES&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:#d69d85;&quot;&gt;&amp;#39;rest_framework.permissions.IsAdminUser&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;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;PAGE_SIZE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&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:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create your models here.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Book)
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Author)
&lt;&#x2F;span&gt;&lt;span&gt;admin.autodiscover()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BookSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Book
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__all__&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BooksViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ReadOnlyModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Book.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = BookSerializer
&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:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;url, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.http &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;books&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, BooksViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;index(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&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;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;admin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, admin.site.urls),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, index, name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;homepage&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api-auth&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework.urls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,\
&lt;&#x2F;span&gt;&lt;span&gt;                                   namespace=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&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;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.wsgi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_wsgi_application
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&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:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.management &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;execute_from_command_line
&lt;&#x2F;span&gt;&lt;span&gt;    execute_from_command_line(sys.argv)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    get_wsgi_application()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Everything related to &lt;a href=&quot;http:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;&quot;&gt;Django REST Framework&lt;&#x2F;a&gt; is not mandatory. I was looking for &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;979&#x2F;&quot;&gt;interesting links&lt;&#x2F;a&gt; over the internet, and I found this question on &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;32866578&#x2F;4055832&quot;&gt;StackOverflow&lt;&#x2F;a&gt;. I saw this as an opportunity to kill two birds with one stone.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The above script was saved in a file named &lt;code&gt;single.py&lt;&#x2F;code&gt; in a folder named &lt;code&gt;lwdj&lt;&#x2F;code&gt;. But you can do as you feel, as soon as you respect the name of the file and the name of the current folder. The rest is known story:&lt;&#x2F;p&gt;
&lt;p&gt;Make the migrations for our application:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py makemigrations lwdj
&lt;&#x2F;span&gt;&lt;span&gt;Migrations for &amp;#39;lwdj&amp;#39;:
&lt;&#x2F;span&gt;&lt;span&gt;  migrations&#x2F;0001_initial.py:
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Author
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%) ⤷
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Run the migrations:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py migrate
&lt;&#x2F;span&gt;&lt;span&gt;Operations to perform:
&lt;&#x2F;span&gt;&lt;span&gt;  Apply all migrations: admin, auth, contenttypes, lwdj, sessions
&lt;&#x2F;span&gt;&lt;span&gt;Running migrations:
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0002_logentry_remove_auto_add... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0002_remove_content_type_name... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0002_alter_permission_name_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0003_alter_user_email_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0004_alter_user_username_opts... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0005_alter_user_last_login_null... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0006_require_contenttypes_0002... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0007_alter_validators_add_error_messages... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0008_alter_user_username_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying lwdj.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying sessions.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Create a super user and run the server:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py createsuperuser
&lt;&#x2F;span&gt;&lt;span&gt;Username (leave blank to use &amp;#39;nsukami&amp;#39;):
&lt;&#x2F;span&gt;&lt;span&gt;Email address: nsukami@gmail.com
&lt;&#x2F;span&gt;&lt;span&gt;Password:
&lt;&#x2F;span&gt;&lt;span&gt;Password (again):
&lt;&#x2F;span&gt;&lt;span&gt;Superuser created successfully.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Performing system checks...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;January 12, 2017 - 18:52:57
&lt;&#x2F;span&gt;&lt;span&gt;Django version 1.10.4, using settings None
&lt;&#x2F;span&gt;&lt;span&gt;Starting development server at http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;Quit the server with CONTROL-C.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;so-what-have-we-learned-here&quot;&gt;&lt;strong&gt;So, what have we learned here?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Yes, that is not how you are supposed to use Django. But we were able to learn few things.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;projects-and-applications&quot;&gt;&lt;strong&gt;Projects and applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Somewhere in the Django documentation related to &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;applications&#x2F;#projects-and-applications&quot;&gt;projects and applications&lt;&#x2F;a&gt;, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&#x27;s no restriction that a project package can&#x27;t also be considered an application and have models, etc. (which would require adding it to INSTALLED_APPS).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We can double check using the &lt;code&gt;tree&lt;&#x2F;code&gt; command:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ tree
&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;├── activate -&amp;gt; &#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;bin&#x2F;activate
&lt;&#x2F;span&gt;&lt;span&gt;├── db.sqlite3
&lt;&#x2F;span&gt;&lt;span&gt;├── Makefile
&lt;&#x2F;span&gt;&lt;span&gt;├── media
&lt;&#x2F;span&gt;&lt;span&gt;├── migrations
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── 0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── __init__.py
&lt;&#x2F;span&gt;&lt;span&gt;│   └── __pycache__
&lt;&#x2F;span&gt;&lt;span&gt;│       └── __init__.cpython-36.pyc
&lt;&#x2F;span&gt;&lt;span&gt;├── single.py
&lt;&#x2F;span&gt;&lt;span&gt;├── static
&lt;&#x2F;span&gt;&lt;span&gt;│   └── site.css
&lt;&#x2F;span&gt;&lt;span&gt;├── static_root
&lt;&#x2F;span&gt;&lt;span&gt;└── templates
&lt;&#x2F;span&gt;&lt;span&gt;    └── home.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-django-setup-method&quot;&gt;&lt;strong&gt;The django.setup() method&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Reading The Fabulous &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;Manual&lt;&#x2F;a&gt;, we learn that, this method configures Django by loading the settings, but also:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When Django starts, django.setup() is responsible for populating the application registry.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s start a shell using the command &lt;code&gt;python single.py shell&lt;&#x2F;code&gt;, and let&#x27;s check the application registry:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.apps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;apps
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.ready
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.get_app_configs()
&lt;&#x2F;span&gt;&lt;span&gt;odict_values([&amp;lt;AppConfig: lwdj&amp;gt;, &amp;lt;AdminConfig: admin&amp;gt;, &amp;lt;AuthConfig: auth&amp;gt;, &amp;lt;ContentTypesConfig: contenttypes&amp;gt;, &amp;lt;SessionsConfig: sessions&amp;gt;, &amp;lt;MessagesConfig: messages&amp;gt;, &amp;lt;StaticFilesConfig: staticfiles&amp;gt;, &amp;lt;AppConfig: rest_framework&amp;gt;])
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c = apps.get_app_config(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.module
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;module &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;(namespace)&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.path
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GITHUB&#x2F;how_tos&#x2F;how_to_django&#x2F;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.verbose_name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.label
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;c.models: print(m)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;author
&lt;&#x2F;span&gt;&lt;span&gt;book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Neat!
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We also &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;read&lt;&#x2F;a&gt; that:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;At this stage, your code shouldn&#x27;t import any models!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is exactly why our models, and everything related to them, do not appear before those 2 lines of code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Doing otherwise, raises the &lt;code&gt;AppRegistryNotReady&lt;&#x2F;code&gt; exception:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;single.py&amp;quot;, line 90, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    class Author(models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;db&#x2F;models&#x2F;base.py&amp;quot;, line 105, in __new__
&lt;&#x2F;span&gt;&lt;span&gt;    app_config = apps.get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 237, in get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;    self.check_apps_ready()
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 124, in check_apps_ready
&lt;&#x2F;span&gt;&lt;span&gt;    raise AppRegistryNotReady(&amp;quot;Apps aren&amp;#39;t loaded yet.&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;django.core.exceptions.AppRegistryNotReady: Apps aren&amp;#39;t loaded yet.
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;installed-applications&quot;&gt;&lt;strong&gt;Installed applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;I have not yet fully understood this part. &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; is actually containing the name of the current directory. By putting &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; inside &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt;, Django was able to find all the Django models existing inside the current directory:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; highlight python &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&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:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&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:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;app-label&quot;&gt;&lt;strong&gt;App label&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;All our models were created outside of a &lt;code&gt;models.py&lt;&#x2F;code&gt; file. They&#x27;re not even in a &lt;em&gt;real&lt;&#x2F;em&gt; Django application. So we were obliged to tell them which application they belongs to. This is done using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;models&#x2F;options&#x2F;#app-label&quot;&gt;app_label&lt;&#x2F;a&gt; attribute of the internal &lt;code&gt;class Meta&lt;&#x2F;code&gt; of Django models.
{{&amp;lt; highlight python &amp;gt;}}
class Author(models.Model):
name = models.CharField(max_length=200)
class Meta:
app_label = APP_LABEL&lt;&#x2F;p&gt;
&lt;p&gt;class Book(models.Model):
author = models.ForeignKey(Author, related_name=&#x27;books&#x27;)
title = models.CharField(max_length=400)
class Meta:
app_label = APP_LABEL
{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Really hope you learnt something. Also, I would not be able to write this post, without following the &lt;em&gt;StackTrace&lt;&#x2F;em&gt; leaved by the people who were there before me. A huge thanks to them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dotmobo.github.io&#x2F;django-minimaliste.html&quot;&gt;Créer une application django minimaliste&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.fahhem.com&#x2F;2011&#x2F;10&#x2F;django-models-without-apps-or-everything-django-truly-in-a-single-file&#x2F;&quot;&gt;Django Models without Apps OR Everything Django Truly in a Single File&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;Django as microframework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Make</title>
        <published>2016-11-25T00:00:00+00:00</published>
        <updated>2016-11-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/mk/"/>
        <id>https://nskm.xyz/posts/mk/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/mk/">&lt;p&gt;if you have some &lt;strong&gt;complex and esoteric shell commands&lt;&#x2F;strong&gt; that you have to run on a regular basis, it can be convenient to just package them up &lt;em&gt;somewhere&lt;&#x2F;em&gt;, so you don&#x27;t have to &lt;strong&gt;remember them&lt;&#x2F;strong&gt; or &lt;strong&gt;type them out every time&lt;&#x2F;strong&gt;. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Why, I don&#x27;t use Makefiles more often? Even though I know I should. One of the reason may be because, as an Emacs user, automating simple tasks is &lt;em&gt;funny&lt;&#x2F;em&gt; using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;manual&#x2F;html_node&#x2F;elisp&#x2F;&quot;&gt;Emacs Lisp&lt;&#x2F;a&gt;. Following are simple elisp functions I use to compile a C file, nothing extraordinary:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;lisp&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-lisp &quot;&gt;&lt;code class=&quot;language-lisp&quot; data-lang=&quot;lisp&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-save-compile ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Save, and compile c file.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (save-buffer)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile
&lt;&#x2F;span&gt;&lt;span&gt;   (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cc -Wall -Wextra -pedantic -std=c11 -g %s -o .&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;           (buffer-file-name)
&lt;&#x2F;span&gt;&lt;span&gt;           (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-run ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Run c code.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                   (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Another reason I don&#x27;t use Makefiles more often could be, the &lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;Bash-Beginners-Guide&#x2F;html&#x2F;Bash-Beginners-Guide.html&quot;&gt;Bourne Again Shell&lt;&#x2F;a&gt;. I find it easier to quickly write shell aliases for repetitive tasks. The following is some aliases I &lt;em&gt;sometimes&lt;&#x2F;em&gt; use whenever I&#x27;m doing &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; development:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# my weird aliases
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_runserver=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py runserver&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shell=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shellp=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell_plus&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_make=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py makemigrations&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_mig=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py migrate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_csu=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py createsuperuser&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_smtpd=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python -m smtpd -n -c DebuggingServer localhost:1025&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Make do have a reputation for being complex. Indeed, it can be very &lt;a href=&quot;http:&#x2F;&#x2F;okmij.org&#x2F;ftp&#x2F;Computation&#x2F;#Makefile-functional&quot;&gt;esoteric&lt;&#x2F;a&gt;. The full &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;manual&lt;&#x2F;a&gt; is a 183 pages. Fortunately, you can ignore most of this, Make can be used in a very simple and incredibly useful way. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The following, is a Makefile I sometimes use in replacement of the shell aliases above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-make &quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Makefile for (the project)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Nsukami
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# November 2016
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SHELL := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tas&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PYTHON_BIN := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;VIRTUAL_ENV&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.dev&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.prod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.test&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;shell dirname &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;realpath &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;lastword &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;MAKEFILE_LIST&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;))))&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;python manage.py&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# if not on prod server, use dev settings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;ifneq &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;shell uname -n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,phobos)
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;DEV_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROD_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: all - Default target. Does nothing.
&lt;&#x2F;span&gt;&lt;span&gt;all:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nothing to do by default. Try &amp;#39;make help&amp;#39;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: help - Show list of targets + description
&lt;&#x2F;span&gt;&lt;span&gt;help:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;^# target:&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Mm&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;akefile
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: init - Install that a dev needs to get up and running.
&lt;&#x2F;span&gt;&lt;span&gt;init: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;bootstrap.sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo .&#x2F;bootstrap.sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean - remove all useless files
&lt;&#x2F;span&gt;&lt;span&gt;clean: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clean-pyc clean-build&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-pyc - remove all auto generated files
&lt;&#x2F;span&gt;&lt;span&gt;clean-pyc:
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*~&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force  {} +
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-build - remove all auto generated folders
&lt;&#x2F;span&gt;&lt;span&gt;clean-build:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive build&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive dist&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive htmlcov
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive .coverage
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.egg-info
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: translate - calls the &amp;quot;makemessages&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;translate:
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; $(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -a
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: test - calls the &amp;quot;test&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;test:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: run - calls the &amp;quot;runserver&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;run:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: update - install (and update) pip requirements
&lt;&#x2F;span&gt;&lt;span&gt;update:
&lt;&#x2F;span&gt;&lt;span&gt;    pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;requirements&#x2F;dev.txt
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: collect - calls the &amp;quot;collectstatic&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;collect:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;collectstatic --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; --noinput
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: rebuild - rebuild tables from models
&lt;&#x2F;span&gt;&lt;span&gt;rebuild:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemigrations --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;migrate --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: deploy - let make take care of deployment
&lt;&#x2F;span&gt;&lt;span&gt;deploy:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I call fabric here?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.ONESHELL:
&lt;&#x2F;span&gt;&lt;span&gt;.PHONY: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;all help translate test clean update collect rebuild run clean-pyc clean-build clean init&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Finally, the other reason, and probably the main reason I don&#x27;t use Makefiles more often, it&#x27;s because of &lt;a href=&quot;http:&#x2F;&#x2F;www.fabfile.org&#x2F;&quot;&gt;Fabric&lt;&#x2F;a&gt;. Following is a fabfile more or less doing the same thing as the Makefile above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# -*- coding: utf-8 -*- #
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; fabric commands &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;fabric.api &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;env, sudo, cd, local, task, run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;fabric.contrib.project &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;project
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Local path configuration (can be absolute or relative to fabfile)
&lt;&#x2F;span&gt;&lt;span&gt;env.hosts = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;env.use_ssh_config = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;env.ssh_config_path = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;.ssh&#x2F;config&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;env.owner = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;nsukami&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;tas&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.dev&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.prod&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.test&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python manage.py &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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;uname():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Prints information about the host. &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;uname -n&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:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;uname() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is not &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;phobos&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = DEV_SETTINGS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = PROD_SETTINGS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;init():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;init - Install that a dev needs to get up and running.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        sudo(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bootstrap.sh&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean - remove all useless files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    clean_pyc()
&lt;&#x2F;span&gt;&lt;span&gt;    clean_build()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_pyc():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;# clean-pyc - remove all auto generated files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyc&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyo&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*~&amp;#39; -exec rm --force  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_build():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean-build - remove all auto generated folders&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive build&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive dist&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive htmlcov&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive .coverage&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive *.egg-info&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;translate():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;translate - calls the &amp;#39;makemessages&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; -a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;        local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;test():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test - calls the &amp;#39;test&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;runserver():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;run - calls the &amp;#39;runserver&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;update():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update - install (and update) pip requirements&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;requirements&#x2F;dev.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We see that Fabric &lt;em&gt;can&lt;&#x2F;em&gt; be used as a build tool even though it isn&#x27;t one. It is easy to read and write, especially for a Python developer. The drawback may be, it does require Python to run. &lt;em&gt;Seriously, who cares?&lt;&#x2F;em&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;New year resolution: &lt;strong&gt;using Makefiles more often.&lt;&#x2F;strong&gt;
&lt;br&gt;&lt;br&gt;
More on the topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;Make&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=5276339&quot;&gt;Make alternatives&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_build_automation_software&quot;&gt;List of build automation software&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How to create processes</title>
        <published>2016-08-22T03:40:17+00:00</published>
        <updated>2016-08-22T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/process-creation/"/>
        <id>https://nskm.xyz/posts/process-creation/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/process-creation/">&lt;p&gt;We&#x27;ve seen &lt;a href=&quot;&#x2F;on-processes.md&quot;&gt;processes&lt;&#x2F;a&gt;, We&#x27;ve said lots of things about processes, but we did not talk about process creation. Let&#x27;s see how to create a process in C, in &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;&quot;&gt;Golang&lt;&#x2F;a&gt;, and in &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;en-US&#x2F;&quot;&gt;Rustlang&lt;&#x2F;a&gt; &lt;em&gt;&lt;strong&gt;Disclaimer:&lt;&#x2F;strong&gt; I&#x27;m not doing a comparison to find out which one is better than the other. I just want to explore how the same task can be done using different approaches.&lt;br&gt;&lt;br&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fork-and-exec&quot;&gt;&lt;strong&gt;Fork and Exec:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;UNIX processes are created using the fork() &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;System_call&quot;&gt;system call&lt;&#x2F;a&gt;. Fork is the primary method of process creation on Unix-like operating systems.  Fork is the system call that the parent process uses to &quot;divide&quot; itself, to &quot;fork&quot; into two identical processes. The child process will be the exact copy of the parent except for the return value.&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Exec_(system_call)&quot;&gt;exec()&lt;&#x2F;a&gt; system call and its family of functions are almost always used with fork(). The exec() syscall and the like overwrite the current [stackframe]({{&amp;lt; ref on-processes &amp;gt;}})with the name of the application passed to it.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;c&quot;&gt;&lt;strong&gt;C:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In C, there is nothing special to do, contrary to Golang and Rustlang. You just really call fork(), then exec(), simple and direct. The following, is an example written in C:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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 style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;  pid = fork();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; if pid equals 0,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#608b4e;&quot;&gt;&#x2F;&#x2F; we&amp;#39;re dealing with the child process
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I am the child process, my pid is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; execvp will search for ls on $PATH
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#608b4e;&quot;&gt;&#x2F;&#x2F; catch any error that may occur during execution
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(EXIT_FAILURE);
&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:#608b4e;&quot;&gt;&#x2F;&#x2F; returned pid is -1, fork operation failed
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&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:#608b4e;&quot;&gt;&#x2F;&#x2F; The wait system-call blocks the parent process
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and waits for the child-process to end.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;go&quot;&gt;&lt;strong&gt;Go:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Go, it is recommended to use the &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;exec&#x2F;&quot;&gt;exec&lt;&#x2F;a&gt; package. It runs external commands, and wraps &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;#StartProcess&quot;&gt;os.StartProcess&lt;&#x2F;a&gt; function for you. Following, is the previous example, this time written in Golang:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;go&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-go &quot;&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;package &lt;&#x2F;span&gt;&lt;span&gt;main
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;syscall&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&#x2F;exec&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check if ls command exists in the PATH
&lt;&#x2F;span&gt;&lt;span&gt;    binary, lookErr := exec.LookPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&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:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;lookErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(lookErr)
&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:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    args := []string{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&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:#608b4e;&quot;&gt;&#x2F;&#x2F; fork new process and execute our program
&lt;&#x2F;span&gt;&lt;span&gt;    execErr := syscall.Exec(binary, args, os.Environ())
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; catch error if any
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;execErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(execErr)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;rust&quot;&gt;&lt;strong&gt;Rust:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Rust, we have &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html&quot;&gt;std::process::Command&lt;&#x2F;a&gt;. It is is a type that acts as a process builder and provides fine-grained control over how the new process should be spawned. If we browse the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;std&#x2F;process.rs.html#521&quot;&gt;source code&lt;&#x2F;a&gt;, we can read beginning line 521:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Constructs a new &lt;code&gt;Command&lt;&#x2F;code&gt; for launching the program at&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;path &lt;code&gt;program&lt;&#x2F;code&gt;, with the following default configuration:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;No arguments to the program&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s environment&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s working directory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit stdin&#x2F;stdout&#x2F;stderr for &lt;code&gt;spawn&lt;&#x2F;code&gt; or &lt;code&gt;status&lt;&#x2F;code&gt;, but create pipes for &lt;code&gt;output&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;Basically, it behave a little bit like a call to fork(), followed by a call to exec(). Let&#x27;s rewrite the previous example in Rust:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::process::Command;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = Command::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .output()
&lt;&#x2F;span&gt;&lt;span&gt;                     .expect(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls command failed to start&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;stdout: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, String::from_utf8_lossy(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;output.stdout));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html#method.output&quot;&gt;output&lt;&#x2F;a&gt; function executes the command as a child process, waiting for it to finish and collecting all of its output. By default, stdin, stdout and stderr are captured (and used to provide the resulting output).&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;option&#x2F;enum.Option.html#method.expect&quot;&gt;expect&lt;&#x2F;a&gt; function is used for quick and dirty error handling.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;strace-trace-system-calls-and-signals&quot;&gt;&lt;strong&gt;Strace, trace system calls and signals:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Somewhere in the strace&#x27;s manual page, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If everything went normally during the execution of our scripts, we should see, in the strace&#x27;s output, lots of system calls, the most important ones being a call to &lt;strong&gt;clone()&lt;&#x2F;strong&gt;, followed by a call to &lt;strong&gt;exec()&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;4714  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;CLONE_CHILD_SETTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;SIGCHLD, child_tidptr=0x7fac5d28da90) = 4715
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;7564  execve(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;bin&#x2F;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; 74 vars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;unfinished ...&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;fork() was the original UNIX system call. Only used to create new processes, not threads. Also, it is portable.&lt;&#x2F;p&gt;
&lt;p&gt;clone() is a new, versatile system call which can be used to create, depending on the passed option, a UNIX process, or a POSIX thread, or something in between, or something completely different. I invite you to &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Read The Fabulous Manual&lt;&#x2F;a&gt; about clone().&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t really know if there is something else you can read to learn more on this topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;Fork&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;exec.3.html&quot;&gt;Exec&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Clone&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;Strace&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Processes</title>
        <published>2016-08-09T03:40:17+00:00</published>
        <updated>2016-08-09T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/processes-introduction/"/>
        <id>https://nskm.xyz/posts/processes-introduction/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/processes-introduction/">&lt;p&gt;As a Debian user, I often want to see the active processes, sometimes, I want to kill them. I know how to launch a new process, inside my Python scripts. But what is a process?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;A process is the execution context of a running program. When an executable program is read into memory by the kernel and executed, it becomes a process. Processes are dynamic entities, they are constantly changing as their machine code instructions are executed by the CPU.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;With the exception of the &lt;code&gt;init process&lt;&#x2F;code&gt;, every process is the child of another process. And every process has the potential to be the parent of another process. The following is a small C program that will print the current process ID and the corresponding parent process ID:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main (){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; ch;
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getpid ());
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The parent process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getppid ());
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;( ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&amp;amp; ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    ch = getchar();
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After execution, you should see something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;~
&lt;&#x2F;span&gt;&lt;span&gt;+-&amp;gt; .&#x2F;bin&#x2F;ex1
&lt;&#x2F;span&gt;&lt;span&gt;The process ID is 11147
&lt;&#x2F;span&gt;&lt;span&gt;The parent process ID is 9552
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a name=&quot;vas&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;virtual-address-space&quot;&gt;&lt;strong&gt;Virtual address space?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A virtual address space, &lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process. The virtual address space is what a process sees when it executes. A process works with and only sees VAS. The operating system handles mapping VAS to real storage so that this is invisible to the running program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;We need VAS to prevent process A and process B from writing&#x2F;reading in the same memory addresses. VAS is a way to achieve &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Process_isolation&quot;&gt;process isolation&lt;&#x2F;a&gt;. With VAS, several programs could write to memory location at the same address without stepping over each others results.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;vas-schema.9c317ee408a2f21e.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;www.tenouk.com&#x2F;ModuleW_files&#x2F;ccompilerlinker007.png&quot;&gt;tenouk.com&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-s-inside-vas&quot;&gt;&lt;strong&gt;What&#x27;s inside VAS?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process, so what is inside a VAS? A typical memory representation of process consists of following sections:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that is used for several related purposes, the main one being to keep track of the point to which each active subroutine should return control when it finishes executing. The return address is pushed onto the stack by the caller. When it finishes, the called subroutine, pops the return address off the stack and transfers control to that address. &lt;br&gt;&lt;br&gt;That section also stores temporary variables created by each function inside the program. The stack is a LIFO data structure, managed and optimized by the CPU quite closely. Every time a function declares a new variable, it is &quot;pushed&quot; onto the stack, you don&#x27;t have to allocate the needed memory by hand. Then every time a function exits, all of the variables pushed onto the stack by that function, are freed for you. Once a stack variable is freed, that region of memory becomes available for other stack variables.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Heap:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section where dynamic memory allocation usually takes place. Unlike the Stack, this part of the VAS is not managed automatically for you, and is not as tightly managed by the CPU. You are in charge of allocating memory on the heap. You are also responsible for deallocating that memory once you don&#x27;t need it any more. If you fail to do this, your program will have what is known as a memory leak.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialized Data Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
Or simply, Data Segment. VAS section, which contains the global and static variables that are initialized by the programmer. The size of this segment is determined by the size of the values in the program&#x27;s source code, and does not change at run time.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uninitialized (bss) Data Segment:&lt;&#x2F;strong&gt; &lt;br&gt;
VAS section that contains all global and static variables that are initialized to zero or do not have explicit initialization in the programer&#x27;s source code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Text (code) Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that contains machine instructions of the program. Those machine instructions can be thought of as the text of a novel: It tells the story of what the program does.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-do-some-introspection&quot;&gt;&lt;strong&gt;How to do some introspection?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;How do we learn about the memory layout of a running process? How do we look at how program are laid out in memory?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Directly from &#x2F;proc&#x2F;PID&#x2F;maps:&lt;br&gt;&lt;&#x2F;strong&gt;
You can directly ask to the process information pseudo-filesystem: &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;proc&lt;&#x2F;a&gt;. Let&#x27;s see the output of &lt;code&gt;cat &#x2F;proc&#x2F;6026&#x2F;maps&lt;&#x2F;code&gt;. Here &lt;code&gt;6026&lt;&#x2F;code&gt; is the PID of a running process on my Debian:&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;00400000-00401000 r-xp 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;00600000-00601000 rw-p 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;01698000-016b9000 rw-p 00000000 00:00 0                  [heap]
&lt;&#x2F;span&gt;&lt;span&gt;7f747118a000-7f747132c000 r-xp 00000000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747132c000-7f747152b000 ---p 001a2000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152b000-7f747152f000 r--p 001a1000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152f000-7f7471531000 rw-p 001a5000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471531000-7f7471535000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471535000-7f7471555000 r-xp 00000000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471734000-7f7471737000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471752000-7f7471755000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471755000-7f7471756000 r--p 00020000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471756000-7f7471757000 rw-p 00021000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471757000-7f7471758000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d89b000-7ffc4d8bc000 rw-p 00000000 00:00 0          [stack]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99b000-7ffc4d99d000 r-xp 00000000 00:00 0          [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99d000-7ffc4d99f000 r--p 00000000 00:00 0          [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
The Heap segment and the Stack segment are labelled, easy. The addresses are displayed from the lowest `00400000`, to the highest `ffffffffff601000`. The first segment, `00400000-00401000`, is read-only and executable, so, this is the Code segment. We know that between the Code segment, and the Heap segment, there is the Data segment. If you don&#x27;t want to browse the `&#x2F;proc` directory, there is also the [pmap](http:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;pmap) command you can use to report the memory map of a process.
&lt;br&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Using the GNU debugger:&lt;&#x2F;strong&gt;
GDB, the &lt;em&gt;awesome&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GNU Project debugger&lt;&#x2F;a&gt;, allows you, among others things, to see what is going on &lt;code&gt;inside&lt;&#x2F;code&gt; a running process. For example, from the gdb prompt, you can type &lt;code&gt;info proc mappings&lt;&#x2F;code&gt; to see the current address mapping:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;process 8460
&lt;&#x2F;span&gt;&lt;span&gt;Mapped address spaces:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        Start Addr           End Addr     Size   Offset objfile
&lt;&#x2F;span&gt;&lt;span&gt;          0x400000           0x401000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x600000           0x601000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x601000           0x622000  0x21000      0x0 [heap]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7a31000     0x7ffff7bd3000 0x1a2000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7bd3000     0x7ffff7dd2000 0x1ff000 0x1a2000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd2000     0x7ffff7dd6000   0x4000 0x1a1000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd6000     0x7ffff7dd8000   0x2000 0x1a5000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd8000     0x7ffff7ddc000   0x4000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ddc000     0x7ffff7dfc000  0x20000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7fd7000     0x7ffff7fda000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff5000     0x7ffff7ff8000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff8000     0x7ffff7ffa000   0x2000      0x0 [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffa000     0x7ffff7ffc000   0x2000      0x0 [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffc000     0x7ffff7ffd000   0x1000  0x20000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffd000     0x7ffff7ffe000   0x1000  0x21000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffe000     0x7ffff7fff000   0x1000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffffffde000     0x7ffffffff000  0x21000      0x0 [stack]
&lt;&#x2F;span&gt;&lt;span&gt;0xffffffffff600000 0xffffffffff601000   0x1000      0x0 [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;And there is more to explore:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;(gdb) help info proc
&lt;&#x2F;span&gt;&lt;span&gt;Show &#x2F;proc process information about any running process.
&lt;&#x2F;span&gt;&lt;span&gt;Specify any process id, or use the program being debugged by default.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;List of info proc subcommands:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;info proc all -- List all available &#x2F;proc info
&lt;&#x2F;span&gt;&lt;span&gt;info proc cmdline -- List command line arguments of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc cwd -- List current working directory of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc exe -- List absolute filename for executable of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc mappings -- List of mapped memory regions
&lt;&#x2F;span&gt;&lt;span&gt;info proc stat -- List process info from &#x2F;proc&#x2F;PID&#x2F;stat
&lt;&#x2F;span&gt;&lt;span&gt;info proc status -- List process info from &#x2F;proc&#x2F;PID&#x2F;status
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;help info proc&amp;quot; followed by info proc subcommand name for full documentation.
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;apropos word&amp;quot; to search for commands related to &amp;quot;word&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;Command name abbreviations are allowed if unambiguous.
&lt;&#x2F;span&gt;&lt;span&gt;(gdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-create-a-process&quot;&gt;&lt;strong&gt;How to create a process?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;1.&lt;strong&gt;fork():&lt;&#x2F;strong&gt;
The fork() system call is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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 style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;((pid = fork()) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&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;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&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 style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&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:#608b4e;&quot;&gt;&#x2F;&#x2F;The parent executes the wait.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I really would like to write more on this topic. Maybe in another post, otherwise the article will be too long, &lt;em&gt;and I have the dishes to do&lt;&#x2F;em&gt;. At least, we&#x27;ve seen that there is an interesting amount of informations behind what is called a process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-hope-you-ve-learned-something-and-if-you-want-to-know-more&quot;&gt;I hope you&#x27;ve learned something, and if you want to know more:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;tlk&#x2F;kernel&#x2F;processes.html&quot;&gt;Processes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;filesystems&#x2F;proc.txt&quot;&gt;Proc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;Proc man pages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;446528&#x2F;&quot;&gt;The &quot;vsyscall&quot; and &quot;vDSO&quot; segments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;the-jealous-process&#x2F;&quot;&gt;The jealous process&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Network namespaces</title>
        <published>2016-07-08T00:00:00+00:00</published>
        <updated>2016-07-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/onn/"/>
        <id>https://nskm.xyz/posts/onn/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/onn/">&lt;p&gt;I use LXC containers mainly as isolated environments when I&#x27;m writing code, but also when I just want to try the last version of a package without being obliged to break something on my current configuration. This is the first part of a serie about LXC containers. In this post, I&#x27;ll share with you what I&#x27;ve learned about network namespaces. Everything here will be done under Debian Jessie, as root, I&#x27;m using Python 3.5 and I&#x27;ve pip installed pyroute2.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To keep the schemas as simple as possible, I won&#x27;t mention the interface &lt;code&gt;lo&lt;&#x2F;code&gt; actually available inside the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. The &lt;code&gt;root namespace&lt;&#x2F;code&gt; is the namespace available to you after a fresh boot of your Operating System. This is a small schema of my configuration showing you where we&#x27;ll start: &lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;root_ns.png&quot; alt=&quot;Root namespace&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What we will do:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#namespace-creation&quot;&gt;Create a namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#veth-pair-creation&quot;&gt;Create a virtual ethernet device pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#assign-on-side-to-namespace&quot;&gt;Assign one side of the veth pair to the namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#ip-addresses&quot;&gt;Assign IP addresses to each side of the veth pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#default-route-for-namespace&quot;&gt;Set the default route for our namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#attach-veth-to-bridge&quot;&gt;Attach the other side of the veth pair to a bridge&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;network-namespaces&quot;&gt;Network namespaces&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;namespace&lt;&#x2F;strong&gt; is a way of scoping a particular set of identifiers. You can use the same identifier multiple times in different namespaces. Most importantly, you can also restrict an identifier set visible to particular processes.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fact: the set of network interfaces and routing tables are shared across your entire Operating System. &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;580893&#x2F;&quot;&gt;Network namespaces&lt;&#x2F;a&gt; change that fundamental assumption. With network namespaces, you can have different and separate instances of network interfaces and routing tables that operate independent of each other. Let&#x27;s see how it works, using the Python package &lt;a href=&quot;https:&#x2F;&#x2F;pypi.python.org&#x2F;pypi&#x2F;pyroute2&quot;&gt;Pyroute2&lt;&#x2F;a&gt;:
&lt;a name=&quot;namespace-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pyroute2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;IPDB, IPRoute, NetNS, netns, NSPopen
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;subprocess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Popen, PIPE
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_namespace1 = IPDB(nl=NetNS(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; nsp = NSPopen(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;addr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;], stdout=PIPE)
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;nsp.communicate()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;print(l)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;1: lo: &amp;lt;LOOPBACK&amp;gt; mtu 65536 qdisc noop state DOWN group default &amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ve just created a network namespace named &lt;code&gt;namespace1&lt;&#x2F;code&gt;. The &lt;code&gt;ip addr&lt;&#x2F;code&gt; command launched inside the namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt; tells us that there is only one interface, &lt;code&gt;lo&lt;&#x2F;code&gt;.
&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;ns_created.png&quot; alt=&quot;Namespace1 created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, we need a way to link our newly created namespace, to the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To do that, virtual ethernet devices, &lt;code&gt;veth pair&lt;&#x2F;code&gt;, need to be created and configured. A &lt;code&gt;veth pair&lt;&#x2F;code&gt; works like a patch cable, connecting two sides. It consists of two virtual interfaces, one of them is assigned to the root network namespace, while the other lives within the network namespace, &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;veth-pair-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root = IPDB() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# root namespace
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root.create(ifname=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, kind=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, peer=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).commit()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ca:a0:d7:39:57:22&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_created.png&quot; alt=&quot;Veth pair device created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Veth pair device created. Both sides of the veth pair device are actually in the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To link the &lt;code&gt;root namespace&lt;&#x2F;code&gt; to our newly created namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt;, one side of the veth pair device, the peer, should be assigned to &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;assign-on-side-to-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;v:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;v.net_ns_fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_peer_moved.png&quot; alt=&quot;Veth peer moved&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s give IP addresses to all of our interfaces, and set everybody up:
&lt;a name=&quot;ip-addresses&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.v01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.36&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;f2:2d:aa:9d:16:da&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.37&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;26:29:f4:06:8a:ea&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.lo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;i:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;i.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;772&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65536&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point, we can open a shell and directly check the configuration for &lt;code&gt;v01&lt;&#x2F;code&gt; interface:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show v01
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;6: v01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether f2:2d:aa:9d:16:da brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.36&#x2F;24 scope global v01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::f02d:aaff:fe9d:16da&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We can also, still from the shell, check the available interfaces inside &lt;code&gt;namespace1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip addr show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
&lt;&#x2F;span&gt;&lt;span&gt;    inet 127.0.0.1&#x2F;8 scope host lo
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 ::1&#x2F;128 scope host
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;5: vp01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 26:29:f4:06:8a:ea brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.37&#x2F;24 scope global vpeer01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::2429:f4ff:fe06:8aea&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;A system uses its routing table to determine which network interface to use when sending packets to remote systems. Let&#x27;s make all traffic leaving &lt;code&gt;namespace1&lt;&#x2F;code&gt; to go through &lt;code&gt;v01&lt;&#x2F;code&gt;:
&lt;a name=&quot;default-route-for-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip route add default via 192.168.1.36
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;default-route-added.png&quot; alt=&quot;Default route added&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I told you I often use LXC containers when I&#x27;m working. For that reason, I always have a bridge configured and up. Then, all the containers are connected to the internet, via the bridge, as &lt;code&gt;ports&lt;&#x2F;code&gt;. Let me show you:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show br0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;4: br0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 3c:97:0e:65:c0:27 brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.34&#x2F;24 brd 192.168.1.255 scope global br0
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::3e97:eff:fe65:c027&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;code&gt;br0&lt;&#x2F;code&gt; interface is the interface I use for going outside. In fact, &lt;code&gt;br0&lt;&#x2F;code&gt; is a bridge. &lt;code&gt;eth0&lt;&#x2F;code&gt; and &lt;code&gt;vethLMRON&lt;&#x2F;code&gt; are interfaces, &lt;code&gt;ports&lt;&#x2F;code&gt;, attached to that &lt;a href=&quot;http:&#x2F;&#x2F;www.linuxfoundation.org&#x2F;collaborate&#x2F;workgroups&#x2F;networking&#x2F;bridge&quot;&gt;bridge&lt;&#x2F;a&gt;. &lt;code&gt;v01&lt;&#x2F;code&gt; should be attached to the &lt;code&gt;br0&lt;&#x2F;code&gt; bridge, otherwise, &lt;code&gt;v01&lt;&#x2F;code&gt; won&#x27;t be able to send packets to the outside world:
&lt;a name=&quot;attach-veth-to-bridge&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl addif br0 v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;                                                        v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
![Veth pair device added to bridge]({filename}&#x2F;images&#x2F;ns.png)
&lt;br&gt;&lt;br&gt;
If everything went fine, you should be able to ping an external host from `namespace1`:
```
kintanu:~# ip netns exec namespace1 ping 8.8.8.8
```
```
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 192.168.1.34: icmp_seq=1 Redirect Host(New nexthop: 192.168.1.1)
64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=104 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=54 time=104 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min&#x2F;avg&#x2F;max&#x2F;mdev = 104.190&#x2F;104.859&#x2F;105.375&#x2F;0.595 ms
kintanu:~#
```
&lt;br&gt;
&lt;p&gt;We&#x27;ve just seen how to create a network namespace, and link that network namespace to the outside world. When playing with LXC containers, you will also heard about &lt;code&gt;control groups&lt;&#x2F;code&gt;, a kernel mechanism that will allow you to allocate resources among user-defined groups of tasks (processes) running on a system. That will be the topic of the next chapter.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;All the diagrams were made using [Asciiflow](http:&#x2F;&#x2F;asciiflow.com&#x2F;)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introduction</title>
        <published>2015-07-24T00:00:00+00:00</published>
        <updated>2015-07-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/intro/"/>
        <id>https://nskm.xyz/posts/intro/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/intro/">&lt;p&gt;Hello, I&#x27;m Patrick, born and raised in central &lt;a href=&quot;#&quot;&gt;Africa&lt;&#x2F;a&gt;, currently based in West Africa, &lt;a href=&quot;#&quot;&gt;Dakar Senegal&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I am an experienced software engineer, passionate about &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;. I have a strong background in developing backend solutions. With almost 10 years of hands-on experience in the field, I have successfully contributed to &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt; and I have successfully developed and deployed &lt;a href=&quot;#&quot;&gt;numerous&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;software&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;projects&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;across&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;various&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;industries&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My expertise lies in &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Python programming&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;databases&lt;&#x2F;a&gt;; enabling me to tackle complex challenges and deliver high-quality, scalable software solutions. I thrive in dynamic and collaborative environments, working closely with cross-functional teams to understand requirements, design architectures, and implement robust solutions.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout my career, I have demonstrated a proven track record of delivering projects on time and within budget, while ensuring adherence to best practices and industry standards. I am adept at analyzing existing systems, identifying areas for improvement, and implementing enhancements that optimize performance and user experience.&lt;&#x2F;p&gt;
&lt;p&gt;Over the course of my professional journey, I have had the privilege of &lt;a href=&quot;#&quot;&gt;working as a programming instructor&lt;&#x2F;a&gt; for diverse groups of learners, ranging from beginners to experienced professionals. My &lt;a href=&quot;#&quot;&gt;teaching&lt;&#x2F;a&gt; approach is centered around creating an engaging and supportive &lt;a href=&quot;#&quot;&gt;learning environment&lt;&#x2F;a&gt;, where students can grasp complex concepts with ease and apply them effectively.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond technical skills, I am a team player, strong communicator and effective problem solver. I excel at sharing knowledge, at translating complex technical concepts into clear &amp;amp; non-technical language, fostering effective communication between stakeholders, clients, and development teams.&lt;&#x2F;p&gt;
&lt;p&gt;I am constantly exploring emerging technologies and &lt;a href=&quot;#&quot;&gt;staying up-to-date&lt;&#x2F;a&gt; with industry trends, as I believe in continuous learning and professional growth. I am eager to leverage my skills and expertise to contribute to a dynamic organization, driving innovation and delivering exceptional software solutions.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
