Free hosting for side projects ends where Stripe begins

The last mile of a side project is a URL

Every side project has a graveyard stage, and it’s almost always the same one: fully working, completely invisible, running on localhost:3000. The project doesn’t become real until a stranger can load it over HTTPS. The good news is that getting there is now a ten-minute job — push to Git, connect a host, collect a URL. The better news, which nobody advertises on the pricing page, is that “free” on these platforms is a terms-and-quotas decision, not just a price. A detailed comparison of the five big free Git hosts got me thinking about how to frame that decision, because most people frame it wrong.

The map, sorted by what actually binds you

People compare free hosting tiers on bandwidth, and bandwidth is almost never the constraint. What binds you is builds, credits, cold starts, or the terms of service — in roughly that order of surprise. Here’s the honest map:

  • Cloudflare Pages is the generous static default. Requests to static assets are unmetered, you get 500 builds a month, and custom domains just work. The trap in the word “unlimited”: Pages Functions share the Workers free cap of 100,000 requests a day. A brochure site stays free forever; an API-on-the-edge does not.
  • Vercel Hobby is the best developer experience for Next.js and React — detected frameworks, instant preview deploys, roughly 100 GB of fast transfer a month. The trap is the licence, not the quota: Hobby is non-commercial, personal use only.
  • Netlify Free now runs on credits: 300 a month, hard limit, no auto-recharge. A production deploy costs 15 credits and bandwidth costs 20 per GB, so the maths is unforgiving — about twenty deploys a month and not much traffic before visitors see “site not available”. Deploy previews are free, which is the one mercy.
  • GitHub Pages is simplest: 1 GB site, a soft 100 GB monthly bandwidth cap, and a policy that flatly rules out stores and commercial SaaS. Perfect for docs and portfolios, wrong for anything with a checkout.
  • Render static sites are free on a Git-connected CDN with 5 GB of bandwidth — but do not confuse them with Render’s free web services, which sleep after fifteen minutes and take a groggy minute to wake. Free web services are for toy APIs, not for anything with a deadline.

(All numbers move. Screenshot the usage page the week you launch anything real; the two that ambush people are Netlify credits and Vercel fair-use.)

The Stripe tripwire

Here is the part worth internalising, because it’s the same story on every platform wearing a different hat. The moment money touches the URL, the free tier is over — whether or not anyone bills you.

Vercel’s fair-use rules are the clearest example: payments, ads, donation buttons, affiliate-driven sites, and getting paid to build or host the site all count as commercial. There is no “under $10 MRR is still Hobby” clause. One paying customer, or even a tip jar, is the policy line — and crossing it quietly, then migrating during your first traffic spike, is far more expensive than the $20 a month the paid tier would have cost all along. GitHub Pages makes the same call as policy rather than pricing, and Cloudflare’s version is a quota: static business sites are fine, edge functions hit the cap.

So the mental model I use: a free tier is a staging environment with suspiciously good production qualities. Use it for demos, portfolios, experiments, and the version of the product that exists while you’re still deciding. The moment there’s an invoice in either direction, pay for the floor under it. Budget the paid tier as a line item of the first dollar of revenue, not as a response to it.

The homelab objection, taken seriously

Regular readers know my first instinct is to serve it myself: I have servers, a reverse proxy, and a suspicious relationship with uptime monitors. And yes, a static site behind your own proxy is a solved problem. But I’ve come around to a division of labour: the git-push CDN hosts the public-facing, must-be-up-when-my-power-isn’t things — the portfolio, the status page, the write-ups — and the homelab fronts the dynamic stuff, the dashboards, and everything that genuinely needs to run on my hardware.

“Free” is doing quiet work in that sentence. A free tier you treat as a staging environment gives you uptime you don’t personally own, TLS you don’t renew, and a CDN you don’t debug at midnight. That’s a fair trade for a side project. It stops being a fair trade the moment the project has customers, and the whole trick is noticing which side of that line you’re on this week.

Five rules that keep free hosting boring

  • Env vars live in the dashboard, never in the repo. If a .env ever touched Git, rotate every key in it. This is the single most common way a free-tier side project becomes a paid incident.
  • One canonical URL. Don’t dual-deploy to two hosts “for backup” — you’ll end up with two half-updated versions and no idea which one Google indexed.
  • Share preview deploys, not localhost screenshots. The preview URL is the demo. It’s also a free smoke test on infrastructure that isn’t your laptop.
  • Pick the host by your binding constraint. Deploying often? Netlify credits will bite. Edge functions? Cloudflare’s daily cap. Trying to impress a client? Don’t put it on a plan that cold-starts.
  • Decide the money line up front. If Stripe is in the plan, a paid tier is in the plan. Write both names on the same line of the napkin.

Free hosting is genuinely one of the best deals in computing — for the thing you’re building before it’s a product. Treat it as that, upgrade the day it becomes one, and you get all of the free with none of the fine print.

The empty bill of materials: ESP32 jobs that ship with just the board

The best bill of materials is the empty one

Every maker has a shelf of half-planned projects that stalled the moment the shopping list got long. Two sensors, a relay module, a buck converter, a case, some Dupont wire — and suddenly a weekend tinkering session has a lead time and a freight cost. That’s usually where the momentum dies. So there’s something quietly radical about the observation at the heart of a recent XDA roundup of ESP32 projects: there’s a whole class of genuinely useful builds where the parts list is one board and the USB cable already tangled in your drawer.

