My VPS homelab setup with simple docker-compose stacks and Caddy as a reverse proxy & https cert manager.
See GUIDE.md for detailed setup instructions and security considerations.
Structure of VPS home directory from a non-root but sudo user:
~/infra/- Caddy and Kuma docker-compose stacks~/apps/- Other apps~/tools/- Other tools~/actions-runners/- Self-hosted GitHub Actions runners as a systemd service
- Caddy as a reverse proxy and cert manager. Create a single caddy network for all containers to share.
- GH Actions runners on VPS for CI/CD (self-hosted runners as systemd services). One runner for infra, one for each app repo.
- Kuma for observability. Accessible via Tailscale net OR
kuma.simlal.dev
- Redirect here: simlal.dev (Recursion!)
- Static healthcheck: healthcheck.simlal.dev
curl-able CV (Next): curl-cv.simlal.dev- ...
Using Kuma service mesh for observability. Accessible via kuma.simlal.dev reverse proxied by Caddy.
Manually configure Kuma monitors for each app/container on dashboard.
Example:
Caddy serves a static file at healthcheck subdomain:
healthcheck.simlal.dev.
Configure SMTP alerts in Kuma to send email notifications for each service.
Example email subject when stopping the Caddy container:
Homelab (main healthcheck - https://simlal.dev/health): 🔴 Down
Using self-hosted GitHub Actions runners on the VPS for CI/CD. Push-based model for simplicity (no webhooks or polling).
Repo level self-hosted runners as systemd services on the VPS.
All stacks are deployed via GitHub Actions workflows in this repo.
Similar push-based GitHub Actions workflows for each app repo to deploy to VPS.