main
  1<!DOCTYPE html>
  2<html lang="en">
  3 <head>
  4  <meta name="viewport" content="width=device-width, initial-scale=1">
  5  <meta charset="utf-8">
  6  <meta name="viewport" content="width=device-width, initial-scale=1">
  7  <title>
  8   TIL — Today I Learned
  9  </title>
 10  <meta name="author" content="Vincent Demeester">
 11  <meta name="generator" content="Org Mode">
 12  <script src="/flux.js" defer=""></script>
 13  <link rel="stylesheet" href="/style.css" type="text/css">
 14 </head>
 15 <body>
 16  <div class="site-controls">
 17   <button class="theme-toggle" id="theme-toggle" title="Toggle dark/light mode">☀️</button>
 18  </div>
 19  <article id="content" class="content">
 20   <header>
 21    <h1 class="title">
 22     TIL — Today I Learned
 23    </h1>
 24   </header>
 25   <p>
 26    Short things I learned, discovered, or found interesting.
 27   </p>
 28   <section id="outline-container-github-is-a-cve-numbering-authority" class="outline-2">
 29    <h2 id="github-is-a-cve-numbering-authority">
 30     <a href="#github-is-a-cve-numbering-authority" class="anchor">§</a>GitHub is a CVE Numbering Authority<span class="tags"><a href="/flux/tags/github.html" class="tag">github</a><a href="/flux/tags/security.html" class="tag">security</a><a href="/flux/tags/opensource.html" class="tag">opensource</a></span>
 31    </h2>
 32    <div id="text-github-is-a-cve-numbering-authority" class="outline-text-2">
 33     <p>
 34      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-03-12">2026-03-12</time></a></span>
 35     </p>
 36     <p>
 37      GitHub can assign CVE IDs for any GitHub-hosted project. Most OSS projects don't need to
 38become their own CNA.
 39     </p>
 40     <p>
 41      The full flow stays within GitHub:
 42     </p>
 43     <ol class="org-ol">
 44      <li>
 45       Someone submits a Private Vulnerability Report (PVR)
 46      </li>
 47      <li>
 48       Accepting it creates a draft security advisory <i>you own</i>
 49      </li>
 50      <li>
 51       Create a private fork from the advisory for the fix
 52      </li>
 53      <li>
 54       Merge + publish is atomic: GHSA entry, CVE to MITRE/NVD, Dependabot alerts — all at once
 55      </li>
 56     </ol>
 57     <div class="callout callout-note" id="org7f16d57">
 58      <div class="callout-title">
 59       Note
 60      </div>
 61      <p>
 62       Private forks from advisories do <i>not</i> run GitHub Actions. Test locally or use a separate CI environment.
 63      </p>
 64     </div>
 65     <div class="callout callout-tip" id="org99c01cb">
 66      <div class="callout-title">
 67       Tip
 68      </div>
 69      <p>
 70       Request the CVE early (it stays "reserved"), develop the fix privately, then go public all at once: merge → publish advisory → tag release → announce.
 71      </p>
 72     </div>
 73    </div>
 74   </section>
 75   <section id="outline-container-fail2ban-push-notifications-self-dos" class="outline-2">
 76    <h2 id="fail2ban-push-notifications-self-dos">
 77     <a href="#fail2ban-push-notifications-self-dos" class="anchor">§</a>Fail2ban + push notifications = self-DoS<span class="tags"><a href="/flux/tags/homelab.html" class="tag">homelab</a><a href="/flux/tags/fail2ban.html" class="tag">fail2ban</a><a href="/flux/tags/nixos.html" class="tag">nixos</a></span>
 78    </h2>
 79    <div id="text-fail2ban-push-notifications-self-dos" class="outline-text-2">
 80     <p>
 81      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-03-02">2026-03-02</time></a></span>
 82     </p>
 83     <p>
 84      Push notification services (ntfy, Gotify) behind a reverse proxy with fail2ban create a
 85self-DoS loop:
 86     </p>
 87     <ol class="org-ol">
 88      <li>
 89       Persistent subscribers maintain long-lived connections
 90      </li>
 91      <li>
 92       Any disruption (Caddy reload, auth blip) triggers reconnection bursts
 93      </li>
 94      <li>
 95       Fail2ban sees the burst → bans your IP
 96      </li>
 97      <li>
 98       Auto-unban → instant re-ban (subscriber retries immediately)
 99      </li>
100      <li>
101       <code>bantime-increment</code> makes each cycle worse
102      </li>
103     </ol>
104     <p>
105      The fix: exclude the notification service from fail2ban entirely:
106     </p>
107     <div class="org-src-container">
108      <pre class="src src-ini"><code># In caddy-auth filter
109ignoreregex = ^.*"host":"ntfy\.sbr\.pm".*$
110</code></pre>
111     </div>
112     <div class="callout callout-warning" id="org7925b9e">
113      <div class="callout-title">
114       Warning
115      </div>
116      <p>
117       <code>ignoreIP</code> doesn't help if your IP changes (travel, mobile). The service itself must be excluded from the filter.
118      </p>
119     </div>
120    </div>
121   </section>
122   <section id="outline-container-usb-autosuspend-can-cascade-across-shared-xhci-controllers" class="outline-2">
123    <h2 id="usb-autosuspend-can-cascade-across-shared-xhci-controllers">
124     <a href="#usb-autosuspend-can-cascade-across-shared-xhci-controllers" class="anchor">§</a>USB autosuspend can cascade across shared xHCI controllers<span class="tags"><a href="/flux/tags/linux.html" class="tag">linux</a><a href="/flux/tags/hardware.html" class="tag">hardware</a><a href="/flux/tags/nixos.html" class="tag">nixos</a></span>
125    </h2>
126    <div id="text-usb-autosuspend-can-cascade-across-shared-xhci-controllers" class="outline-text-2">
127     <p>
128      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-02-27">2026-02-27</time></a></span>
129     </p>
130     <p>
131      Intermittent network drops on my laptop's USB ethernet adapter (Realtek r8152) turned out
132to be caused by a <b>webcam</b> (Logitech C920) on the same USB controller. USB autosuspend on
133the webcam triggered controller resets that cascaded to the ethernet adapter.
134     </p>
135     <p>
136      Devices on different logical USB buses can still share a physical xHCI controller.
137     </p>
138     <p>
139      Fix via udev rule in NixOS:
140     </p>
141     <div class="org-src-container">
142      <pre class="src src-nix"><code><span class="org-nix-attribute">services.udev.extraRules</span> = <span class="org-string">''
143  ACTION=="add", SUBSYSTEM=="usb", \
144    ATTR{idVendor}=="046d", ATTR{idProduct}=="082d", \
145    ATTR{power/control}="on"
146''</span>;
147</code></pre>
148     </div>
149     <div class="callout callout-tip" id="org7f6f53b">
150      <div class="callout-title">
151       Tip
152      </div>
153      <p>
154       When debugging USB issues, check <code>dmesg</code> for <code>xhci_hcd</code> reset messages. The culprit device may be on a completely different logical bus than the affected one.
155      </p>
156     </div>
157    </div>
158   </section>
159   <section id="outline-container-remote-nixos-install-don-t-bind-mount-over-nix-store" class="outline-2">
160    <h2 id="remote-nixos-install-don-t-bind-mount-over-nix-store">
161     <a href="#remote-nixos-install-don-t-bind-mount-over-nix-store" class="anchor">§</a>Remote NixOS install: don't bind-mount over <code>/nix/store</code><span class="tags"><a href="/flux/tags/nixos.html" class="tag">nixos</a><a href="/flux/tags/disko.html" class="tag">disko</a></span>
162    </h2>
163    <div id="text-remote-nixos-install-don-t-bind-mount-over-nix-store" class="outline-text-2">
164     <p>
165      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-02-12">2026-02-12</time></a></span>
166     </p>
167     <p>
168      When installing NixOS from a live USB, <code>/nix/store</code> is an overlayfs with a tmpfs upper
169layer (RAM-backed). If the closure is too large, you might be tempted to bind-mount the
170target disk's store over <code>/nix/store</code>.
171     </p>
172     <p>
173      <b>Don't.</b> It hides all system binaries and breaks the installer.
174     </p>
175     <p>
176      Instead, resize the tmpfs:
177     </p>
178     <div class="org-src-container">
179      <pre class="src src-shell"><code>mount -o remount,<span class="org-variable-name">size</span>=28G /nix/.rw-store
180</code></pre>
181     </div>
182     <p>
183      Or better: build the closure on a remote machine and <code>nix copy</code> it over.
184     </p>
185     <div class="callout callout-note" id="orgde0f8b8">
186      <div class="callout-title">
187       Note
188      </div>
189      <p>
190       The live USB's <code>/nix/store</code> has a read-only squashfs lower layer (<code>.ro-store</code>) and a tmpfs upper layer (<code>.rw-store</code>). Default tmpfs is ~50% of RAM.
191      </p>
192     </div>
193    </div>
194   </section>
195   <section id="outline-container-paperless-let-it-auto-detect-don-t-optimize" class="outline-2">
196    <h2 id="paperless-let-it-auto-detect-don-t-optimize">
197     <a href="#paperless-let-it-auto-detect-don-t-optimize" class="anchor">§</a>Paperless: let it auto-detect, don't "optimize"<span class="tags"><a href="/flux/tags/homelab.html" class="tag">homelab</a><a href="/flux/tags/paperless.html" class="tag">paperless</a></span>
198    </h2>
199    <div id="text-paperless-let-it-auto-detect-don-t-optimize" class="outline-text-2">
200     <p>
201      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-02-09">2026-02-09</time></a></span>
202     </p>
203     <p>
204      When migrating paperless-ngx to a more powerful machine (RK3588), I initially set
205restrictive "ARM64 optimizations" — fewer workers, single threads, OCR first page only.
206     </p>
207     <p>
208      This was wrong. The RK3588 has 8 cores and 32GB RAM. The defaults are <i>already optimized</i>:
209paperless auto-detects CPU count and sets workers/threads accordingly.
210     </p>
211     <div class="org-src-container">
212      <pre class="src src-nix"><code><span class="org-comment-delimiter"># </span><span class="org-comment">DON'T do this on capable hardware:
213</span><span class="org-nix-attribute">PAPERLESS_TASK_WORKERS</span> = <span class="org-string">"2"</span>;        <span class="org-comment"># Limiting!
214</span><span class="org-nix-attribute">PAPERLESS_THREADS_PER_WORKER</span> = <span class="org-string">"1"</span>;  <span class="org-comment"># Limiting!
215</span><span class="org-nix-attribute">PAPERLESS_OCR_PAGES</span> = <span class="org-string">"1"</span>;           <span class="org-comment"># Incomplete!
216</span>
217<span class="org-comment-delimiter"># </span><span class="org-comment">DO this: just let paperless figure it out
218</span><span class="org-comment-delimiter"># </span><span class="org-comment">(remove all worker/thread overrides)</span>
219</code></pre>
220     </div>
221    </div>
222   </section>
223   <section id="outline-container-always-use-explicit-refspecs-for-git-push" class="outline-2">
224    <h2 id="always-use-explicit-refspecs-for-git-push">
225     <a href="#always-use-explicit-refspecs-for-git-push" class="anchor">§</a>Always use explicit refspecs for <code>git push</code><span class="tags"><a href="/flux/tags/git.html" class="tag">git</a><a href="/flux/tags/safety.html" class="tag">safety</a></span>
226    </h2>
227    <div id="text-always-use-explicit-refspecs-for-git-push" class="outline-text-2">
228     <p>
229      <span class="timestamp-wrapper"><a class="timestamp-link" href="/flux/2026.html"><time class="timestamp" datetime="2026-01-28">2026-01-28</time></a></span>
230     </p>
231     <p>
232      Bare <code>git push</code> without a refspec uses the branch's tracking configuration, which
233can silently push to the wrong branch — especially with worktrees or branches created
234from unexpected bases.
235     </p>
236     <p>
237      Always use:
238     </p>
239     <div class="org-src-container">
240      <pre class="src src-shell"><code>git push origin branch:branch
241</code></pre>
242     </div>
243     <p>
244      Never:
245     </p>
246     <div class="org-src-container">
247      <pre class="src src-shell"><code>git push  <span class="org-comment-delimiter"># </span><span class="org-comment">← dangerous</span>
248</code></pre>
249     </div>
250     <div class="callout callout-warning" id="org79c4fb7">
251      <div class="callout-title">
252       Warning
253      </div>
254      <p>
255       With worktrees, tracking configs can diverge between the main repo and worktree checkouts. A bare <code>git push</code> in a worktree might push to a completely different remote branch than you expect.
256      </p>
257     </div>
258    </div>
259   </section>
260  </article>
261  <time hidden="" datetime="2026-03-12"></time>
262 </body>
263</html>