infra
Everything I host runs on a mini PC on a shelf: a laptop-class Ryzen 7 8745HS, 48 GB of RAM, no GPU, Ubuntu 24.04. It runs an apartment listing monitor, a housing-subscription dashboard, the train seat bot, a WordPress site and a Telegram gateway for an AI agent. There is no pager. When a 4:30 a.m. job failed, it failed silently, and I found out a day later.
UbuntuDocker ComposesystemdCloudflare TunnelSQLite
- Layout
- One Docker Compose project per app, nine containers, all bound to localhost. Public pages come in through a Cloudflare Tunnel, which is just one more container. nginx and a few small apps run on the host under systemd. Data lives in SQLite or JSON files, except WordPress, which brought its own MariaDB.
- 4:30 a.m.
- A nightly job logged
uv: command not foundand stopped. From my own shell it ran fine. Cron's PATH does not include~/.local/bin, where uv lives, and an exit trap underset -eswallowed the real exit code, so nothing complained for 24 hours. The fix was one line: call the virtualenv's Python directly, then prove it underenv -iwith cron's minimal PATH. That project's jobs now run through a wrapper that sends a Telegram message when one fails. - What I got wrong
- The containers run on UTC, and so did the seat bot's idea of today: from midnight to 9 a.m. in Seoul it offered yesterday's trains.