Add homelab installer and services (allprox, authelia, lldap)
This commit is contained in:
parent
68b23f1cbe
commit
bb754cdd8c
32 changed files with 2356 additions and 1 deletions
169
README.md
169
README.md
|
|
@ -1 +1,168 @@
|
|||
# homelab
|
||||
# homelab
|
||||
|
||||
A common, reusable repository for running services on a personal homelab.
|
||||
|
||||
Every service lives in its own folder under [`services/`](services/) and is described by a
|
||||
`metadata.json` file (plus any extra files the service needs, such as a `Caddyfile`). The
|
||||
[`installer/`](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`](services/allprox) — reverse proxy; protected routes use Caddy `forward_auth` to Authelia.
|
||||
- [`authelia`](services/authelia) — the SSO server (login portal, OIDC, 2FA) that authenticates users against…
|
||||
- [`lldap`](services/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`:
|
||||
|
||||
```bash
|
||||
bun run src/index.ts install lldap authelia allprox
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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`](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:
|
||||
|
||||
```bash
|
||||
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](docs/metadata-schema.json) — see [`services/README.md`](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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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`](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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue