Self-hosted infrastructure for mfilipe.eu on hopper (Debian / ZFS / Docker). Architecture and rationale: DESIGN.md.
| Dir | Service | Endpoint |
|---|---|---|
caddy/ |
Reverse proxy + TLS for all *.mfilipe.eu |
— |
immich/ |
Photos | img.mfilipe.eu |
memos/ |
Notes | notes.mfilipe.eu |
blog/ |
Hugo site, served static from blog/site/ |
blog.mfilipe.eu |
jellyfin/ |
Media (systemd) | tv.mfilipe.eu |
monitoring/ |
VictoriaMetrics + Grafana + Telegraf + vmagent | graf. / metrics.mfilipe.eu |
iot/ |
Zigbee2MQTT + Mosquitto | internal |
llm/ |
Local LLM via llama-swap (systemd); see llm/AGENTS.md |
internal |
ddns/ |
Dynamic DNS updater (systemd timer) | — |
fail2ban/ |
IP banning | — |
git clone git@github.com:msf/selfhost.git /srv/selfhost && cd /srv/selfhost
./deploy.sh # decrypt secrets.tar.age → */env (needs ~/.age-key.txt)- Docker:
docker compose up -din each dir with a compose file (caddy,immich,memos,monitoring,monitoring/telegraf,monitoring/vmagent,iot). - Systemd:
jellyfin,ddns.timer,fail2ban. LLM stack viallm/install.sh, fail2ban viafail2ban/install.sh.
git pull && ./deploy.sh
docker compose restart # in the changed dir
# or: sudo systemctl restart <unit>env files are gitignored; the tracked .env are symlinks to them. The encrypted
bundle is secrets.tar.age (age).
./encrypt-secrets.sh # */env → secrets.tar.age
./deploy.sh # secrets.tar.age → */envdocker ps
docker logs <name>
systemctl status jellyfin ddns fail2ban
sudo fail2ban-client status