<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chukwudum Agbasi</title>
    <description>The latest articles on DEV Community by Chukwudum Agbasi (@chukwudum_agbasi_d9e1cb29).</description>
    <link>https://dev.to/chukwudum_agbasi_d9e1cb29</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1796162%2Fd94f6f55-21e6-4131-811f-41668debfebb.jpeg</url>
      <title>DEV Community: Chukwudum Agbasi</title>
      <link>https://dev.to/chukwudum_agbasi_d9e1cb29</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chukwudum_agbasi_d9e1cb29"/>
    <language>en</language>
    <item>
      <title>DevOps Magic: Building a Self-Healing, Policy-Driven Deployment Engine</title>
      <dc:creator>Chukwudum Agbasi</dc:creator>
      <pubDate>Wed, 06 May 2026 21:11:36 +0000</pubDate>
      <link>https://dev.to/chukwudum_agbasi_d9e1cb29/devops-magic-building-a-self-healing-policy-driven-deployment-engine-3bc3</link>
      <guid>https://dev.to/chukwudum_agbasi_d9e1cb29/devops-magic-building-a-self-healing-policy-driven-deployment-engine-3bc3</guid>
      <description>&lt;p&gt;Modern DevOps isn't just about moving code; it’s about creating a "clinical" environment where infrastructure is predictable, self-validating, and resilient. For my recent project, SwiftDeploy, I built a CLI tool that doesn't just deploy containers—it diagnoses the host environment and enforces strict policy guardrails before a single container is birthed.&lt;/p&gt;

&lt;p&gt;Here is the technical deep dive into how I built a self-generating infrastructure stack with Open Policy Agent (OPA) integration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Design: Infrastructure as Logic&lt;/strong&gt;
Most CI/CD pipelines rely on static YAML files. SwiftDeploy takes a different approach: it treats infrastructure as a dynamic output of a manifest.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;br&gt;
The tool uses a manifest.yaml as the "source of truth." When you run ./swiftdeploy init, the script acts as a compiler:&lt;/p&gt;

&lt;p&gt;It parses service definitions (images, ports, environment variables) using yq.&lt;/p&gt;

&lt;p&gt;It injects these variables into .template files using envsubst.&lt;/p&gt;

&lt;p&gt;It generates a perfectly tailored docker-compose.yml and nginx.conf on the fly.&lt;/p&gt;

&lt;p&gt;By "writing" its own infrastructure files, SwiftDeploy eliminates configuration drift. If the manifest changes, the infrastructure regenerates to match, ensuring that what you see in your config is exactly what runs in your stack.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Guardrails: OPA and the "Pre-Flight" Check&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In a production environment, isolation isn't just a preference—it's a requirement. I integrated Open Policy Agent (OPA) to act as the "Medical Board" for my deployments.&lt;/p&gt;

&lt;p&gt;The Logic of Isolation:&lt;br&gt;
We use OPA to evaluate two distinct policy sets:&lt;/p&gt;

&lt;p&gt;Infrastructure Policy: Checks host health (CPU load, Disk space, Memory). If the host is "feverish" (e.g., CPU load &amp;gt; 2.0), OPA blocks the deployment to prevent a cascading failure.&lt;/p&gt;

&lt;p&gt;Canary Safety: During promotion from Stable to Canary, OPA analyzes live metrics. If the error rate exceeds 5%, the promotion is "quarantined."&lt;/p&gt;

