repo/README.md

6.8 KiB

homelab

A common, reusable repository for running services on a personal homelab.

Every service lives in its own folder under services/ and is described by a metadata.json file (plus any extra files the service needs, such as a Caddyfile). The installer/ directory contains a Bun + TypeScript terminal UI (TUI) that reads the catalog straight from GitHub (used as the CDN) and installs or updates services with Docker.

homelab/
├── services/               # one folder per service
│   ├── catalog.json        # generated index used by the installer (CDN listing)
│   ├── allprox/            # Caddy reverse proxy + portal
│   │   ├── metadata.json
│   │   ├── Caddyfile       # proxy rules (domains → local IPs)
│   │   └── portal/index.html
│   ├── authelia/           # SSO / IdP (login portal, OIDC, forward-auth)
│   │   ├── metadata.json
│   │   ├── configuration.yml
│   │   └── users_database.yml
│   ├── lldap/              # lightweight LDAP user store
│   │   └── metadata.json
│   └── ...
├── installer/              # Bun + TypeScript TUI
│   ├── src/
│   └── scripts/
└── docs/
    └── metadata-schema.json

Identity stack (SSO)

Three services work together for single sign-on:

browser ──▶ allprox (Caddy) ──forward_auth──▶ authelia ──LDAP──▶ lldap
  • allprox — reverse proxy; protected routes use Caddy forward_auth to Authelia.
  • authelia — the SSO server (login portal, OIDC, 2FA) that authenticates users against…
  • lldap — the lightweight LDAP directory (web UI at http://<host>:17170).

They talk to each other over a shared external Docker network named homelab, which the installer creates automatically. Install lldap first, then authelia, then allprox:

bun run src/index.ts install lldap authelia allprox

Quick start

# 1. Install Bun: https://bun.sh

# 2. Install the installer's dependencies
cd installer
bun install

# 3. Launch the TUI
bun run src/index.ts

The TUI lets you browse the catalog, install services, update them, uninstall them, and inspect what is currently running. Services are deployed with docker compose into ~/.homelab/services/<id>/ (a docker-compose.yml and a .env are generated from each metadata.json).

Requirement: Docker must be installed and the docker command available on your PATH.

Non-interactive CLI

The same app works as a plain CLI:

bun run src/index.ts list
bun run src/index.ts info allprox
bun run src/index.ts install allprox
bun run src/index.ts update            # update everything installed
bun run src/index.ts update allprox    # update one service
bun run src/index.ts uninstall allprox
bun run src/index.ts status

Useful flags:

Flag Meaning
--local <path> Read services from a local folder instead of GitHub (handy while developing a new service).
--owner/--repo/--branch Override the GitHub source (also available as HOMELAB_OWNER, HOMELAB_REPO, HOMELAB_BRANCH).
--env KEY=VALUE Provide an environment value non-interactively (repeatable).
--yes Never prompt; use defaults or provided --env values.
--dry-run Print what would happen (including the generated compose file) without touching Docker.
--force Re-run an update even if versions already match.
--verbose Stream docker compose output instead of only showing failures.

How the CDN works

The installer treats this GitHub repository as its content delivery network:

  1. It lists services from services/catalog.json (one request). If that file is missing it falls back to the GitHub git/trees API.
  2. Each service's metadata.json is fetched from https://raw.githubusercontent.com/<owner>/<repo>/<branch>/services/<id>/metadata.json.

Pointing the installer at your own fork is just a matter of setting --owner/--repo (or the HOMELAB_* environment variables). For a private repository, export a GitHub token and the installer authenticates its API and raw requests automatically: HOMELAB_GITHUB_TOKEN (or GITHUB_TOKEN / HOMELAB_TOKEN). The repository must be pushed — the installer reads from GitHub, not from your local checkout.

Adding a new service means adding a folder plus its metadata.json and regenerating the catalog:

cd installer
bun run catalog

Adding a service

  1. Create services/<id>/metadata.json (the folder name must equal the id).
  2. Fill in the metadata schema — see services/README.md for a walkthrough of every field. Add any extra files the service needs (a Caddyfile, a Dockerfile, a static portal/, …) alongside metadata.json; the installer copies them into the deploy directory, so reference them with relative bind mounts in compose.volumes.
  3. Regenerate the catalog: cd installer && bun run catalog.
  4. Commit and push. The installer will now offer the new service.

Service metadata at a glance

metadata.json is the single source of truth for a service. The essential shape:

{
  "id": "allprox",
  "name": "allprox",
  "description": "Caddy reverse proxy with an SSO-ready portal",
  "version": "1.0.0",
  "category": "network",
  "compose": {
    "image": "caddy:2-alpine",
    "container_name": "allprox",
    "restart": "unless-stopped",
    "ports": ["80:80", "443:443"],
    "volumes": ["./Caddyfile:/etc/caddy/Caddyfile:ro", "allprox_data:/data"],
    "environment": ["PORTAL_AUTH_HASH=${PORTAL_AUTH_HASH}"]
  },
  "volumes": { "allprox_data": {} },
  "env": [
    { "name": "PORTAL_AUTH_HASH", "label": "Portal admin password hash", "secret": true }
  ]
}
  • compose is a standard Docker Compose service definition (image, ports, volumes, environment, …). The installer wraps it in a generated docker-compose.yml.
  • volumes / networks are optional top-level named volumes/networks to declare.
  • env declares variables the installer should resolve for you. Use ${NAME} in compose to reference them — the installer writes the resolved values to a .env file next to the compose file.
  • Any other files in the service folder (e.g. Caddyfile, portal/index.html) are copied into the deploy directory, so you can mount them with relative paths (./Caddyfile:...) in compose.volumes.

See docs/metadata-schema.json for the complete, machine-readable schema.

License

This repository is a personal template. Service entries reference their upstream projects; each service's own license applies to the software it deploys.