- multistreaming (new): RTMP ingest + multi-platform fan-out with pluggable providers (Twitch/YouTube/Kick/custom), zero-knowledge key vaults, Authelia OIDC auth, shared rooms with editor/streamer roles, single-use invites, per-account streaming grants, and scenes & composition (grid/PiP layouts, text/image overlays, per-output audio routing). - installer: support Dockerfile build in metadata (not just image) and RSA key generation for the Authelia OIDC JWKS. - authelia: add OIDC provider with portainer + multistreaming clients (public + PKCE). - services: remove allprox; add nginx-proxy-manager and portainer; update lldap; regenerate catalog.
161 lines
6.4 KiB
Markdown
161 lines
6.4 KiB
Markdown
# services
|
|
|
|
One folder per service. Each folder must contain a `metadata.json` describing the service
|
|
(including the Docker Compose definition used to deploy it). The folder may also contain any extra
|
|
files the service needs — a config file, a `Dockerfile`, static assets — which the installer copies
|
|
into the deploy directory.
|
|
|
|
## Folder conventions
|
|
|
|
- The folder name **must** equal the service `id` in `metadata.json` (lowercase kebab-case).
|
|
- Only folders that contain a valid `metadata.json` are treated as services by the installer.
|
|
- After adding, editing, or removing a service, regenerate the index:
|
|
|
|
```bash
|
|
cd installer
|
|
bun run catalog
|
|
```
|
|
|
|
This rewrites [`catalog.json`](catalog.json), which the installer uses as a one-request listing.
|
|
|
|
## Extra files
|
|
|
|
A service folder can contain files beyond `metadata.json` — for example the `authelia` service ships
|
|
a `configuration.yml` and a `users_database.yml`, while the `multistreaming` service ships a `Dockerfile`,
|
|
`package.json`, `src/`, and `web/` for its `build`. On install/update the installer copies the whole
|
|
folder (except `metadata.json`) into `~/.homelab/services/<id>/`, preserving subdirectories.
|
|
|
|
Reference those files from `compose.volumes` with **relative** paths:
|
|
|
|
```json
|
|
"volumes": [
|
|
"./configuration.yml:/config/configuration.yml:ro",
|
|
"./users_database.yml:/config/users_database.yml:ro"
|
|
]
|
|
```
|
|
|
|
Because the generated `docker-compose.yml` lives in the same directory, `docker compose` resolves
|
|
the `./...` paths against it — and, for `build` services, the `.` build context is that same
|
|
directory, so the Dockerfile and source files are found automatically.
|
|
|
|
## Shared networks
|
|
|
|
Services that need to talk to each other (e.g. `nginx-proxy-manager` → `authelia` → `lldap`) join an external
|
|
Docker network. Declare it at the top level of `metadata.json` and attach the service to it:
|
|
|
|
```json
|
|
"networks": { "homelab": { "external": true } },
|
|
"compose": {
|
|
"networks": ["homelab"]
|
|
}
|
|
```
|
|
|
|
The installer creates the external network automatically (if it doesn't already exist) before
|
|
running `docker compose up`.
|
|
|
|
## `metadata.json` reference
|
|
|
|
| Field | Required | Type | Description |
|
|
| --- | --- | --- | --- |
|
|
| `id` | ✅ | string | Unique kebab-case id, equal to the folder name. |
|
|
| `name` | ✅ | string | Human-readable name shown in the TUI. |
|
|
| `description` | ✅ | string | Short description. |
|
|
| `version` | ✅ | string | Version string for change detection on update. |
|
|
| `compose` | ✅ | object | A Docker Compose **service** definition (`image`, `ports`, `volumes`, `environment`, …). The installer wraps it in a generated `docker-compose.yml`. |
|
|
| `volumes` | — | object | Optional top-level named volumes to declare. |
|
|
| `networks` | — | object | Optional top-level networks to declare. |
|
|
| `env` | — | array | Variables the installer resolves for you (see below). |
|
|
| `category` | — | string | Grouping shown as a hint in the TUI. |
|
|
| `tags` | — | string[] | Free-form tags. |
|
|
| `icon` | — | string | URL to an icon. |
|
|
| `author` | — | string | Upstream author. |
|
|
| `license` | — | string | License of the deployed software. |
|
|
| `homepage` | — | string | Project homepage URL. |
|
|
| `documentation` | — | string | Documentation URL. |
|
|
| `dependsOn` | — | string[] | Ids of services that should be installed first (informational). |
|
|
| `notes` | — | string | Free-form notes shown by `info`. |
|
|
|
|
A machine-readable JSON Schema is available at [`docs/metadata-schema.json`](../docs/metadata-schema.json).
|
|
|
|
### `compose` (the service definition)
|
|
|
|
This object is the value you would normally put under a service key in `docker-compose.yml`. It must
|
|
set **either** `image` (pull a prebuilt image) **or** `build` (build from a Dockerfile shipped in the
|
|
service folder). Pull example:
|
|
|
|
```json
|
|
{
|
|
"image": "ghcr.io/example/myapp:1.0.0",
|
|
"container_name": "myapp",
|
|
"restart": "unless-stopped",
|
|
"ports": ["8080:8080"],
|
|
"volumes": ["myapp_data:/data"],
|
|
"environment": ["TZ=${TZ}"]
|
|
}
|
|
```
|
|
|
|
Build example (the Dockerfile, source files, and `.dockerignore` live in the service folder and are
|
|
copied into the deploy directory, so the build context is `.`):
|
|
|
|
```json
|
|
{
|
|
"build": { "context": ".", "dockerfile": "Dockerfile" },
|
|
"container_name": "myapp",
|
|
"restart": "unless-stopped",
|
|
"ports": ["8080:8080"],
|
|
"volumes": ["myapp_data:/data"],
|
|
"environment": ["TZ=${TZ}"]
|
|
}
|
|
```
|
|
|
|
The installer turns either into a `docker-compose.yml` service. On install it runs
|
|
`docker compose build` (for `build` services) or pulls the image on update; then `docker compose up -d`
|
|
brings the container up. For image-based services, pin the tag so updates are predictable — the
|
|
installer compares `version` to decide whether an update is available.
|
|
|
|
### `env` (interactive variables)
|
|
|
|
Each entry describes a variable the installer should collect (and write to `.env`):
|
|
|
|
```json
|
|
{
|
|
"name": "WEBPASSWORD",
|
|
"label": "Web admin password",
|
|
"description": "Password for the web UI",
|
|
"default": "change-me",
|
|
"required": true,
|
|
"secret": true,
|
|
"options": []
|
|
}
|
|
```
|
|
|
|
- `name` (required) — the variable name. Reference it in `compose` as `${NAME}`.
|
|
- `label` / `description` — shown when prompting.
|
|
- `default` — used when the user accepts the default or runs non-interactively.
|
|
- `required` — a missing value is an error in non-interactive mode unless a `default` is set.
|
|
- `secret` — mask input at the prompt (e.g. passwords).
|
|
- `options` — if provided, the installer offers a fixed choice list instead of free text.
|
|
- `generate` — generate a random 64-char hex secret instead of prompting (for JWT/session secrets).
|
|
|
|
Docker Compose automatically reads the `.env` written next to the generated compose file, so
|
|
`${NAME}` references resolve at `docker compose up` time.
|
|
|
|
### `rsaKeys` (generated private keys)
|
|
|
|
For secrets that cannot be injected via environment variables — most notably Authelia's OIDC
|
|
signing key (`identity_providers.oidc.jwks.key`, which rejects `$file:`/`$env:` secret references) —
|
|
declare an RSA private key the installer generates into a file on first install:
|
|
|
|
```json
|
|
"rsaKeys": [
|
|
{ "name": "OIDC_JWKS_KEY", "path": "oidc-jwks.pem", "bits": 2048 }
|
|
]
|
|
```
|
|
|
|
- `name` (required) — human label.
|
|
- `path` (required) — file written into the service's deploy directory, referenced by a relative
|
|
`./path:...` bind mount in `compose.volumes`.
|
|
- `bits` — RSA modulus size (default 2048).
|
|
|
|
The key is only created if the file is absent, so updating a service never rotates the key and
|
|
invalidates existing sessions.
|