I want to take that idea seriously, because it’s more than a curiosity. When a project needs nothing you don’t already own, three costs disappear: the money, the wait, and — the expensive one — the decision fatigue. You can start on impulse and finish before dinner. Here are the four jobs that earn that status, and where I’d actually deploy each one.

A DNS sinkhole that fits in your palm

The first surprise: you can run a real ad-blocking DNS sinkhole on an ESP32. Projects like the ESP32_AdBlocker firmware hold a blocklist in memory and answer DNS queries directly, no Raspberry Pi or home server required. The catch is RAM — modern blocklists are chunky, so you want an ESP32-S3 with 8MB of PSRAM rather than the bare classic board.

My honest take: this is not a Pi-hole replacement, and you shouldn’t pretend it is. You lose the query logging, the pretty dashboards, and the group management that make Pi-hole feel like infrastructure. But as a disposable sinkhole it’s excellent — the DNS blocker you hand to a family member, drop on a guest network VLAN, or throw in a bag for travel. If it dies or gets replaced, you’ve lost a five-dollar board, not a server you have to rebuild.

Motion detection with no motion sensor

The cleverest trick in the bunch is ESPectre-style Wi-Fi sensing. Wi-Fi packets carry channel state information — a fingerprint of how the radio signal physically propagates through the room. Move around the room and the fingerprint shifts. An ESP32 sitting next to your access point can watch those shifts and turn them into a motion score, no PIR module anywhere in sight.

Treat this as a lighting convenience, not a security control. After calibration it’s surprisingly reliable for the low-stakes jobs: pantry lights, hallway LEDs, “did someone actually go into the server closet.” I’d still put a real presence sensor on anything where failure hurts — stairs, or anything that decides whether an alarm arms. But for automations where a false trigger costs you nothing, free motion detection from a board that’s already there is an absurdly good deal.

The watchdog that can’t die with your server

This is the one I’d push on every homelab and small business, because it solves a monitoring blind spot that bites people constantly. When your uptime monitor runs inside the stack it’s watching — a container on the same host, a check that depends on the same network path — it fails exactly when you need it. The fix is an out-of-band probe, and an ESP32 on the desk Wi-Fi is about as out-of-band as infrastructure gets.

Flash it with ESPHome, point it at your Proxmox UI or your NAS or the client portal, and let it report connectivity to Home Assistant as a binary sensor. A trimmed version of the config looks like this:

http_request:
  useragent: esp32-watchdog
  timeout: 5s

binary_sensor:
  - platform: template
    name: "Proxmox Web UI"
    id: proxmox_up
    device_class: connectivity
    lambda: return {};

globals:
  - id: failures
    type: int
    restore_value: no
    initial_value: '0'

interval:
  - interval: 30s
    then:
      - http_request.get:
          url: https://192.168.1.50:8006/
          capture_response: true

on_response:
  then:
    - lambda: |-
        id(failures) = 0;
        id(proxmox_up).publish_state(true);

on_error:
  then:
    - lambda: |-
        id(failures) += 1;
        if (id(failures) >= 3) {
          id(proxmox_up).publish_state(false);
        }

The three-strike counter matters: one dropped packet shouldn’t page you, three in a row should. And note what this enables beyond alerts. Because the probe is independent of your servers, it can be the trigger half of a dead man’s switch — if the ESP32 can’t reach the VPS for N minutes, it shuts the VPS down (or fires a webhook, or toggles a smart plug). That’s the shape of real failover logic, running on hardware that costs less than the coffee beside it.

A radio you’re not using yet

The fourth job depends slightly on which board you grabbed. Any ESP32 can act as a Bluetooth proxy, relaying BLE devices to Home Assistant — passive listening, or active control if you want to drive lights and blinds through it. If it’s a C6, the onboard 802.15.4 radio adds two more roles: a Zigbee router extending your mesh, or a Thread radio co-processor. Add a U.FL antenna and it’ll cover more than a room or two.

This is the least glamorous item and the one I’d bet gets the most daily use. Radio coverage problems are the silent tax on every smart-home rollout — pairing fails in the far bedroom, devices drop off the mesh, and the fix is usually “buy another hub.” A spare ESP32 plugged into a wall socket near the dead zone is the fix that’s already in the drawer.

The constraint is the feature

What ties these together isn’t the ESP32 specifically. It’s that each build works because it refuses to accrete parts. No sensors to mount, no modules to wire, no enclosure to print — flash, plug in, done. That’s why they escape the project graveyard: there’s no gap between deciding to do it and having it running.

So the next time you clear out a drawer and find a couple of ESP32s from an old order, don’t bin them and don’t “save” them. A spare board isn’t inventory, it’s unbuilt infrastructure: a travel DNS filter, a closet motion trigger, an independent pair of eyes on your Proxmox node, or a radio bridge for the far end of the house. The only thing you need to add is the cable — and you have that too.

The afternoon rule: if the ESP32 build doesn’t fix something by tonight, don’t build it

Most hardware projects die of ambition, not difficulty

Look in any maker’s drawer and you’ll find the fossils: the ambitious build that was going to do everything, got 70% finished over three weekends, and now powers nothing. The lesson I’ve slowly accepted — and that a lovely XDA piece on afternoon-scale ESP32 builds states better than I have — is that the projects which survive aren’t the cleverest. They’re the ones that fix a real annoyance before bed.

Call it the afternoon rule: if a build can’t remove a genuine, current annoyance by tonight, it’s a solution to a hypothetical problem, and hypothetical problems are how drawers fill up.

What struck me reading that piece wasn’t the five builds themselves — a knock sensor identifying which door, a reed switch on the garage, a vibration sensor announcing the laundry, Bluetooth proxies locating lost headphones, a particulate sensor driving an air purifier. It’s that all five reduce to the same three-stage pattern, and the pattern is the part worth stealing:

  • Sense. One cheap sensor on one cheap board, reporting one fact.
  • Threshold. A rule that turns the raw reading into an event worth knowing about.
  • Notify. A push to the phone of whoever is actually bothered by the problem.

That’s it. No dashboard redesign, no “platform play”, no graphing every metric because the graphing library looks nice. One annoyance, one signal, one notification.

The quality lives in the threshold

Here’s the detail that separates a build you forget about from a build you turn off in week two: the debounce. The laundry example is perfect — a vibration sensor taped to a washing machine can’t just alert “no vibration”, because washers go quiet between spin and fill. Alert fires mid-cycle, everyone learns to ignore it, the build is dead. A three-minute quiet buffer changes it from noise into signal.

The same thinking applies everywhere:

  • A garage door sensor that alerts instantly will nag during a two-minute unloading. Alert on open for more than five minutes.
  • A door sensor that triggers on any vibration will fire in a storm. Require a pattern, or a sustained event.
  • A temperature alarm needs hysteresis, or it flaps around the threshold all afternoon.

In Home Assistant the whole pattern is a few lines, which is precisely why it clears the afternoon bar:

automation:
  - alias: "Washer finished"
    trigger:
      - platform: state
        entity_id: binary_sensor.washer_vibration
        to: "off"
        for: "00:03:00"
    action:
      - service: notify.mobile_app_garys_phone
        data:
          message: "Washer's done — go rescue the laundry"

And the sensor side is an ESPHome config file, not firmware development — YAML you can keep in git next to your compose files, redeploy onto a replacement board in minutes when one eventually dies.

The rule works double duty in a lab or small business

The pattern scales past the house. The same sense → threshold → notify shape, pointed at infrastructure instead of appliances, is most of what a small operation needs from monitoring:

  • A reed switch on the server room or comms-closet door, alerting on open-for-more-than-a-minute. Cheap, dumb, and it will catch the contractor who “just checked something” at 6pm.
  • A water sensor under the rack or the air-con drip tray. One of the least glamorous boards you’ll ever flash, and one of the few that can pay for the entire drawer.
  • A temperature sensor near the switch stack in the cupboard with the closing door and no ventilation, alerting before the gear throttles rather than after it reboots.

None of these need dashboards on a wall. They need a push notification at the moment a fact changes, which is what the afternoon pattern delivers.

Know when to break the rule

Two honest caveats. First, anything involving mains wiring — doorbell circuits, HVAC control, the purifier’s power — moves out of “afternoon” territory the moment you open the case. A relay on the bench is a learning project; a relay inside a machine that’s plugged into the wall is an electrical decision. Use proper isolation, or stay on the sensing side and let the notification land with a human.

Second, safety-critical is out of scope entirely. The rule is for annoyances, and it works because annoyances are cheap to be wrong about. A false “garage open” is a shrug; a sensor trusted to fire a safety alert is a different class of engineering. Keep the two firmly separate.

But within those limits, the rule is the best scope-creep defence I know. The board costs five dollars, the sensor costs two, and the question isn’t “what could this become?” — it’s “what annoyance does this kill by tonight?” Answer the second question first, and the drawer stays a toolbox instead of a museum.

Proofreading is the job your smallest local model does best

The most underrated job in the house is the one your smallest model can do

Every conversation about local LLMs eventually wanders into horsepower: which quantisation, how many billion parameters, whether the GPU can hold the whole context window. Meanwhile the workload that small models are genuinely best at — not “adequate despite their size”, but actually better suited than the big ones — sits quietly in every writer’s workflow: proofreading.

The case was put well in a piece on XDA where a journalist swapped their cloud writing assistant for a small model running on modest hardware, and I think the underlying idea deserves to be generalised across home labs and small businesses: constrained, boring, high-volume text jobs belong on small local models. Not because it’s cheaper — it is — but because the failure modes of a big model are exactly the failure modes you’re trying to avoid.

The problem with “writing assistants” is that they write

Grammar tools have spent the last few years drifting from checker to co-author. Flag a typo, and along comes the suggestion to restructure the paragraph, formalise the tone, and compress three sentences into one nobody would say out loud. If you’ve ever had a document come back sounding like a press release for itself, you know the mode. The tool stopped asking “is this correct?” and started asking “could this be more impressive?”

Here’s the twist: a small local model is largely immune to this, because ambition is a function of capability. A 3–4B parameter model doesn’t have the confidence to restructure your argument. Asked to fix what’s broken and leave the rest, it does mostly that. The model that can’t write a brilliant essay is also the model that won’t try to rewrite yours. What you want from a proofreader is a careful reader with a red pen, not a ghostwriter — and the red pen role is where the small models live.

The setup is smaller than you think

This job does not need the GPU you don’t own. A Qwen, Gemma or Llama model in the 3–4B class runs comfortably on:

  • the mini-PC or NAS already running your containers,
  • a 8–16GB laptop through Ollama or LM Studio,
  • even a recent phone, if you’re curious.

Latency tolerance is the hidden advantage. Nobody cares if proofreading takes four seconds — there’s no chat stream to keep snappy, no autocomplete racing the typist. You paste, you wait, you diff. The job has no egos in it.

The part that actually matters is the prompt. Proofreading quality is mostly a contract about restraint, and it needs to be explicit:

