IronCard

A workout tracker web app I built with Claude as my coding partner, then deployed on the home server. I run it like a production app: it runs in a container, it's never exposed directly, and the only way in is over HTTPS with a login.

App
IronCard workout tracker, written with Claude, packaged as a Docker container
Host
Home server, RHEL 10 with Docker Compose
Front door
Caddy reverse proxy with HTTPS and a password prompt
Access
On my LAN, and from my phone anywhere through Tailscale

How it's deployed

  • Localhost only. The container publishes its port on 127.0.0.1, not on the LAN, so nothing on the network can reach the app directly.
  • One way in. Caddy is the only path to the app. It serves a local HTTPS name with a certificate from its private CA, like every other service on the server.
  • A login in front. Caddy asks for a username and password before passing any request through. The password is stored as a bcrypt hash, never in plain text.
  • Phone access without open ports. Tailscale lets me use it from my phone anywhere without exposing anything to the internet.
Phone (Tailscale) or laptop
  |  HTTPS
  v
Caddy :443, private CA certificate
  |  basic auth (bcrypt)
  v
IronCard container, 127.0.0.1 only
The app's port never leaves the host, so every request goes through Caddy.