repo/services
2026-09-11 00:08:59 +02:00
..
authelia Authelia: add storage encryption_key, drop deprecated jwt_secret and duplicate redirection url 2026-09-11 00:08:59 +02:00
forgejo Add forgejo (with shared postgres), docs/ideas; fix ENOTDIR in local catalog listing 2026-09-10 23:29:36 +02:00
lldap multistreaming: scenes/composition, installer build support, service updates 2026-09-02 21:18:25 +02:00
multistreaming multistreaming: fix scene font paths for Alpine, add session state notes 2026-09-02 23:30:21 +02:00
nginx-proxy-manager Installer: support Forgejo as catalog source; NPM dashboard bound to internal IP 2026-09-11 00:02:49 +02:00
portainer multistreaming: scenes/composition, installer build support, service updates 2026-09-02 21:18:25 +02:00
postgres Add forgejo (with shared postgres), docs/ideas; fix ENOTDIR in local catalog listing 2026-09-10 23:29:36 +02:00
catalog.json Add forgejo (with shared postgres), docs/ideas; fix ENOTDIR in local catalog listing 2026-09-10 23:29:36 +02:00
README.md multistreaming: scenes/composition, installer build support, service updates 2026-09-02 21:18:25 +02:00

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:

    cd installer
    bun run catalog
    

    This rewrites 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:

"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-managerauthelialldap) join an external Docker network. Declare it at the top level of metadata.json and attach the service to it:

"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.

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:

{
  "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 .):

{
  "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):

{
  "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:

"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.