proof() {
  ollama run qwen3:4b "$(cat <<'EOF'
You are a proofreader. Fix only: typos, duplicated words,
grammar errors, and phrasing that is genuinely ambiguous.
Do not rewrite sentences that are already correct. Do not
change tone, structure or word choice. Return the full text
with the smallest possible number of edits, then list the
changes you made in one line each.
EOF
)" "$1"
}

Two details in that prompt are doing real work. “Smallest possible number of edits” turns restraint into a measurable instruction. And “list the changes” means you review a diff instead of trusting a rewrite — which is the entire safety model. Never paste-blind-accept; make the model show its work.

Why local isn’t just a preference here

For individuals, running this locally is nice. For a small business, it’s close to mandatory. The documents that most need a second pair of eyes — quotes, tender responses, client emails, anything under NDA — are precisely the documents you should not be shipping to a third-party API for a typo fix. Cloud AI terms change, retention policies change, and “we pasted the tender document into a chatbot” is not a sentence anyone wants to explain in a security review.

The same privacy argument applies to the homelab journal, the incident postmortem, the email to the accountant. Proofreading is high-touch, low-stakes, repetitive work on sensitive text — the exact shape of workload that should never leave the LAN. Run the model on hardware you own, on a network you control, and the question of where your drafts go answers itself: nowhere.

Give the boring jobs to the small models

There’s a habit worth building from this: match model size to job stakes. Big models for reasoning, synthesis, anything where a wrong answer compounds. Small local models for the high-volume, low-stakes, sensitive-text jobs — proofreading, summarising your own notes, reformatting, extracting structure. Those jobs don’t need brilliance; they need consistency and containment.

The writing stays yours. That’s not a limitation of the setup — it’s the design goal.

The phone test: a self-hosted service isn’t finished until it survives your pocket

A service you can only use at a desk is half a service

Most home lab dashboards have a dirty secret: they’re only ever opened from the chair. The moment you’re standing in the garage, on a client site, or in the supermarket queue, that beautifully docker-composed stack of yours may as well be a screenshot. The services still run — you just can’t reach them, or reaching them is enough friction that you don’t bother.

I’ve been applying a simple filter when deciding what earns a place in the stack, and I’d argue it matters more than most feature comparisons: the phone test. Before a service graduates from “experiment” to “infrastructure”, I try to complete its core workflow from my phone — once on home Wi-Fi, once on mobile data, from somewhere that isn’t my house. If I can’t, it isn’t finished.

The instinct came from a piece on XDA where the author rebuilt their self-hosted stack around exactly this criterion — notes, photos, media, saved links, home control, tasks — and found it changed which tools they picked in the first place. That matches my experience, and I’d go one step further: mobile support isn’t a nice-to-have feature, it’s a proxy for whether the project is any good.

The phone app is an integration test

Here’s why the test works. A desktop web UI can hide a lot of sins. A native (or even decent wrapper) mobile app forces the project to have a stable API, working authentication, sane session handling, and a data model that survives intermittent connectivity. Projects that clear that bar tend to be well-engineered everywhere else. Projects that ship a WebView pointed at their own homepage tend to be fragile in other ways too.

So when I’m evaluating two candidates for the same job, I look at the phone experience first:

  • Real app or thin wrapper? A WebView app that breaks the moment the CSS changes is a maintenance liability, not a client.
  • Offline behaviour. Notes and read-later apps must work on a plane. A dashboard that goes blank without connectivity is tolerable. Know which one you’re getting.
  • Background sync. Photo backup that only runs while the app is foregrounded is not a backup strategy.
  • Push notifications. For anything that alerts — Home Assistant especially — this is the entire point of mobile access.

On those criteria, the same categories keep passing: Joplin for notes, Immich for photos, Home Assistant for the house, a read-later tool (Wallabag or Karakeep), and a task board you can actually tap an item into. If a category’s mobile story is weak across every candidate, that tells you something too — maybe the workflow doesn’t need a phone, or maybe it’s a gap worth solving with a shortcut or an API script instead of a full app.

The test is really a network decision in disguise

Where people trip up isn’t the apps — it’s what mobile access implies. A phone on mobile data cannot reach http://192.168.1.10:8096, and the two honest answers to that are:

  • A VPN, not a port forward. Tailscale or WireGuard on the phone, and every service is reachable by name from anywhere, with zero public attack surface. This is my default and I’d make it yours.
  • A reverse proxy with real auth for the few things that must be public. If a service genuinely needs sharing with other humans, it goes behind HTTPS, with authentication that isn’t a password in a URL.

What you should never do is port-forward six services “for convenience” and tell yourself you’ll get to auth later. The phone test fails permanently the day your stack becomes someone else’s crypto miner. One VPN app on the phone, configured once, covers the whole lab — and it also covers the apps’ strict requirements, because most mobile clients refuse plain HTTP remotes anyway.

For small businesses the same logic applies with higher stakes. The owner who can check the booking system, the camera at the shop, or the backup status from the car park makes faster decisions than one chained to the office PC. Field staff with phones are the norm; give them infrastructure that assumes it.

Run the test before you adopt, not after

The cheap version of all this: before you commit a weekend to deploying a new service, install its phone app first and point it at the demo instance. If the app is a disaster, you’ve saved yourself a weekend. If it’s good, you’ve learned more about the project’s engineering culture than any README can tell you.

Self-hosting is supposed to make your tools yours — every screen you own, not just the one bolted to the desk. If the stack only works from the chair, you haven’t replaced the cloud service; you’ve just moved it into the house and made it less convenient. Make the phone test part of the deployment checklist, and watch how quickly the stack starts feeling like infrastructure instead of a project.

Stop filing notes by hand: the self-triaging vault

