<?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>Forem: Zerlo.net</title>
    <description>The latest articles on Forem by Zerlo.net (@zerlo).</description>
    <link>https://forem.com/zerlo</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%2F3873649%2F1a15c026-91f0-4b38-85e4-d9f9c1e05357.png</url>
      <title>Forem: Zerlo.net</title>
      <link>https://forem.com/zerlo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zerlo"/>
    <language>en</language>
    <item>
      <title>I built a JSON/YAML/TOML toolkit after wasting too much time validating configs</title>
      <dc:creator>Zerlo.net</dc:creator>
      <pubDate>Sun, 12 Apr 2026 14:14:15 +0000</pubDate>
      <link>https://forem.com/zerlo/i-built-a-jsonyamltoml-toolkit-after-wasting-too-much-time-validating-configs-6d</link>
      <guid>https://forem.com/zerlo/i-built-a-jsonyamltoml-toolkit-after-wasting-too-much-time-validating-configs-6d</guid>
      <description>&lt;p&gt;Working with config files should be boring.&lt;/p&gt;

&lt;p&gt;That’s exactly the problem: it usually isn’t.&lt;/p&gt;

&lt;p&gt;I kept running into the same small annoyances over and over again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a broken comma in JSON&lt;/li&gt;
&lt;li&gt;YAML indentation issues&lt;/li&gt;
&lt;li&gt;converting between formats just to test something quickly&lt;/li&gt;
&lt;li&gt;opening three different tools for tasks that should take 20 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is difficult work. It’s just annoying work.&lt;br&gt;
And that kind of friction adds up fast when you deal with configs regularly.&lt;/p&gt;

&lt;p&gt;In my case, it happened often enough while working with API payloads, small web tools, AI-related settings, and general dev utilities that I got tired of constantly switching between validators, formatters, and converters.&lt;/p&gt;

&lt;p&gt;So I built a small browser-based &lt;a href="https://zerlo.net/json-toolkit" rel="noopener noreferrer"&gt;JSON Toolkit&lt;/a&gt; for my own workflow.&lt;/p&gt;

&lt;p&gt;The goal was not to build “yet another formatter”.&lt;br&gt;
The goal was to remove those tiny interruptions that break focus for no good reason.&lt;/p&gt;

&lt;p&gt;What I wanted in one place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;format JSON quickly&lt;/li&gt;
&lt;li&gt;validate it without extra clutter&lt;/li&gt;
&lt;li&gt;minify it when needed&lt;/li&gt;
&lt;li&gt;convert JSON ↔ YAML/TOML without weird surprises&lt;/li&gt;
&lt;li&gt;keep the whole thing fast and simple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A typical example is when I have some ugly JSON like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"toolkit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and I just want this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"toolkit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or when I want to quickly turn it into YAML for a config test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;toolkit&lt;/span&gt;
&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s not a hard problem.&lt;br&gt;
It’s just the kind of thing that wastes time in small, repetitive chunks.&lt;/p&gt;

&lt;p&gt;While building it, I tried to keep the tool focused:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no overloaded interface&lt;/li&gt;
&lt;li&gt;no unnecessary steps&lt;/li&gt;
&lt;li&gt;no “power user” nonsense for basic tasks&lt;/li&gt;
&lt;li&gt;just a practical utility that does the job cleanly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That was the main idea from the start:&lt;br&gt;
not a big platform, not a complicated parser playground — just something useful enough that I’d actually keep using it myself.&lt;/p&gt;

&lt;p&gt;That’s usually my best filter for small tools:&lt;br&gt;
if I don’t come back to it after building it, it probably wasn’t worth building.&lt;/p&gt;

&lt;p&gt;So far, this one stayed.&lt;/p&gt;

&lt;p&gt;You can try the &lt;a href="https://zerlo.net/json-toolkit" rel="noopener noreferrer"&gt;JSON Toolkit here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m curious how others handle this kind of workflow:&lt;br&gt;
do you prefer one small all-in-one tool, or separate tools for validation, formatting, and conversion?&lt;/p&gt;

