Writing
Blog
Transparency: most posts here are drafted with AI assistance, and the non-English versions are machine-translated by a local LLM and then reviewed. Spotted an error? Please let me know.
-
Before the battery does — watching, and safely steering, a fleet of DC power systems over SNMP
A telecom site's quiet promise is that the lights stay on when the grid doesn't. This is the system that keeps watch over a fleet of Eltek DC power plants — discovering them from Zabbix, classifying them against editable per-vendor SNMP profiles, polling every fifteen minutes for metrics and component inventory, and letting operators steer controller parameters over SNMP behind hard guardrails: validate, confirm, set, read back, audit, revert.
-
Knowing what your nginx config actually allows — an auditor that computes effective access
nginx-acl-guard parses an nginx config with crossplane, computes the effective access policy for every server/location, and guards edits behind a pipeline that diffs effective access and refuses any unconfirmed widening — git backup, nginx -t on staging, atomic swap, rollback.
-
A self-translating blog: SQLite, a Markdown editor, and a local LLM
How this blog works under the hood — posts live in SQLite and render Markdown at request time, an admin editor replaces build-time files, and a local Gemma model drafts the Russian and Ukrainian versions for me to review before they go live.
-
RAG for the fuzzy questions, a deterministic CLI for the exact ones
maximo-ticket-tools — a read-only toolkit over an IBM Maximo trouble-ticket system: index it into a local Onyx RAG for natural-language questions, but answer 'how many' with deterministic queries, never the LLM. Plus a PoP-map dashboard and a Telegram watcher.
-
Renting a house with a local LLM as the filter
home.khanoff.com — a watcher that pulls fresh house-rental listings from two Ukrainian sources, scores each one against fuzzy human criteria with a local LLM, and pings me on Telegram. The model never sits on the ingest path.
-
A resident portal for a homeowners’ association — in plain PHP and SQLite
osbb-wh.pp.ua — a private web cabinet for the members of an apartment association: announcements, documents, a car registry with licence-plate OCR, polls, tickets to the board and internal mail. No framework, no MySQL — PHP 8.3 and a SQLite file.
-
Leaving WordPress: migrating my site to Astro and SQLite
Why I replaced a 475 MB WordPress install on andrew.khanoff.com with a single Astro container and a SQLite file — and how I did the cutover with zero downtime and a one-command rollback.
-
A daily GitHub → local LLM pipeline that writes my project cards
How the Projects section on this site is filled automatically: a cron job reads my private repos, asks a local Gemma model to draft a blurb, and merges the result into SQLite — without ever overwriting my edits or leaking a private repo.
-
A typo-tolerant family document hub with FastAPI and Meilisearch
start.khanoff.com — a warm, self-hosted hub for the whole family: documents, how-tos, recipes, links and videos behind one forgiving search box. FastAPI + HTMX + Meilisearch + Immich, magic-link login, PWA.
-
Building a self-hosted CV with Astro, SQLite and a local LLM
How andrew.khanoff.com is built — server-rendered Astro, a SQLite single source of truth, passkey-only admin, and a daily GitHub→local-LLM pipeline that drafts the project cards.
-
Auto-blocking attackers with BGP — an IDS that announces black-hole routes
Suri Defender: detection feeds (CrowdSec + fail2ban) drive an ExaBGP route-injector that announces offending IPs as RTBH routes over iBGP, so attack traffic is dropped at the network borders — not on the server. A 2.7 GB stack rewritten into a few hundred MB.