Every notes app dies the same death: capture gets easy, filing stays hard, and six months later you’ve got a thousand-note landfill where a knowledge base used to be. The usual advice is discipline — file as you go, tag consistently, review weekly. That advice has never worked once in the history of computing. The fix that actually holds is the same one you’d apply to any other growing system: stop doing the filing yourself and make it a pipeline.

I’ve been running variants of this for a while now — my blog drafts literally start as timestamped quick-capture lines in an Obsidian journal that a script collects every night — and the pattern generalises to any vault. It’s three layers: capture with zero decisions, deterministic rules for everything predictable, and an agent for the ambiguous residue.

Capture is one keystroke, not a journey

Friction at capture is what creates the landfill, because the workaround for “too many steps” is “dump it anywhere.” The fix is a capture macro: one hotkey, a choice of four or five note types, and everything lands in a single Inbox/ folder. No folder decisions, no naming agonising. The note’s type applies a template so it’s born structured:

---
status: seed
type: research
created: {{date}}
---
# {{title}}
## Source
## Notes
## Next

Templating is the unglamorous half of this. A note that starts with frontmatter — status, type, created — is machine-readable on day one, which is exactly what the next two layers need. A note that starts as a blank page never becomes anything else.

Rules file the 80% that’s predictable

Most of what lands in the inbox is boringly predictable: Docker research goes to the Docker folder, client notes go to the client folder, travel stuff to Travel. An auto-filing plugin — AutoMover in Obsidian, a folder-action script, or ten lines of cron anywhere else — moves notes into their homes on rules: title keywords, tags, template type. Mine sweeps every ten minutes. If a note’s title contains “compose” or it’s typed research and tagged docker, it lands in the right place without me touching it.

Two hard-won rules about rules:

  • Keep the list short. Every rule is a promise to maintain it forever. Past fifteen or so, you stop remembering what they do and start getting surprised by where notes end up. Surprise is failure.
  • Write exclusions for anything sacred. Templates, attachments, and anything a script generates should be explicitly excluded from being moved. The first time a rule drags your template folder into Travel, you’ll understand.

The inbox is a queue, not a shame pile

Once capture is one keystroke and rules drain the predictable stuff, what’s left sitting in the inbox after a couple of days is meaningful data. It’s either genuinely ambiguous (belongs to two projects, or none yet) or junk (captured and already obsolete). Both are worth seeing clearly rather than burying in nested folders. An inbox that only ever contains the genuinely-unresolved is a triage queue you can actually act on — that’s a feature, not a failure state.

An agent for the long tail — proposing, not moving

The ambiguous residue is where a language model finally earns a spot in your note-taking. Plain Markdown means the whole vault is agent-legible: point one at the inbox, ask for a move plan, and get back a table of file → suggested folder → one-line reason. Have it flag likely duplicates and orphans while it’s in there. Then you approve the moves in one pass.

The key word is plan. The agent proposes; it doesn’t execute. Batch renames and moves are exactly the kind of thing models are confidently wrong about — close enough to right to look done, wrong enough to quietly wreck a vault you’ve spent years building. A nightly sweep that outputs a plan you skim in the morning gets you 95% of the benefit with none of the 3am regret. And since a vault of Markdown files is just a directory, put it in git first; then every automated action — yours or an agent’s — has an undo button.

Your vault is infrastructure — run it like it

Here’s the homelab framing that makes this click: an unfiled note is unlabeled config drift. A vault that feeds automations — journals that become blog drafts, project notes that become standup summaries — is a production system, and “I’ll organise it this weekend” is not an acceptable ops posture for a production system. Structure maintained by hand rots exactly as fast as structure maintained by nobody. Structure maintained by code — capture templates, filing rules, a scheduled agent sweep — is the only kind that survives contact with a busy quarter.

The goal was never a beautiful vault. It’s a vault that stays out of your way: capture takes one keystroke, the predictable files itself, and the only thing you ever touch is the small pile of genuinely interesting decisions. Build that once and the landfill never forms again.

Inspired by 3 free Obsidian plugins I use to automate my entire vault at XDA — a good walkthrough of the QuickAdd/AutoMover combo from the user side.

Your home lab agent’s first skills should be eyes, not hands

So you’ve stood up an LLM agent somewhere in the home lab. The demos make it look inevitable: plug it into everything, hand it a shell, and let the to-do list melt away. The instinct is to start with hands — restart this, resize that, deploy the thing. Resist it. The first thing your agent should do in your lab is look, and the honest way to make that happen is with skills whose entire job is reading state and explaining it.

There’s a nice shift happening in agent tooling that makes this easy. Agent runtimes — Hermes, OpenClaw, and friends — now have skill systems: packaged instructions plus small helper scripts that teach the agent how a particular system works. And thanks to shared hubs like the Hermes Skills Hub and ClawHub, a skill written for one lab’s Technitium DNS server or Proxmox cluster is often a one-line install for yours. Someone already wrote the glue. Your job is deciding what glue deserves to exist.

A skill is a monitoring probe that can explain itself

Reframe what a skill is and the whole safety question gets simpler. A read-only skill is a monitoring probe with a language model bolted on. Uptime Kuma pings your service and reports up or down. A DNS skill queries your resolver’s API and reports auth failures, zone warnings, and weird error spikes — and then, unlike the probe, it answers follow-up questions. “Which of these errors started first?” is where the agent starts earning its electricity.

Probes don’t need root, and neither do eyes. Before you install anything, run the runtime’s inspection commands and actually read what the skill claims to do:

hermes skills search technitium
hermes skills inspect technitium-dns
hermes skills install technitium-dns

The inspect step is the one people skip and shouldn’t. You’re about to hand a third-party package an environment variable with an API token in it. Look at what endpoints it calls, whether it’s read-only by construction or read-only by promise, and whether the install-time security scan flags anything. Thirty seconds of reading beats a week of regretting.

The three eyes worth installing first

Most home labs converge on the same three load-bearing systems, so the first three read-only skills pick themselves:

  • DNS. It’s the lab’s nervous system. When something is “slow” or “broken,” half the time the real story is in the resolver: unreachable API, auth failures, zones with issues, unusual error rates. A skill that summarizes resolver health turns vague vibes into a diagnosis.
  • The hypervisor. Node inventory, CPU and memory pressure, which guests are stopped, snapshot lists. Ask for a compact summary before you ask for anything deeper — “list my nodes and guests, show node CPU and memory, flag stopped guests, change nothing” is a perfect first prompt.
  • Uptime monitoring. Your dashboard already knows what’s down; a skill lets the agent distinguish a current outage from a down-that-already-recovered, and line the timeline up against the other two eyes.

Notice what’s missing from that list: anything that mutates state. No container restarts, no snapshot creation, no DNS record edits. That’s not timidity — it’s sequencing. You can’t trust an agent’s hands until you’ve watched its eyes for a while.

The real payoff is correlation, not queries

Anyone can open three dashboards. The agent’s edge is holding all three in one context and answering the question you actually have at 7am: what happened overnight, and do I need to care?

So make the agent produce a briefing:

“Check my DNS server for auth problems, zone warnings, and error spikes. Summarize my hypervisor nodes: CPU, memory, any stopped guests. List monitors that are currently down versus down-and-recovered. Correlate timestamps. Read-only, no changes.”

The first few briefings will be mildly wrong in small ways — a service it miscounts, an alert it over-weights. That’s the point of the read-only phase: wrong answers cost you nothing but a correction. Every correction you make is training your own expectations about what the agent sees clearly and where it hallucinates confidence. That calibration is the actual product of week one.

Read-only is a property of the credential, not the prompt

Here’s the part worth internalizing: “keep this check read-only” in a prompt is a suggestion. The token in the environment variable is the contract. If your Proxmox credential can create snapshots, then so can the agent, no matter what the prompt says — a model under instruction drift, a confused plugin, or a malformed request will happily use every permission the token grants.

So scope the credential like you mean it:

  • Proxmox: a PVEAuditor-style role, not root@pam.
  • Technitium or TrueNAS: an API key restricted to read endpoints, in its own TECHNITIUM_URL / TRUENAS_API_KEY environment pair.
  • Uptime Kuma: a viewer-level session, and if the skill only supports fuller access, accept that it can pause monitors and decide whether you’re okay with that.

The env-var pattern most skills use makes this pleasant: one token per skill, one line to rotate, one line to revoke. Treat tokens like the probes they feed — small, named, and individually disposable.

The ladder from watching to touching

Once the briefings have been reliable for a few weeks, you’ve earned the next rung, and only the next one:

  • Observe. Read-only skills, scoped tokens.
  • Correlate. Cross-system briefings on a schedule.
  • Propose. The agent drafts the change — a snapshot plan, a compose fix, a DNS record edit — as a diff you review. It still can’t apply anything.
  • Act. One narrowly-scoped write capability, on one non-critical system, with every action logged somewhere you’ll actually read.

Most labs will live happily on the first three rungs for months. The agents that get there fastest are the ones whose owners can point at a month of briefings and say “its eyes have been right every time.”

The boring briefing is the product

An agent in the lab succeeds the same way good monitoring does: by making the invisible boring. You’ll know the read-only phase worked when the morning briefing is a paragraph you skim in ten seconds and trust completely — and when something does go sideways at 2am, it’s the agent’s correlated timeline, not three browser tabs, that tells you why.

Inspired by 7 Hermes Agent Skills I’d Add to My Home Lab First over at Virtualization Howto — worth a read for the concrete skill list and CLI walkthrough.

Self-hosting Umami: the site analytics a small business actually needs

Inspired by Umami — open-source web and product analytics.

Every small business site I’ve inherited has the same line in its <head>: a Google Analytics snippet someone pasted in 2019 and nobody has logged into since. It sits there slurping data into an account nobody checks, feeding a dashboard with forty reports, hanging a consent banner off the front of the site, and — the part that always gets me — costing actual page weight on every visit, on a service the site owner doesn’t control and can’t export anything useful out of.

Google Analytics is built for organisations with analysts. A tradie’s site, a consultancy, a hobby blog with delusions of grandeur: none of these need “explorations” or a predictive audience. They need four answers — is anyone here, where did they come from, what did they read, did that campaign work? — and they need them in ten seconds without a training course.

That’s the whole case for Umami, an MIT-licensed, privacy-first analytics platform you can self-host. No cookies, no personal data, no cross-site tracking — first-party aggregation only. It answers the four questions and declines to collect the surveillance surplus that creates the legal and ethical overhead in the first place.

Why “no cookies” is a bigger deal than it sounds

It’s not a values statement, it’s an operational one. Analytics that sets no cookies and stores no personal data doesn’t just feel cleaner — it removes the reason a small site drags a consent banner in front of every visitor. I’m not your lawyer and rules differ by jurisdiction, so verify your own obligations, but the banner exists to obtain consent for the tracking. Delete the tracking and the banner’s reason for existing goes with it. Fewer scripts, faster loads, nothing to consent to.