</description>
      <category>json</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What To Do When Your Website Is Under a DDoS Attack</title>
      <dc:creator>Zerlo.net</dc:creator>
      <pubDate>Sat, 11 Apr 2026 15:53:03 +0000</pubDate>
      <link>https://forem.com/zerlo/what-to-do-when-your-website-is-under-a-ddos-attack-3g6</link>
      <guid>https://forem.com/zerlo/what-to-do-when-your-website-is-under-a-ddos-attack-3g6</guid>
      <description>&lt;p&gt;A little while ago, &lt;a href="https://zerlo.net/" rel="noopener noreferrer"&gt;Zerlo.net&lt;/a&gt; was hit by a DDoS attack.&lt;/p&gt;

&lt;p&gt;At first, I assumed it was just a technical issue. But after checking our traffic and infrastructure, it became clear that this was not normal user activity. In this post, I’ll show how we identified the attack, how Cloudflare helped reduce the impact, and what actions are worth taking when your website suddenly starts collapsing under artificial load.&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%2F8mlfdlh2rhcxhpiuzwzs.jpg" 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%2F8mlfdlh2rhcxhpiuzwzs.jpg" alt="DDoS attack banner" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a DDoS attack?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Distributed Denial of Service (DDoS)&lt;/strong&gt; attack tries to make a website or service unavailable by overwhelming it with traffic from many different sources at the same time.&lt;/p&gt;

&lt;p&gt;In practice, this often means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;huge spikes in requests&lt;/li&gt;
&lt;li&gt;abnormal load on the origin server&lt;/li&gt;
&lt;li&gt;suspicious user agents&lt;/li&gt;
&lt;li&gt;repeated hits on expensive endpoints like login pages, APIs, search, or forms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are different forms of DDoS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;network-level attacks&lt;/strong&gt; such as UDP or ICMP floods&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;application-layer attacks (Layer 7)&lt;/strong&gt; such as HTTP floods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer 7 attacks are especially annoying because they can look more like “normal” traffic at first glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you recognize it?
&lt;/h2&gt;

&lt;p&gt;A single metric is usually not enough.&lt;/p&gt;

&lt;p&gt;Typical warning signs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sharply rising server load without a corresponding rise in real users&lt;/li&gt;
&lt;li&gt;many requests hitting expensive endpoints&lt;/li&gt;
&lt;li&gt;strange or empty user agents&lt;/li&gt;
&lt;li&gt;unexpected request peaks from unfamiliar ASNs or regions&lt;/li&gt;
&lt;li&gt;high CPU or I/O load even though you didn’t deploy anything new&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the biggest clues in our case was this:&lt;/p&gt;

&lt;p&gt;our own counter tracks &lt;strong&gt;human interactions through JavaScript&lt;/strong&gt;, and those numbers were almost identical to the previous day — while the infrastructure load was massively higher.&lt;/p&gt;

&lt;p&gt;That mismatch is a huge red flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our first practical test
&lt;/h2&gt;

&lt;p&gt;The classic test was simple:&lt;/p&gt;

&lt;p&gt;run everything locally.&lt;/p&gt;

&lt;p&gt;If the application itself is broken, you usually see the problem locally as well.&lt;br&gt;&lt;br&gt;
In our case, local load was basically &lt;strong&gt;0%&lt;/strong&gt;, while the public system was struggling hard.&lt;/p&gt;

&lt;p&gt;That was the moment it became obvious that the pressure was external.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cloudflare showed us
&lt;/h2&gt;

&lt;p&gt;Once we checked Cloudflare, the pattern became much clearer.&lt;/p&gt;

&lt;p&gt;Useful places to look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security Events / Security Analytics&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traffic Analytics&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WAF activity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting and challenge data&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Cloudflare, you can break traffic down by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;path&lt;/li&gt;
&lt;li&gt;country&lt;/li&gt;
&lt;li&gt;ASN&lt;/li&gt;
&lt;li&gt;method&lt;/li&gt;
&lt;li&gt;user agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it much easier to distinguish real traffic from garbage.&lt;/p&gt;

