feat: make the three-runner compose a Coolify service - #10
Closed
azlekov wants to merge 1 commit into
Closed
Conversation
Deploys docker-compose.yml as one Coolify resource running all three X64
runners, and fixes two upstream footguns found while verifying the file
against myoung34's entrypoint.
Coolify contract:
- APP_ID / APP_PRIVATE_KEY / APP_LOGIN use ${VAR:?} so a half-filled
Environment Variables tab blocks the deploy instead of crash-looping;
the optional vars keep ${VAR:-default} so they stay UI-editable.
- SERVICE_FQDN_* / SERVICE_URL_* / SERVICE_PASSWORD_* magic variables are
deliberately unused: no port, no domain, and the only secret is the
GitHub App key the operator supplies.
- Per-service healthcheck on Runner.Listener so Coolify can tell a
registered runner from a crash-looping one. Exec form on purpose: under
CMD-SHELL the wrapping sh -c carries the pattern in its own cmdline and
pgrep -f matches itself, reporting healthy forever.
- json-file log rotation, stop_grace_period for the deregister trap, and
pull_policy: always for the floating tag.
Behaviour fixes:
- EPHEMERAL: "false" was enabling --ephemeral. The entrypoint tests it
with [ -n ... ], so any non-empty value turns the flag on, which tore
each runner down after every job and contradicted the file's own
comment. EPHEMERAL is no longer passed at all.
- DISABLE_AUTO_UPDATE had the same trap; it is hardcoded to "true" and
hidden from the UI so nobody can type "false" and get the opposite.
- Each service pins RUNNER_NAME to ${RUNNER_NAME_PREFIX}-N. Coolify
recreates containers on every redeploy and config.sh runs with
--replace, so the org runner list keeps exactly three entries instead
of collecting an offline runner per redeploy.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3cupBSAf2XKiDu1AYPZ3R
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deploys
docker-compose.ymlas one Coolify resource running all three X64 runners, and fixes two upstream footguns found while verifying the file againstmyoung34'sentrypoint.sh.Coolify contract
APP_ID/APP_PRIVATE_KEY/APP_LOGINuse${VAR:?}, so a half-filled Environment Variables tab blocks the deploy instead of crash-looping the containers. Optional vars keep${VAR:-default}so they stay editable in the UI.SERVICE_FQDN_*/SERVICE_URL_*/SERVICE_PASSWORD_*magic variables are deliberately unused: the runners publish no port, need no domain, and their only secret is the GitHub App key the operator supplies. Nothing here needs generating — forcing a generated value in would only put 32 random characters into the runner names. Documented in the README so the omission reads as a decision, not an oversight.healthcheckonRunner.Listener, so Coolify can tell a registered runner from a crash-looping one. Exec form on purpose — underCMD-SHELLthe wrappingsh -ccarries the pattern in its own command line andpgrep -fmatches itself, reporting healthy forever.json-filelog rotation,stop_grace_period: 30sfor the entrypoint's deregister trap, andpull_policy: alwaysfor the floating tag.Behaviour fixes
Both come from the upstream entrypoint testing these with
[ -n ... ]rather than comparing to"true":EPHEMERAL: "false"was enabling--ephemeral. Any non-empty value turns the flag on, so the three runners were being torn down after every job — the opposite of what the file's own comment and the README claimed, and enough to make the new health check flap.EPHEMERALis no longer passed at all.DISABLE_AUTO_UPDATEhad the same trap. It is now hardcoded to"true"and hidden from the Coolify UI, matching the previous effective behaviour while removing the chance of typingfalseand getting the opposite. A self-updating runner writes into the container layer and loses the update on the next redeploy anyway.Stable runner names
Each service pins
RUNNER_NAMEto${RUNNER_NAME_PREFIX}-1…-3instead of using the upstream random suffix. Coolify recreates containers on every redeploy andconfig.shruns with--replace, so the org runner list keeps exactly three entries instead of collecting an offline runner per redeploy. Running the stack on a second host against the same org means changingRUNNER_NAME_PREFIXthere — documented in both the README and.env.example.Validation
docker compose configparses cleanly (merge keys resolve, all 18 named volumes are declared and mounted exactly once).required variable APP_ID is missing a value.entrypoint.shonmaster:--replaceis always passed (line 185),RUNNER_NAMEwins over the random suffix, andRUN_AS_ROOTdefaults totrue, so the/root/*cache mounts stay correct.Not deployed to a live Coolify instance from here — worth one redeploy to confirm the health check goes green before merging.
🤖 Generated with Claude Code
https://claude.ai/code/session_01T3cupBSAf2XKiDu1AYPZ3R
Generated by Claude Code