There’s a trust angle too: when a client asks “who has my visitors’ data?”, the answer becomes “me, in a Postgres database on hardware I control, and it’s page URLs and referrers, not people.” That’s an answer you can give without flinching.

One container and a database

The deployment is the kind of small a homelab barely notices. Umami ships a Docker image and a compose file that brings up the app with PostgreSQL:

docker compose up -d

The image is docker.umami.is/umami-software/umami:latest, the database wants PostgreSQL 12.14 or newer, and the first build creates your tables plus an admin account you should change the password of immediately. If you’d rather run from source, it’s a Node 18.18+ app with a one-variable .env — DATABASE_URL — and a build step. Behind your existing reverse proxy on some hostname like stats.example.com, it’s just another service in the rack. Updates are the usual dance: docker compose pull && docker compose up -d --force-recreate.

Instrumenting the site is one async script tag with a data-website-id. There’s no plugin to install, no tag manager to wrangle. If you can edit a template, you’re live.

What you get, and what you don’t

The dashboard is deliberately small: traffic over time, visitors, pageviews, top pages, referrers, countries, browsers and devices, plus events and UTM-tagged campaigns so “did the newsletter work” is a filter click instead of a research project. You can generate share links — a public, read-only view of a site’s stats — which is a surprisingly useful client-facing feature: send the link, skip the PDF export ritual every month.

What you don’t get is the deep end: session replay, funnels through twelve steps, cohorts, “AI insights”. If your business genuinely lives and dies on product-analytics funnels, run a product-analytics tool and pay for it honestly. But for the ninety percent of sites whose analytics questions end at “is the blog working, and where do people come from”, the deep end is a cost centre — in dollars, in complexity, and in privacy exposure.

One genuinely forward-looking detail: Umami has an MCP endpoint (off by default — enable with MCP_ENABLED=1 and an API key from Settings). That means your agent can query the analytics itself. “Ask the stats server how last week’s post did” becomes a tool call. On a homelab that’s already agent-shaped, that’s a nice little moat GA will never give you.

The honest trade-offs

  • You own the uptime. If the container falls over, your stats stop recording. It’s a single service with one dependency — but it’s yours to monitor, back up and upgrade. Put it with the rest of your watched services.
  • You own the data — including its loss. Back up the database. It’s one Postgres volume; snapshot it with everything else.
  • Ad blockers still block it. Self-hosted analytics dodges most GA-specific blocklists but not all blockers. Treat numbers as trends, not censuses — which, honestly, is all GA ever gave you too.

Google Analytics is free the way a puppy is free: the purchase price is the smallest cost you’ll ever pay. For a small business site, Umami flips the model — a few hundred megabytes of RAM and a Postgres volume, in exchange for faster pages, no consent banner theatre, answers in ten seconds, and a stats database whose continued existence doesn’t depend on a product manager at a trillion-dollar company staying interested. That last one, historically, is the strongest argument of all.

ArtCraft: the creative suite rebuilt in Rust, with agents in the driver seat

Inspired by “Crafting Apps: thirteen open-source creative tools, built in Rust” (ArtCraft).

Every year or so, someone announces they’re going to replace Adobe with open source, and every year the announcement ages like milk. GIMP still opens with a dialogue about its old name, Krita is genuinely great if you paint, Inkscape’s exporters still fight you — and the suite-of-misfits problem never goes away: each app has its own shortcuts, its own file habits, its own ideas about what a toolbar is. So when a project called ArtCraft says it’s building thirteen creative apps from scratch — image editor, vector illustration, video editing, raw photo development, PDF workbench, motion graphics, page layout, interface design, word processing, audio workstation, presentations, CAD and spreadsheets — my first reaction was healthy scepticism.

My second reaction was that they’re not attacking the problem the way everyone else has, and the difference matters even if you never install a single one of these apps.

One stack, one language, no Electron

All thirteen apps are being written from scratch in Rust, compiled to native desktop apps for macOS, Windows and Linux — no Electron, no web views, no Chromium instances wearing an app costume. Each app also compiles to WebAssembly and runs in a browser tab, which sounds like a party trick until you remember what it means for deployment: the same codebase behind your desk and in a browser, with no porting layer between them.

The stated rules are consistent across the lineup: open source under permissive licences with the code on GitHub, files that stay on your machine (no cloud round-trip between you and your work), and layouts familiar to professionals who already know the incumbent tools. There’s a launcher that installs and updates the whole set, the way a package manager should have been doing this for a decade.

The sceptic’s caveat, stated plainly: most of the lineup is labelled “in development”, and the rest “early alpha”. Nobody should be cancelling an Adobe subscription over this today. Video editing, DAW work and CAD are famously brutal categories where the incumbents have decades of edge-case scar tissue. A from-scratch video editor is a five-year problem even when it’s the only thing you’re building.

The part that’s actually new

Here’s the line in their principles that made me stop scrolling: agent-ready. Every app is drivable from a CLI, a JSON control channel, or an MCP server — built for automation and AI agents from day one, not bolted on later.

Think about what that means in practice. A PDF tool you can drive from a script means “split these 40 invoices, stamp each with its filename, move them to the client folder” is a one-liner in your agent’s tool belt — no UI automation, no screenshot-driven hacks, no hoping the desktop app doesn’t steal focus mid-job. An image editor with a JSON control channel means batch-resizing, watermarking and exporting become part of a pipeline instead of a Tuesday morning of clicking. The MCP support means an agent you already run — the one that lives in your homelab and handles the boring chores — can operate these apps like it operates your file system.

