luis's blog

notas e relatos de campo

notas

sobre código, servidores, linux e o que mais der vontade de escrever.

arquivo

anatomy of a cryptomining incident: when a public postgresql ate our erp server

16/09/2026

anatomy of a cryptomining incident: when a public postgresql ate our erp server

an anonymized post-mortem: how an exposed database, a weak password and a busy container turned a small saas server into someone else's crypto farm and how we got our data back at 30 kb/s.

resurrecting a 2007 laptop as a headless alpine server

13/09/2026

resurrecting a 2007 laptop as a headless alpine server

a dead-battery Acer Aspire 5315, a minirootfs install, a QEMU dress rehearsal, zram swap and a clock stuck in 2001. it now runs containers around the clock.

building wired.rs - a hub with a CRT soul

25/08/2026

building wired.rs - a hub with a CRT soul

turning a list of links into a place. canvas networks, palette swaps with CSS variables, and an easter egg as a design-system test.

the mailto link that disappeared (thanks, CDN)

15/07/2026

the mailto link that disappeared (thanks, CDN)

Cloudflare rewrote my email into a span only JavaScript could decode. undoing it taught me to read my own HTML as a stranger.

offline-first is a data modeling problem

16/06/2026

offline-first is a data modeling problem

a trucking app taught me that sync is not a library toggle. it's a set of decisions about identity, conflicts and retries.

alchemy, secrecy and reproducible builds

02/06/2026

alchemy, secrecy and reproducible builds

alchemists wrote in symbols and lost their recipes. chemistry won by publishing methods. CI has been fighting this war for a decade.

the model isn't the bottleneck - retrieval is

19/05/2026

the model isn't the bottleneck - retrieval is

building a RAG chat over PDFs and spreadsheets taught me that answers are only as good as the chunks you feed the model.

Redis is not just a cache

28/04/2026

Redis is not just a cache

rate limits, locks and queues all fit in Redis - until you need delivery guarantees. knowing where the line is changed how I design services.

the nginx reload that failed silently

14/04/2026

the nginx reload that failed silently

systemctl reload said success, the site kept serving the old config, and nginx -t was happy. one line in the error log explained everything.

cathedrals and software that outlives you

07/04/2026

cathedrals and software that outlives you

Cologne Cathedral took 632 years. the masons who finished it never met the ones who started, and that is the whole lesson.

lying to a client, politely: building an OpenAI-compatible proxy

31/03/2026

lying to a client, politely: building an OpenAI-compatible proxy

zcode-opencode-provider exposes a local app-server as an OpenAI-shaped API. compatibility layers are translation problems, and the contract is the product.

yt-dlp extractors break every few weeks. plan for it.

17/03/2026

yt-dlp extractors break every few weeks. plan for it.

TikTok and Instagram stopped working on two of my tools on the same week. same cause, same fix, and a fallback.

never run the security scanner on the host

24/02/2026

never run the security scanner on the host

SmartSec runs Nmap and Nuclei inside rootless Podman containers, with pinned digests and minimized evidence. that constraint shaped the whole design.

rate limiting without ever storing an IP

10/02/2026

rate limiting without ever storing an IP

the AfroRetratos anonymous feed needed abuse protection without collecting personal data. HMACs and a bit of discipline did it.

Roman roads were an API

03/02/2026

Roman roads were an API

standardized surfaces, documented milestones, published deprecation. the cursus publicus is infrastructure design and we keep re-learning it.

clipboard sync and the loop that never ends

27/01/2026

clipboard sync and the loop that never ends

clipsync keeps the clipboard shared between Linux and Android. the hardest bug wasn't the network - it was two devices agreeing too much.

Cloudflare was serving my old JavaScript

13/01/2026

Cloudflare was serving my old JavaScript

the deploy was green, the HTML was new, the toggle didn't exist. CDNs cache URLs, not intentions.

Renaissance perspective was the first render engine

06/01/2026

Renaissance perspective was the first render engine

Brunelleschi painted a building, held up a mirror, and invented the camera transform. we just moved the math to a GPU.

two Docker daemons on the same machine (rootless vs rootful)

09/12/2025

two Docker daemons on the same machine (rootless vs rootful)

docker ps showed nothing, the container was clearly running, and the port was bound. I was talking to a different daemon.

the Greek roots of the words we use every day

27/11/2025

the Greek roots of the words we use every day

automation, cryptography, schema, system. four words from one language, and each one is a miniature spec.

the Docker container that was Created but never bound its port

16/11/2025

the Docker container that was Created but never bound its port

the container was healthy, the app was listening inside, and 127.0.0.1:3000 was empty. docker teaches a lesson about when port bindings are programmed.

deterministic colors - turning any string into a color that matches

05/11/2025

deterministic colors - turning any string into a color that matches

ChromaString makes a stable color out of any text. the interesting part is not the hash, it's making the result readable.

giving a deploy key a single job with SSH forced commands

21/10/2025

giving a deploy key a single job with SSH forced commands

my CI key had a full shell on a server with passwordless sudo. here is how I made it unable to do anything except deploy.

firmitas, utilitas, venustas - the three qualities, 2000 years later

08/10/2025

firmitas, utilitas, venustas - the three qualities, 2000 years later

Vitruvius wrote down what a building needs. software keeps rediscovering the same three things.

glibc, musl, and the binary that refused to run

27/09/2025

glibc, musl, and the binary that refused to run

my CI got 2x faster and then the container crashed with "GLIBC_2.39 not found". this is what dynamic linking taught me.

Swaptop, monitor your swap usage in real time

12/05/2025

Swaptop, monitor your swap usage in real time

how i made a tui tool to monitor swap using rust

How to change linux swap size

19/02/2025

How to change linux swap size

how to increase linux swap and more about it

how to use tar to compress files

18/02/2025

how to use tar to compress files

How to use tar with examples, and more

My First Post

17/02/2025

My First Post

This is my first blog post.