Skip to content

Manifest Authoring

Purpose

This page is the project-facing guide for writing .ilgaming-onboard.json.

It is intended for both:

  • human operators preparing a new repo for onboarding
  • another LLM that needs explicit rules for how to inspect a repo and produce a correct manifest

The goal is to describe the app once in the repo, then let onboarding treat the manifest as the project-level source of truth.

What the manifest is for

The manifest should describe the deployment shape of the app, not every one-off operator action.

Good manifest content:

  • compose file location
  • deploy mode
  • health check strategy and target
  • public hostname
  • nginx proxy port
  • whether a deploy job and webhook should exist
  • stable notes about the app

Bad manifest content:

  • secrets
  • API keys
  • passwords
  • machine-specific temporary overrides
  • values that only make sense for one debugging run

Canonical file name

Default path:

  • .ilgaming-onboard.json

Onboarding uses that path by default, so repos should prefer it unless there is a strong reason to use a different manifest filename.

Minimal template

{
  "APP_NAME": "Example App",
  "DEPLOY_MODE": "compose-build",
  "COMPOSE_FILE": "docker-compose.yml",
  "HEALTHCHECK_TYPE": "http",
  "HEALTHCHECK_TARGET": "http://127.0.0.1:8400/health",
  "ENABLE_NGINX": true,
  "NGINX_SERVER_NAME": "example.ilgaming.xyz",
  "NGINX_PROXY_PORT": "8400",
  "ENABLE_DEPLOY_JOB": true,
  "ENABLE_GIT_WEBHOOK": true,
  "WEBHOOK_BRANCH": "main",
  "NOTES": "Short stable description of the service"
}

LLM Workflow

When another LLM is asked to fill this manifest, it should follow this order.

1. Determine whether the repo is app-source or host-stack

Use compose-build when the repo builds the application image from source.

Signals:

  • compose service contains build:
  • repo has app source, package files, Dockerfile, migrations, etc.

Use compose-image when the repo is mainly a host stack that runs prebuilt upstream images.

Signals:

  • compose file mostly references image: values
  • repo is mostly config, env files, and runtime wiring

2. Locate the compose file relative to repo root

The manifest value must be relative to the repo root, not relative to the compose file itself.

Common values:

  • docker-compose.yml
  • compose.yml
  • docker/docker-compose.yml
  • docker/compose.yml

If the compose file lives under docker/, set:

  • COMPOSE_FILE: docker/docker-compose.yml

Do not shorten it to docker-compose.yml unless that file really exists at repo root.

3. Identify the app-facing host port

This is the most important judgment call.

The LLM must find the port that serves the user-facing app, not the database, cache, queue, or internal admin service.

Rules:

  • Prefer the port on the service that serves HTTP traffic to end users.
  • Ignore Postgres, MySQL, Redis, MongoDB, and similar backing-service ports for nginx.
  • If multiple public app ports exist, choose the main web entrypoint for NGINX_PROXY_PORT.
  • If the compose file only exposes container ports internally and not to the host yet, the manifest should use the intended host port and the repo should be updated to bind it.

Examples:

  • 5432:5432 on a Postgres service is not the nginx port.
  • 8462:3000 on a Next.js app means NGINX_PROXY_PORT should be 8462.

4. Identify the health check target

Use a real app endpoint, not a guessed one.

Preferred order:

  • explicit /health or /api/health route in the app
  • existing README docs that name the health endpoint
  • framework route implementation visible in the source tree

Rules:

  • For HEALTHCHECK_TYPE=http, the target should use 127.0.0.1 and the chosen host app port.
  • Do not point the health check at the public domain.
  • Do not point it at a database or internal service.

Examples:

  • http://127.0.0.1:8462/api/health
  • http://127.0.0.1:8780/health

5. Decide whether nginx should be enabled

Set ENABLE_NGINX=true when the app is meant to be reached via a public hostname on this box.