&lt;p&gt;Why Rego?&lt;br&gt;
Using Rego (OPA's query language) allows us to write policies like this:&lt;/p&gt;

&lt;p&gt;Code snippet&lt;br&gt;
package infrastructure&lt;br&gt;
default allow = false&lt;br&gt;
allow {&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input.cpu_load &amp;lt; data.infrastructure.max_cpu_load
input.disk_free_gb &amp;gt; data.infrastructure.min_disk_free_gb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;br&gt;
This decouples "how to deploy" from "when it is safe to deploy."`&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;*&lt;em&gt;The Chaos: Watching the System Break
*&lt;/em&gt;
A deployment tool is only as good as its visibility. To test SwiftDeploy, I intentionally injected a "Slow State" and an "Error State" into the Python backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Failure Scenario:&lt;/strong&gt;&lt;br&gt;
I updated the app to return 500 Internal Server Error on 20% of traffic. I then monitored the stack using the built-in status view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Status View Capture:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Plaintext&lt;br&gt;
  UPTIME:  124.5s&lt;br&gt;
  REQUESTS: 50 total&lt;/p&gt;

&lt;p&gt;POLICY COMPLIANCE&lt;/p&gt;

&lt;p&gt;metrics: error_rate=20.0% p99_latency=450ms&lt;br&gt;
  checking canary_safety policy...&lt;br&gt;
  BLOCK canary_safety: error_rate 20.0% exceeds maximum 5%&lt;br&gt;
Because the status loop was feeding real-time metrics into OPA, the Promote command was automatically locked. The system "knew" it was sick before I did.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lessons Learne&lt;/strong&gt;
Building this journey from Stage 2 through 4B taught me three critical lessons:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Environment Parity is Hard: Moving from Linux-based logic to a Windows/Git Bash environment revealed how much we rely on specific binaries like free or /proc. Python is the ultimate "bridge" for cross-platform hardware stats.&lt;/p&gt;

&lt;p&gt;Fail-Safe is the Only Way: My policy engine was designed to "Block if OPA is unavailable." This saved me multiple times when the OPA container hadn't fully mapped its ports to the host.&lt;/p&gt;

&lt;p&gt;Observability is Part of Deployment: A deployment doesn't end when the container is Up. It ends when the metrics prove the container is healthy.&lt;/p&gt;

&lt;p&gt;Replicate the Work&lt;/p&gt;

&lt;p&gt;If you want to build your own policy-driven CLI:&lt;/p&gt;

&lt;p&gt;Tooling: Bash, Docker, OPA, and yq.&lt;/p&gt;

&lt;p&gt;Step 1: Create templates for your YAML.&lt;/p&gt;

&lt;p&gt;Step 2: Use curl to POST your system stats to OPA’s Data API.&lt;/p&gt;

&lt;p&gt;Step 3: Only trigger docker compose up if the API returns {"result": true}.&lt;/p&gt;

&lt;p&gt;Infrastructure should be smart enough to say "No" to a bad deployment. SwiftDeploy makes sure it does.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>cicd</category>
      <category>devops</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How I Built a Real-Time DDoS Detection Engine from Scratch (No Fail2Ban)</title>
      <dc:creator>Chukwudum Agbasi</dc:creator>
      <pubDate>Wed, 29 Apr 2026 12:16:39 +0000</pubDate>
      <link>https://dev.to/chukwudum_agbasi_d9e1cb29/how-i-built-a-real-time-ddos-detection-engine-from-scratch-no-fail2ban-5fl4</link>
      <guid>https://dev.to/chukwudum_agbasi_d9e1cb29/how-i-built-a-real-time-ddos-detection-engine-from-scratch-no-fail2ban-5fl4</guid>
      <description>&lt;p&gt;Have you ever wondered how a website "knows" it's being attacked and automatically pulls the plug on the attacker?&lt;/p&gt;

&lt;p&gt;I recently built an anomaly detection engine from scratch. It’s a live system that watches incoming traffic, learns what "normal" looks like, and automatically blocks suspicious IPs using Linux firewall rules.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through how it works in plain English. No prior security experience required. Lets get into it....&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;🛠 What the Project Does (and Why It Matters)&lt;/strong&gt;&lt;br&gt;
Imagine a popular restaurant. Usually, customers walk in, order, and eat. But what if 500 people suddenly rushed in at once, stood at the counter, and ordered nothing? The staff would be so overwhelmed they couldn't serve real customers.&lt;/p&gt;

&lt;p&gt;That is a DDoS (Distributed Denial of Service) attack.&lt;/p&gt;

&lt;p&gt;The challenge is that you can't just say "block anyone who sends more than 100 requests." A busy server might normally get 200, while a quiet one gets 5. A hardcoded limit would either block real fans or miss real attackers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: Build a system that learns your server's "rhythm" and flags anything that breaks it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bird's Eye View&lt;/strong&gt;&lt;br&gt;
Here is how the data flows:&lt;/p&gt;

&lt;p&gt;Internet Traffic hits the Nginx server.&lt;/p&gt;

&lt;p&gt;Nginx writes logs to a shared folder.&lt;/p&gt;

&lt;p&gt;My Detector Daemon (Python) reads those logs in real-time.&lt;/p&gt;

&lt;p&gt;It calculates a Baseline, detects Anomalies, and executes a Ban.&lt;/p&gt;

&lt;p&gt;It sends a Slack Alert and updates a Live Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Sliding Window: "Forgetting" the Past&lt;/strong&gt;&lt;br&gt;
To know how busy the server is right now, you can't look at all traffic since the beginning of time. You need a Sliding Window.&lt;/p&gt;

&lt;p&gt;Think of a sliding window like a 60-second video clip. Every second, the "window" moves forward. It forgets the oldest second and adds the newest one.&lt;/p&gt;

&lt;p&gt;In Python, I used a deque (&lt;strong&gt;a double-ended queue&lt;/strong&gt;) to handle this efficiently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="c1"&gt;# A list of (timestamp, is_error)
&lt;/span&gt;&lt;span class="n"&gt;ip_window&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;record_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# EVICT OLD: Remove anything older than 60 seconds
&lt;/span&gt;    &lt;span class="n"&gt;cutoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; 
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popleft&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is the beauty&lt;/strong&gt;: It uses almost no memory. Old data literally "falls off" the conveyor belt, leaving you with a fresh count of exactly what happened in the last minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Baseline: Learning What’s "Normal"&lt;/strong&gt;&lt;br&gt;
The sliding window tells us the current speed, but the Baseline tells us the "Speed Limit."&lt;/p&gt;

&lt;p&gt;The engine keeps a 30-minute history of traffic. Every minute, it calculates the Average (Mean) and the Standard Deviation (how much the traffic usually fluctuates).&lt;/p&gt;

&lt;p&gt;Quiet Morning: Average might be 2 requests/sec.&lt;/p&gt;

&lt;p&gt;Busy Afternoon: Average might climb to 40 requests/sec.&lt;/p&gt;

&lt;p&gt;Because the baseline is always recalculating, the system adapts. If your site gets a permanent boost in popularity, the "security guard" doesn't panic—it just learns the new normal. It is literally the darwin of this security architecture&lt;/p&gt;

&lt;p&gt;
  Click here to see why this is the "Darwin" of Security
  &lt;br&gt;
Just like the X-Men's Darwin, who grows gills when submerged in water, this baseline evolves based on the "pressure" of the traffic. If the traffic stays high, the baseline grows to accommodate it. If it stays low, it tightens up. It adapts so it never has to panic.&lt;br&gt;


&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The Math: Z-Scores and Multipliers&lt;/strong&gt;&lt;br&gt;
How do we actually trigger a ban? We use two "sniff tests":&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test A&lt;/strong&gt;: The Z-Score (The Statistical Freak-out)&lt;br&gt;
A Z-score measures how many "standard deviations" a value is from the average.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Z-Score of 1&lt;/strong&gt;: Totally normal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Z-Score of 3+&lt;/strong&gt;: This is mathematically "weird." In a normal world, this happens less than 0.2% of the time. Verdict: Blocked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test B&lt;/strong&gt;: The Multiplier (The "Common Sense" Rule)&lt;br&gt;
If the baseline is very quiet (e.g., 0.1 requests/sec), the Z-score can get jumpy. So we add a backup: Is the current rate 5x higher than the average? If yes: Verdict: Blocked&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The Hammer: iptables&lt;/strong&gt;&lt;br&gt;
Once we catch a "bad actor," we have to stop them. We use iptables, the Linux kernel's built-in firewall.&lt;/p&gt;

&lt;p&gt;When we detect an anomaly, the Python script runs a system command to &lt;strong&gt;DROP&lt;/strong&gt; all traffic from that specific IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# What the code tells the Linux Kernel:&lt;/span&gt;
iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-s&lt;/span&gt; 1.2.3.4 &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is incredibly powerful. The traffic is blocked at the "front door" (the kernel level). It never even reaches the web server, saving your CPU and RAM for real users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Backoff" Schedule&lt;/strong&gt;&lt;br&gt;
We aren't monsters! Sometimes a user just refreshes too fast. We use a "Three Strikes" system:&lt;/p&gt;

&lt;p&gt;1st Offense: 10-minute ban.&lt;/p&gt;

&lt;p&gt;2nd Offense: 30-minute ban.&lt;/p&gt;

&lt;p&gt;3rd Offense: 2-hour ban.&lt;/p&gt;

&lt;p&gt;4th Offense: Permanent block.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because if an IP hasn't learned by now, it’s not a visitor, its a threat&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;📢 Real-Time Alerts&lt;/strong&gt;&lt;br&gt;
Security is only good if you know it's working. Every time a ban happens, the system shoots a message to Slack:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚨 IP BANNED&lt;/strong&gt;&lt;br&gt;
IP: 1.2.3.4&lt;br&gt;
Reason: Z-Score 4.5 (Way above normal!)&lt;br&gt;
Rate: 50 req/s (Baseline: 5 req/s)&lt;br&gt;
Duration: 600s&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Wrapping Up&lt;/strong&gt;&lt;br&gt;
By building this from scratch with no pre-made tools like Fail2Ban I learned that security isn't just about "locking doors." It's about observation, statistics, and automation.&lt;/p&gt;

&lt;p&gt;The beauty of this engine is that it doesn't care if you're a tiny blog or a massive store; it watches your traffic, learns your baseline, and protects you accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔗 Resources&lt;/strong&gt;&lt;br&gt;
Source Code: [&lt;a href="https://github.com/Valescaray/hng-stage-3" rel="noopener noreferrer"&gt;https://github.com/Valescaray/hng-stage-3&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Live Dashboard: [&lt;a href="https://monitor.oppsdev.xyz" rel="noopener noreferrer"&gt;https://monitor.oppsdev.xyz&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;What do you think? Would you trust an automated math equation to protect your server? Let me know in the comments!&lt;/p&gt;

&lt;h1&gt;
  
  
  devsecops #python #programming #security
&lt;/h1&gt;

</description>
      <category>beginners</category>
      <category>security</category>
      <category>showdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
