<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Vineeth N K, Blog</title><description>Writing code, building tools, and sharing what I learn along the way.</description><link>https://vineethnk.in/</link><language>en</language><item><title>I blocked Tor exit nodes, then I opened Tor Browser</title><link>https://vineethnk.in/blog/i-blocked-tor-then-opened-tor-browser/</link><guid isPermaLink="true">https://vineethnk.in/blog/i-blocked-tor-then-opened-tor-browser/</guid><description>I deployed a hardened Tor exit node firewall on a SaaS production box, opened Tor Browser to confirm, and the site loaded. The IPv4 fortress was perfect. The IPv6 side door was wide open. This is the script, the punchline, and the rewrite that became TorShield.</description><pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate><category>tor</category><category>iptables</category><category>ipset</category><category>ipv6</category><category>linux</category><category>security</category><category>ops</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>The node_modules That Wouldn&apos;t Die</title><link>https://vineethnk.in/blog/the-node-modules-that-wouldnt-die/</link><guid isPermaLink="true">https://vineethnk.in/blog/the-node-modules-that-wouldnt-die/</guid><description>An internal app deploy kept importing an old Vite plugin export. The lockfile was right, the build was wrong. The culprit was older than the bug.</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate><category>docker</category><category>deployment</category><category>git</category><category>ci-cd</category><category>ops</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>The Sentry signup nobody could finish</title><link>https://vineethnk.in/blog/the-sentry-invite-that-never-arrived/</link><guid isPermaLink="true">https://vineethnk.in/blog/the-sentry-invite-that-never-arrived/</guid><description>A colleague signed up on our self-hosted Sentry and never got the email. I had been getting Sentry mail forever, so I assumed he was missing something. He was not. DMARC was silently dropping every message to our Workspace inboxes, and the &apos;workaround&apos; I shared with him broke too. Here is the bug, the lie my inbox had been telling me, and the shell command that finally got him in.</description><pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate><category>sentry</category><category>self-hosted</category><category>dmarc</category><category>smtp</category><category>ops</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>The sed that didn&apos;t stick</title><link>https://vineethnk.in/blog/the-sed-that-didnt-stick/</link><guid isPermaLink="true">https://vineethnk.in/blog/the-sed-that-didnt-stick/</guid><description>A failing nightly backup, a sed hotfix that worked once, and the next morning&apos;s cron that failed anyway. Node&apos;s require cache had eaten my patch.</description><pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate><category>docker</category><category>node</category><category>backup</category><category>ops</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Cross-Posting My Blog to dev.to and Hashnode: What I Got Wrong</title><link>https://vineethnk.in/blog/cross-posting-blog-to-devto-and-hashnode/</link><guid isPermaLink="true">https://vineethnk.in/blog/cross-posting-blog-to-devto-and-hashnode/</guid><description>I figured cross-posting my Astro blog to dev.to and Hashnode would take an afternoon. It turned into four PRs, three failure modes, and a few API surprises.</description><pubDate>Sat, 25 Apr 2026 00:00:00 GMT</pubDate><category>blog</category><category>automation</category><category>github-actions</category><category>devops</category><category>self-hosting</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>I Mistook gpt-oss for an Image Generator. Now My Mac Runs FLUX Offline.</title><link>https://vineethnk.in/blog/i-mistook-gpt-oss-for-an-image-generator/</link><guid isPermaLink="true">https://vineethnk.in/blog/i-mistook-gpt-oss-for-an-image-generator/</guid><description>I asked gpt-oss for an image, realised it cannot do that, and ended up with FLUX running on my Mac through Draw Things and a tiny curl pipeline. A full walkthrough so you do not repeat my mistakes.</description><pubDate>Sat, 25 Apr 2026 00:00:00 GMT</pubDate><category>mac</category><category>ai</category><category>flux</category><category>draw-things</category><category>local-llm</category><category>image-generation</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Building a per-repo wiki that actually gets read</title><link>https://vineethnk.in/blog/per-repo-wiki-that-gets-read/</link><guid isPermaLink="true">https://vineethnk.in/blog/per-repo-wiki-that-gets-read/</guid><description>The docs existed. The CI/CD was already automated. And yet I was still getting pinged before every deployment. Honest field notes on why a per-repo wiki finally broke the loop, and the hidden .wiki.git repo nobody talks about.</description><pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate><category>docs</category><category>github-actions</category><category>devops</category><category>team-process</category><category>onboarding</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Why I Stopped Arguing About Docker Port Conventions</title><link>https://vineethnk.in/blog/docker-port-convention-suffix-vs-prefix/</link><guid isPermaLink="true">https://vineethnk.in/blog/docker-port-convention-suffix-vs-prefix/</guid><description>A colleague raised port conflicts in the daily. A suffix vote lost to the 16-bit limit. A prefix rule worked but still felt wrong. Then docker-compose.override.yml.example made the whole debate go away.</description><pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate><category>docker</category><category>devops</category><category>compose</category><category>workflow</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Setting Up a MinIO CDN with Nginx Reverse Proxy on Docker</title><link>https://vineethnk.in/blog/setting-up-minio-cdn-nginx-docker/</link><guid isPermaLink="true">https://vineethnk.in/blog/setting-up-minio-cdn-nginx-docker/</guid><description>A practical walkthrough for self-hosting an S3-compatible CDN with MinIO, Docker Compose, and Nginx - including the small config bits everyone seems to miss until presigned URLs start failing.</description><pubDate>Wed, 22 Apr 2026 00:00:00 GMT</pubDate><category>minio</category><category>nginx</category><category>docker</category><category>self-hosting</category><category>devops</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>The day I realised I had never tested a production backup</title><link>https://vineethnk.in/blog/the-day-i-tested-a-production-restore/</link><guid isPermaLink="true">https://vineethnk.in/blog/the-day-i-tested-a-production-restore/</guid><description>I had been running test-backup drills for months and felt covered. But I had never pulled a real production snapshot into a lab and restored it. The afternoon I finally did is the story behind this post.</description><pubDate>Tue, 21 Apr 2026 00:00:00 GMT</pubDate><category>backup</category><category>docker-compose</category><category>databases</category><category>ops</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>The second half of shipping a CLI: Homebrew tap, Scoop bucket, and the SHA dance</title><link>https://vineethnk.in/blog/shipping-ipwhoami-to-brew-and-scoop/</link><guid isPermaLink="true">https://vineethnk.in/blog/shipping-ipwhoami-to-brew-and-scoop/</guid><description>What happens after you publish to npm? For Mac and Windows users, mostly nothing. Here is the packaging side-quest of getting ipwhoami onto brew and scoop.</description><pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate><category>cli</category><category>homebrew</category><category>scoop</category><category>packaging</category><category>github-actions</category><category>release-please</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Building docling-server: a one-command document API for our AI pipeline</title><link>https://vineethnk.in/blog/building-docling-server/</link><guid isPermaLink="true">https://vineethnk.in/blog/building-docling-server/</guid><description>Why I wrapped docling into a full Docker Compose setup with FastAPI, Celery, and nginx — so our AI project could stop worrying about messy PDFs, Word files, and scanned junk, and just get clean markdown back.</description><pubDate>Sat, 18 Apr 2026 00:00:00 GMT</pubDate><category>docling</category><category>fastapi</category><category>celery</category><category>docker</category><category>ai-pipeline</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Building mcp-pool: one week, eleven MCP servers, one shared OAuth library</title><link>https://vineethnk.in/blog/building-mcp-pool/</link><guid isPermaLink="true">https://vineethnk.in/blog/building-mcp-pool/</guid><description>How a single Stripe MCP server turned into a monorepo of eleven, and why half the engineering effort went into not writing the same OAuth flow six times.</description><pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate><category>typescript</category><category>mcp</category><category>oauth</category><category>monorepo</category><category>ai-tooling</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>I upgraded our 2.5-year-old self-hosted Sentry without losing a single byte</title><link>https://vineethnk.in/blog/upgrading-self-hosted-sentry/</link><guid isPermaLink="true">https://vineethnk.in/blog/upgrading-self-hosted-sentry/</guid><description>A self-hosted Sentry instance, 2.5 years behind, 0 bytes of swap free, 4 mandatory version hops, 78 containers, and one afternoon where I learned that enabling a feature and using a feature are not the same thing.</description><pubDate>Thu, 16 Apr 2026 00:00:00 GMT</pubDate><category>sentry</category><category>self-hosted</category><category>devops</category><category>upgrade</category><category>docker</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>A short history of the CLI I built to stop curling IP APIs</title><link>https://vineethnk.in/blog/a-short-history-of-ipwhoami/</link><guid isPermaLink="true">https://vineethnk.in/blog/a-short-history-of-ipwhoami/</guid><description>It was supposed to be a weekend CLI. Then the name got stolen, the providers started disagreeing with each other, the rate limits hit back, and somewhere along the way the simple tool grew its own self-hosted backend.</description><pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate><category>cli</category><category>node</category><category>ip</category><category>geolocation</category><category>open-source</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>My family thinks WhatsApp can send anything. So I wrote a Python CLI.</title><link>https://vineethnk.in/blog/my-family-whatsapp-made-me-build-medix/</link><guid isPermaLink="true">https://vineethnk.in/blog/my-family-whatsapp-made-me-build-medix/</guid><description>A 2005 wedding video, an 8 GB .VOB file, a family WhatsApp group with unreasonable faith, a small privacy grudge against Google, and the weekend Python CLI that came out of it.</description><pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate><category>python</category><category>ffmpeg</category><category>cli</category><category>media</category><category>open-source</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>jquery.verticalScroll.js: a love letter to jQuery, written ten years later</title><link>https://vineethnk.in/blog/jquery-vertical-scroll/</link><guid isPermaLink="true">https://vineethnk.in/blog/jquery-vertical-scroll/</guid><description>I saw Apple&apos;s iPhone page in 2016, thought &apos;I can build that in jQuery,&apos; and somehow I&apos;m still maintaining it in 2026. Zero stars. Zero regrets.</description><pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate><category>jquery</category><category>plugin</category><category>javascript</category><category>scss</category><category>open-source</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>My .zshrc is 350 lines and I mass-replaced every core Unix command</title><link>https://vineethnk.in/blog/my-zshrc-archaeology/</link><guid isPermaLink="true">https://vineethnk.in/blog/my-zshrc-archaeology/</guid><description>A 350-line .zshrc, a 68-line .bash_aliases time capsule from the Linux era, a secret gist, and the story of a developer who can&apos;t let go of a shell config.</description><pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate><category>shell</category><category>zsh</category><category>dotfiles</category><category>devtools</category><category>personal</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>dfree: stop digging with your hands, you&apos;ve got an axe now</title><link>https://vineethnk.in/blog/dfree-disk-cleanup/</link><guid isPermaLink="true">https://vineethnk.in/blog/dfree-disk-cleanup/</guid><description>A short story about running out of server space because of academy videos, and the shell tool I wrote so I&apos;d never hear &apos;Vineeth, we can&apos;t upload anymore&apos; again.</description><pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate><category>shell</category><category>cli</category><category>devops</category><category>disk-cleanup</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Building agent-sessions: a universal session manager for the AI CLI era</title><link>https://vineethnk.in/blog/building-agent-sessions/</link><guid isPermaLink="true">https://vineethnk.in/blog/building-agent-sessions/</guid><description>Five AI coding agents, five incompatible session formats, one terminal UI to browse them all — and the reverse-engineering it took to get there.</description><pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate><category>typescript</category><category>cli</category><category>ai-tooling</category><category>hexagonal-architecture</category><category>react</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>diskdoc and dockit: same problem, two languages, different answers</title><link>https://vineethnk.in/blog/diskdoc-and-dockit/</link><guid isPermaLink="true">https://vineethnk.in/blog/diskdoc-and-dockit/</guid><description>I built two disk cleanup CLIs — one in Rust with a TUI, one in Go with risk scoring. Here&apos;s what each language and design taught me that the other couldn&apos;t.</description><pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate><category>rust</category><category>go</category><category>cli</category><category>docker</category><category>tui</category><category>open-source</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Building backupctl: what it took to replace a cron job with a backup service</title><link>https://vineethnk.in/blog/building-backupctl/</link><guid isPermaLink="true">https://vineethnk.in/blog/building-backupctl/</guid><description>How a cron-and-restic setup outgrew itself, and the NestJS backup service I built to replace it — with two war stories I didn&apos;t see coming.</description><pubDate>Sat, 11 Apr 2026 00:00:00 GMT</pubDate><category>nestjs</category><category>hexagonal-architecture</category><category>backup</category><category>restic</category><category>open-source</category><category>journey</category><author>me@vineethnk.in (Vineeth N K)</author></item><item><title>Hello World — Welcome to My Blog</title><link>https://vineethnk.in/blog/hello-world/</link><guid isPermaLink="true">https://vineethnk.in/blog/hello-world/</guid><description>First post on my new portfolio blog. A quick intro about what to expect and why I decided to start writing.</description><pubDate>Wed, 03 Apr 2024 00:00:00 GMT</pubDate><category>intro</category><category>blog</category><category>personal</category><author>me@vineethnk.in (Vineeth N K)</author></item></channel></rss>