Set ENABLE_NGINX=false when:

  • the service is internal-only
  • another existing reverse proxy path already fronts it and should not be replaced
  • the app is not HTTP-facing

When ENABLE_NGINX=true, the manifest should normally also include:

  • NGINX_SERVER_NAME
  • NGINX_PROXY_PORT

6. Decide whether deploy job and webhook should exist

For a normal git-backed app:

  • ENABLE_DEPLOY_JOB=true
  • ENABLE_GIT_WEBHOOK=true
  • WEBHOOK_BRANCH=main unless the tracked branch is something else

For a manually managed or experimental app, disable webhook deploys.

7. Keep secrets and environment out of the manifest

Do not place these in .ilgaming-onboard.json:

  • AUTH_SECRET
  • database passwords
  • Keycloak client secrets
  • API tokens
  • S3 credentials

Those belong in the app runtime environment, not the onboarding manifest.

Field Reference

Usually include

  • APP_NAME
  • DEPLOY_MODE
  • COMPOSE_FILE
  • HEALTHCHECK_TYPE
  • HEALTHCHECK_TARGET
  • ENABLE_NGINX
  • NGINX_SERVER_NAME
  • NGINX_PROXY_PORT
  • ENABLE_DEPLOY_JOB
  • ENABLE_GIT_WEBHOOK
  • WEBHOOK_BRANCH
  • NOTES

Usually omit unless needed

  • APP_ID : onboarding can derive it from the repo or folder name.
  • APP_DIR : onboarding can derive it from APP_ID.
  • COMPOSE_PROJECT_NAME : onboarding can derive it from APP_ID.
  • GIT_BRANCH : omit unless it is not main.

Example: App Under docker/

{
  "APP_NAME": "Holiday Card V2",
  "DEPLOY_MODE": "compose-build",
  "COMPOSE_FILE": "docker/docker-compose.yml",
  "HEALTHCHECK_TYPE": "http",
  "HEALTHCHECK_TARGET": "http://127.0.0.1:8462/api/health",
  "ENABLE_NGINX": true,
  "NGINX_SERVER_NAME": "holidaycards.ilgaming.xyz",
  "NGINX_PROXY_PORT": "8462",
  "ENABLE_DEPLOY_JOB": true,
  "ENABLE_GIT_WEBHOOK": true,
  "WEBHOOK_BRANCH": "main",
  "NOTES": "Seasonal holiday card building app"
}

Why this is correct:

  • the compose file lives under docker/
  • the app listens on host port 8462
  • the health route is /api/health
  • Postgres is an internal dependency and must not be used for nginx proxying

Example: Hosted Image Stack

{
  "APP_NAME": "Example Hosted App",
  "DEPLOY_MODE": "compose-image",
  "COMPOSE_FILE": "docker-compose.yml",
  "HEALTHCHECK_TYPE": "http",
  "HEALTHCHECK_TARGET": "http://127.0.0.1:8510/health",
  "ENABLE_NGINX": true,
  "NGINX_SERVER_NAME": "hosted-example.ilgaming.xyz",
  "NGINX_PROXY_PORT": "8510",
  "ENABLE_DEPLOY_JOB": true,
  "ENABLE_GIT_WEBHOOK": false,
  "NOTES": "Hosted image stack with local config"
}

Common Mistakes

  • Setting NGINX_PROXY_PORT to the database port because it appears first in the compose file.
  • Using docker-compose.yml when the real path is docker/docker-compose.yml.
  • Pointing HEALTHCHECK_TARGET at /health when the app actually exposes /api/health.
  • Putting secrets into the manifest.
  • Using the public domain in HEALTHCHECK_TARGET instead of 127.0.0.1.

Operational Notes

  • Onboarding can generate, validate, enable, and reload host nginx automatically.
  • The generated nginx file under /etc/nginx/sites-available is still a privileged host file and remains root-owned.
  • The intended source of truth for future changes is the repo manifest plus onboarding, not an unprivileged hand-edit of the generated nginx file.