← Seungheon Lee

Home Server

2026 · Side project

infra home server containers 9 one box Ryzen 7 8745HS 8 cores · 16 threads · 48 GB cron · 04:30 uv: command not found .venv/bin/python · ok tunnel wordpress mariadb seat bot listings bot housing web housing api video tool api video tool ui

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 found and stopped. From my own shell it ran fine. Cron's PATH does not include ~/.local/bin, where uv lives, and an exit trap under set -e swallowed the real exit code, so nothing complained for 24 hours. The fix was one line: call the virtualenv's Python directly, then prove it under env -i with 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.