Skip to content

Onboarding

Goal

The onboarding flow exists to stop new apps from requiring a manual sequence of shell edits, nginx templating, and job creation.

The shared helper is /home/steam/automation/onboard-managed-app.sh.

It can:

  • create or update /home/steam/automation/apps/<app-id>.conf
  • optionally clone a repo into the requested app directory
  • load deployment defaults from a repo-local JSON manifest
  • generate and enable an nginx site config
  • validate and reload the host nginx service automatically after managed site changes
  • create or update deploy-<app-id> in Jenkins
  • print a GitHub webhook URL when webhook deploy is enabled

Jenkins path

Use the onboard-managed-app Jenkins job when you want the dashboard to perform onboarding.

In the Jenkins UI this is a parameterized pipeline job, so the normal flow is:

  1. Open onboard-managed-app.
  2. Click Build with Parameters.
  3. Fill in the form fields.
  4. Run the job.

The form already exists today. It is generated from the job's pipeline parameters in Jenkins Configuration as Code.

Repo-driven onboarding

For your own apps, the better long-term path is to keep a small onboarding manifest inside the repo and let Jenkins read that instead of retyping the same settings every time.

The onboarding job now supports a repo-local manifest file through APP_MANIFEST.

Default manifest path:

  • .ilgaming-onboard.json

If the file exists inside the cloned repo or the existing APP_DIR, onboarding loads it and uses it as the default source of truth for the app shape.

The Jenkins form still exists, but it becomes an override layer rather than the place where you define everything from scratch.

Example manifest

{
    "APP_NAME": "Holiday Card V2",
    "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": "holiday-card.ilgaming.xyz",
    "ENABLE_DEPLOY_JOB": true,
    "ENABLE_GIT_WEBHOOK": true,
    "WEBHOOK_BRANCH": "main",
    "NOTES": "Seasonal app deployed from the main branch"
}

In that model, the Jenkins operator often only needs to provide:

  • GIT_REPO_URL for a cloneable repo, or APP_DIR for a pre-cloned private repo
  • optionally APP_ID if you do not want it derived from the repo or folder name
  • any one-off overrides for that specific onboarding run

Manifest precedence

The precedence is:

  1. explicit values from the Jenkins form when they differ from the standard defaults
  2. values from .ilgaming-onboard.json
  3. derived defaults from the repo URL, app name, app directory, and compose file

That means the manifest is ideal for project-level conventions, while the form still lets you override details on a one-off run.

Minimum fields for a standard app

For most new apps, you do not need every field in the form. The usual minimum set is:

  • APP_ID: stable machine name, for example my-new-app. If blank, onboarding now tries to derive it from GIT_REPO_URL or APP_NAME.
  • APP_NAME: human-friendly name. If blank, onboarding defaults it to APP_ID.
  • APP_DIR: target path on the box, usually under /home/steam/apps/.... If left at the placeholder, onboarding defaults it to /home/steam/apps/<app-id>.
  • GIT_REPO_URL: only for repo-backed apps that Jenkins should clone
  • APP_MANIFEST: leave this at .ilgaming-onboard.json unless the repo uses a different manifest filename
  • GIT_BRANCH: usually main
  • DEPLOY_MODE: compose-build for your own repo, compose-image for upstream images
  • COMPOSE_FILE: usually docker-compose.yml. If left at the default, onboarding also checks common alternatives like compose.yml, compose.yaml, docker/docker-compose.yml, and docker/compose.yml.
  • HEALTHCHECK_TYPE: usually http if the app exposes a health endpoint
  • HEALTHCHECK_TARGET: for example http://127.0.0.1:4010/health
  • ENABLE_NGINX: whether Jenkins should generate a vhost
  • NGINX_SERVER_NAME: public hostname, for example newapp.ilgaming.xyz
  • NGINX_PROXY_PORT: local app port nginx should proxy to. If blank, onboarding now tries to infer it from the compose file and otherwise stops with a suggested free host port.
  • ENABLE_DEPLOY_JOB: usually true
  • ENABLE_GIT_WEBHOOK: true if pushes to the tracked branch should trigger deploys
  • DEPLOY_AFTER_ONBOARD: true if you want Jenkins to do the first deploy immediately

What the form creates

