- Dockerfile 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| homelab | ||
| vps | ||
| .gitignore | ||
| README.md | ||
services
Self-hosted lab: Docker Compose stacks on two hosts, organized by role. There is no root compose file — each service has its own, deployed from its directory on the host that runs it.
Layout
| Role | Host | Checkout | Contents |
|---|---|---|---|
homelab/ |
app-services (homelab container) | /opt/services |
Apps: files, git, dashboard, notes, blog, terminal |
vps/ |
nirvana (VPS) | /opt/services |
Infra: mesh VPN, identity, CI runner |
See homelab/README.md and vps/README.md for the per-service tables.
Hosts
- app-services — homelab container, runs the
homelab/apps behind the shared externalproxyDocker network. Traefik here is currently off. SSH aliasapp-services(port 5550, key~/.ssh/hermes-agent). - nirvana — public VPS, runs the
vps/infra: netbird mesh (Traefik + crowdsec, TLS via Let's Encrypt), pocket-id OIDC, Forgejo Actions runner. SSH aliasnirvana(port 5550, same key).
Services are reverse-proxied at *.apps.luigi.ovh subdomains; some are only
reachable via the netbird mesh.
Deploy
cd <role>/<service-dir>
docker compose pull # fetch newest images
docker compose up -d # (re)create the containers
up -d recreates a container only when its image or config changed; add
--force-recreate to force it. Deploys are manual from the checkout on the
host that runs the stack.
Secrets
Never committed. Live values live on the host in gitignored .env files and
secret paths (see .gitignore); every service ships a .sample / .example /
.template counterpart. Copy the template to the live name and fill in real
values. Persistent data (*/data/, *.db*) is also host-only and covered by
the offsite backup job — the repo holds config, not state.