This is the inversion worth paying attention to. The old open-source pitch was “same experience, zero dollars”, and it lost because the experience was never quite the same. The pitch hiding inside ArtCraft is different: software you can program beats software you can click, and the creative apps are the last major category where nobody’s seriously tried it. Commercial vendors won’t do this — scriptable creative apps cannibalise the seat licences that fund them. An open-source suite has no such conflict.

What a small shop should actually do

  • Don’t migrate anything. It’s alpha software. Your production files deserve better.
  • Pilot the utilities, not the exotic stuff. A PDF workbench and an image editor are low-stakes, high-frequency tools where an alpha is genuinely usable and an agent hook pays for itself immediately. A from-scratch DAW is not that.
  • Watch the file formats, not the feature lists. The suites that die, die on compatibility. If these apps read and write the incumbent formats honestly (PSD, RAW, PDF/A, SVG, XLSX), they have a path. If they champion a new format first, they don’t.
  • Steal the architecture even if you ignore the apps. If you build internal tools, “every app ships with a CLI, a JSON channel and an MCP server” is a principle you can adopt on Monday. Your future automation stack will thank you.

The bet, framed honestly

Thirteen simultaneous from-scratch rewrites is either monumentally ambitious or monumentally naive, and at alpha stage you can’t tell which from the outside. But the goalposts have moved. Five years ago, an open-source creative suite needed to win a beauty contest against polished commercial tools, and that was a losing game. Today it needs to be good enough to click and perfect to script — because the thing doing the scripting didn’t exist when the incumbents were designed.

That’s the shift worth tracking. The version of this story where it succeeds isn’t “free Photoshop”. It’s “an agent that lives on your NAS quietly processes every asset that touches your business, and the human only opens an app for the decisions that need taste.” Watch the launcher’s update notes, pilot a utility or two, and keep your files portable in the meantime.

The capture layer your homelab is missing: self-hosting Memos for notes you don’t have to file

Inspired by “My favorite Notion alternative isn’t OneNote or Obsidian: it’s more powerful and private” (XDA).

Every note-taking app I’ve used eventually asks the same question before it will accept a single sentence: where does this live? Which page, which database, which workspace, which of the three apps that each hold a third of your system? I’ve lost more thoughts to that decision than to forgetfulness. The thought arrives, the filing dialog opens, and by the time the thought has a home, it’s gone.

That’s the problem Memos solves, and it solves it by refusing to ask. It’s a self-hosted, capture-first note app: you type, it lands on a timeline, you get on with your day. Organization happens later — or never, which turns out to be fine more often than you’d think.

The filing tax

Notion is powerful, but it’s organize-first: you shape your workflow around its databases, and every capture starts with a filing decision. Obsidian gives you local Markdown files, which fixes ownership but not the decision burden — and once you add plugins and themes and CSS snippets, the vault itself becomes a project. OneNote is a notebook. All three tax the first two seconds of note-taking, which is exactly when you can least afford it.

Memos inverts the order. The timeline is the whole interface. You post first and structure emerges from what you actually captured — which, if you’re honest about your note-taking, is mostly one-liners: a command to look up, an app to try, a headline variant, something to check on a server. Not documents. Fragments.

One container, one volume

For a homelab, the deployment is about as small as self-hosting gets. An official Docker image, SQLite by default, one persistent volume:

docker run -d --name memos \
  -p 5230:5230 \
  -v /srv/memos:/var/opt/memos \
  usememos/memos:stable

Treat that as a sketch and check the current docs before you commit it to Compose — image tags and volume paths have changed between releases. Once it’s up, you open the port in a browser, create the admin account, and you’re running. No database server, no dependencies worth naming, nothing to babysit.

The backup story is the quiet best part: your entire instance is essentially one SQLite file in that volume. Snapshot it with your existing host-level backups and you’re done. Every note you own, in one file, on hardware you control — if you’ve ever had to export years out of someone else’s cloud, you know that’s not a small thing.

Tags do the filing for you

The trick that makes capture-first survivable is that structure is inline. You don’t file a memo into a hierarchy — you tag it as you type: #docker, #articleideas, #client/acme. Nested tags give you structure when you want it, search finds everything else, and the home page has a calendar view so “what did I do Tuesday” is answered visually.

The organizational debt doesn’t disappear, but it becomes optional and deferrable. Most of my memos never need promoting — they were valuable for a day and then they weren’t, and a timeline full of stale one-liners costs nothing. The few that matter get promoted on purpose.

Where it sits next to a vault

Memos is not an Obsidian replacement, and you shouldn’t ask it to be. It’s the intake layer. The pipeline that feeds this very blog starts as one-line captures; a capture tool that demands zero decisions is exactly the right shape for that job. The pattern that works:

  • Capture everything to the Memos timeline, tagged loosely
  • Promote weekly — the handful of memos with staying power become real notes or documents in your vault or repo
  • Leave the rest on the timeline, where search still finds them

That division of labour beats either tool doing both jobs. Vaults are for thinking; timelines are for catching.

The honest limits

Memos won’t replace Notion for everyone. There are no relational databases, no board views, no complex team workflows — if your notes need structure stronger than tags and search, you’ll hit the wall fast. It’s not for long-form writing either; the editor is simple by design. There’s PWA support so it installs like a native app on phone and desktop, themes well past the usual light/dark pair, and you can publish individual memos as links — which makes a private instance double as a low-commitment microblog — but the scope stops deliberately at capture.

That restraint is the feature. The next time a thought shows up unannounced, the only thing between it and being saved is a text box. That’s how it should always have worked.

WordPress Appliance - Powered by TurnKey Linux