When the job succeeds, it can create all of the following from one run:

  • the managed app contract in /home/steam/automation/apps/<app-id>.conf
  • the nginx vhost in /etc/nginx/sites-available
  • the enabled nginx include in /etc/nginx/sites-enabled
  • the per-app Jenkins job deploy-<app-id>
  • the optional webhook URL for GitHub if webhook deploys are enabled

During onboarding, the job output now also prints any resolved defaults such as:

  • derived APP_ID
  • derived APP_DIR
  • derived COMPOSE_FILE
  • derived COMPOSE_PROJECT_NAME
  • inferred NGINX_PROXY_PORT
  • manifest-sourced values such as MANIFEST_APP_NAME or MANIFEST_NGINX_SERVER_NAME

Generated nginx configs remain host-managed files under /etc/nginx, so they will still be root-owned on the box. The intended editing path is to rerun onboarding or update the automation inputs, not to hand-edit the generated file from an unprivileged editor session.

For Jenkins, the supported path is not broad sudo. Onboarding now stages the rendered vhost in the automation workspace and installs it onto the host through /home/steam/automation/apply-host-nginx-site.sh, then validates and reloads nginx through /home/steam/automation/reload-host-nginx.sh.

Recommended values for a git-backed app:

  • DEPLOY_MODE=compose-build
  • GIT_BRANCH=main
  • AUTO_GIT_PULL=true
  • ENABLE_DEPLOY_JOB=true
  • ENABLE_GIT_WEBHOOK=true
  • HEALTHCHECK_TYPE=http when the app exposes a real endpoint

Private repo note:

  • Jenkins can only clone a private repo if the URL is reachable with credentials from the Jenkins environment.
  • If the repo is private and Jenkins cannot authenticate, clone it onto the host first, set APP_DIR to that local path, and leave GIT_REPO_URL empty.
  • That private-repo flow works especially well with .ilgaming-onboard.json, because the local checkout can carry the onboarding defaults with it.
  • The preferred long-term fix is an SSH deploy key mounted into the Jenkins container. Generate an ed25519 keypair for Jenkins, add the public key to GitHub as a read-only deploy key or machine-user key, write github.com into known_hosts, rebuild Jenkins, and use an SSH repo URL such as [email protected]:KPInc425/holiday-card-v2.git.

Recommended values for an image-backed app:

  • DEPLOY_MODE=compose-image
  • AUTO_GIT_PULL=false
  • IMAGE_AUTO_PULL=true
  • leave GIT_REPO_URL empty if the compose files are already present on the box
  • ENABLE_DEPLOY_JOB=true

NeonHustleActivity example

NeonHustleActivity is the reference example for a locally built, webhook-driven app:

  • APP_ID=neonhustle-activity
  • APP_NAME=NeonHustleActivity
  • APP_DIR=/home/steam/apps/NeonHustleActivity
  • COMPOSE_FILE=docker-compose.yml
  • COMPOSE_PROJECT_NAME=neonhustle-activity
  • GIT_REPO_URL=https://github.com/KPInc425/NeonHustleActivity.git
  • GIT_BRANCH=main
  • DEPLOY_MODE=compose-build
  • HEALTHCHECK_TYPE=http
  • HEALTHCHECK_TARGET=http://127.0.0.1:8780/health
  • ENABLE_DEPLOY_JOB=true
  • ENABLE_GIT_WEBHOOK=true

Nginx did not need to be regenerated for this app because neonhustle.ilgaming.xyz was already present and mapped to port 8780.

Caveats

  • The helper now validates nginx config and reloads host nginx automatically through /home/steam/automation/reload-host-nginx.sh unless AUTO_RELOAD_NGINX=false is set in the environment.
  • App contracts are source-controlled files; generated deploy jobs are operational Jenkins state and can be recreated with the helper if needed.
  • When an app has local git changes, deployctl.sh refuses to auto-pull until the working tree is clean.
  • Documentation hosting is separate from authoring. The live docs site is served by the automation-docs compose stack on 127.0.0.1:8086 and proxied at docs.ilgaming.xyz.
  • The form is powerful but still fairly operator-oriented. App-specific setup like database seeding, Keycloak client creation, or unusual migration steps still need separate runbooks or follow-up automation.

For a deeper guide on how to author .ilgaming-onboard.json, including an LLM-oriented evaluation flow, see Manifest Authoring.