&lt;p&gt;When we enabled &lt;strong&gt;Under Attack Mode&lt;/strong&gt;, the average server load dropped to around &lt;strong&gt;5%&lt;/strong&gt;. That was the clearest confirmation we needed.&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%2Fxoqspcujookrfxi1wcao.jpg" 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%2Fxoqspcujookrfxi1wcao.jpg" alt="Cloudflare statistics showing abnormal traffic spike" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Cloudflare is actually doing here
&lt;/h2&gt;

&lt;p&gt;This is the simple version:&lt;/p&gt;

&lt;p&gt;Cloudflare sits in front of your origin and can challenge suspicious traffic before it ever reaches your infrastructure.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bots have to solve extra work&lt;/li&gt;
&lt;li&gt;cheap flood traffic becomes more expensive&lt;/li&gt;
&lt;li&gt;real users usually pass with minimal friction&lt;/li&gt;
&lt;li&gt;your backend gets breathing room immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This does not “prevent DDoS forever”, but it buys time and drastically reduces the damage.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you do immediately?
&lt;/h2&gt;

&lt;p&gt;You can’t stop people on the internet from sending packets to your system.&lt;/p&gt;

&lt;p&gt;So the goal is not “prevent everything forever”.&lt;/p&gt;

&lt;p&gt;The real goal is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;reduce the impact enough so that real users can still use the site.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Short-term actions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;enable &lt;strong&gt;Under Attack Mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;challenge suspicious requests&lt;/li&gt;
&lt;li&gt;put &lt;strong&gt;rate limiting&lt;/strong&gt; on sensitive paths&lt;/li&gt;
&lt;li&gt;protect forms and login-like endpoints&lt;/li&gt;
&lt;li&gt;increase caching where possible&lt;/li&gt;
&lt;li&gt;monitor security analytics closely&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Good candidates for immediate protection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/api/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;form endpoints&lt;/li&gt;
&lt;li&gt;login pages&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;li&gt;mail handlers&lt;/li&gt;
&lt;li&gt;expensive POST requests&lt;/li&gt;
&lt;li&gt;dynamic pages with heavy backend processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What should you do long term?
&lt;/h2&gt;

&lt;p&gt;Short-term mitigation is not enough.&lt;/p&gt;

&lt;p&gt;After the incident, hardening should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;proper &lt;strong&gt;WAF rules&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Challenge&lt;/strong&gt; for suspicious traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt; per IP and per path&lt;/li&gt;
&lt;li&gt;caching public pages aggressively&lt;/li&gt;
&lt;li&gt;bypassing cache only where needed&lt;/li&gt;
&lt;li&gt;protecting forms with &lt;strong&gt;Turnstile&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;collecting and reviewing logs&lt;/li&gt;
&lt;li&gt;setting alerts for unusual spikes&lt;/li&gt;
&lt;li&gt;identifying “expensive” endpoints before the next attack&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A practical rule approach
&lt;/h2&gt;

&lt;p&gt;Here is a simple example of the type of logic that makes sense:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
txt
(len(http.user_agent) = 0
 or lower(http.user_agent) contains "python"
 or lower(http.user_agent) contains "curl"
 or lower(http.user_agent) contains "bot"
 or lower(http.user_agent) contains "crawler")
=&amp;gt; Action: Managed Challenge

(http.request.method eq "POST"
 or starts_with(http.request.uri.path, "/api/")
 or http.request.uri.path contains "/sendMail.php")
=&amp;gt; Action: Managed Challenge

# Rate Limiting example
(http.request.method eq "POST" and starts_with(http.request.uri.path, "/api/"))
Threshold: 10 requests in 10 seconds per IP
Action: Challenge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>cloudflarechallenge</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
