From 83321fa330acc5c95a67386792dfaa40c01c8550 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Sat, 3 Oct 2026 12:05:56 +0700 Subject: [PATCH] refactor(renderer)!: prefix every renderer env var with RENDERER_ The renderer's settings now read RENDERER_HOST, RENDERER_PORT, RENDERER_MAX_CONCURRENT_RENDERS, RENDERER_RENDER_TIMEOUT_MS, RENDERER_MAX_OPTIONS, and RENDERER_MAX_OPTION_CHARS, so they read as renderer settings and cannot clash with the bot's variables, which Coolify injects into every service. NODE_ENV keeps its standard name. BREAKING CHANGE: the unprefixed HOST, PORT, MAX_CONCURRENT_RENDERS, RENDER_TIMEOUT_MS, MAX_OPTIONS, and MAX_OPTION_CHARS are no longer read by the renderer. --- compose.yml | 14 ++++++++------ docs/deploy-coolify-selfhosted.md | 5 +++-- renderer/.env.example | 12 ++++++------ renderer/README.md | 6 +++--- renderer/docs/deployment.md | 16 ++++++++-------- renderer/src/config.js | 12 ++++++------ renderer/test/config.test.js | 2 +- 7 files changed, 35 insertions(+), 32 deletions(-) diff --git a/compose.yml b/compose.yml index 0fdeb4e..112d08d 100644 --- a/compose.yml +++ b/compose.yml @@ -57,12 +57,14 @@ services: restart: unless-stopped environment: NODE_ENV: production - HOST: 0.0.0.0 - PORT: "3000" - MAX_CONCURRENT_RENDERS: ${MAX_CONCURRENT_RENDERS:-1} - RENDER_TIMEOUT_MS: ${RENDER_TIMEOUT_MS:-15000} - MAX_OPTIONS: ${MAX_OPTIONS:-32} - MAX_OPTION_CHARS: ${MAX_OPTION_CHARS:-40} + # Every renderer setting carries the RENDERER_ prefix so it cannot clash + # with the bot's variables, which Coolify also injects into this service. + RENDERER_HOST: 0.0.0.0 + RENDERER_PORT: "3000" # keep in sync with the bot's RENDERER_URL and the healthcheck + RENDERER_MAX_CONCURRENT_RENDERS: ${RENDERER_MAX_CONCURRENT_RENDERS:-1} + RENDERER_RENDER_TIMEOUT_MS: ${RENDERER_RENDER_TIMEOUT_MS:-15000} + RENDERER_MAX_OPTIONS: ${RENDERER_MAX_OPTIONS:-32} + RENDERER_MAX_OPTION_CHARS: ${RENDERER_MAX_OPTION_CHARS:-40} expose: - "3000" healthcheck: diff --git a/docs/deploy-coolify-selfhosted.md b/docs/deploy-coolify-selfhosted.md index c82d984..5ff605e 100644 --- a/docs/deploy-coolify-selfhosted.md +++ b/docs/deploy-coolify-selfhosted.md @@ -60,8 +60,9 @@ compose network, so it needs no domain, publishes no port, and takes no auth token. Its API is unauthenticated, so never publish a port or attach a domain to it. -Renderer tuning (`MAX_CONCURRENT_RENDERS`, `RENDER_TIMEOUT_MS`, `MAX_OPTIONS`, -`MAX_OPTION_CHARS`) can be set in Coolify too; the defaults are in +Renderer tuning (`RENDERER_MAX_CONCURRENT_RENDERS`, +`RENDERER_RENDER_TIMEOUT_MS`, `RENDERER_MAX_OPTIONS`, +`RENDERER_MAX_OPTION_CHARS`) can be set in Coolify too; the defaults are in [`renderer/docs/deployment.md`](../renderer/docs/deployment.md). Give the host 1-2 GB of headroom for the renderer's Chrome. diff --git a/renderer/.env.example b/renderer/.env.example index c19d09f..2e9fb45 100644 --- a/renderer/.env.example +++ b/renderer/.env.example @@ -1,8 +1,8 @@ -PORT=3000 -HOST=0.0.0.0 +RENDERER_PORT=3000 +RENDERER_HOST=0.0.0.0 NODE_ENV=production -MAX_CONCURRENT_RENDERS=1 +RENDERER_MAX_CONCURRENT_RENDERS=1 # Remotion browser timeout floor is 7000ms; lower values are raised to 7000. -RENDER_TIMEOUT_MS=15000 -MAX_OPTIONS=32 -MAX_OPTION_CHARS=40 +RENDERER_RENDER_TIMEOUT_MS=15000 +RENDERER_MAX_OPTIONS=32 +RENDERER_MAX_OPTION_CHARS=40 diff --git a/renderer/README.md b/renderer/README.md index c125533..f6f0510 100644 --- a/renderer/README.md +++ b/renderer/README.md @@ -67,7 +67,7 @@ result and its rarity — the service only draws it. Response is a silent H.264 `video/mp4` (Telegram plays it as an animation) with `X-Gacha-Rarity` and `X-Render-Duration-Ms` headers. All routes share the -`MAX_CONCURRENT_RENDERS` slots. No game assets are used. +`RENDERER_MAX_CONCURRENT_RENDERS` slots. No game assets are used. pack-cards animates on the browser clock, so the wish does not use Remotion compositions. `src/render/render-gacha.js` keeps one headless Chrome per @@ -182,6 +182,6 @@ docker run --rm -p 3000:3000 miti99bot-renderer ``` Recommended starting resources: 1-2 vCPU and 1-2 GB RAM, with -`MAX_CONCURRENT_RENDERS=1`. `RENDER_TIMEOUT_MS` defaults to `15000` and is -raised to Remotion's `7000ms` browser timeout floor when configured lower. +`RENDERER_MAX_CONCURRENT_RENDERS=1`. `RENDERER_RENDER_TIMEOUT_MS` defaults to +`15000` and is raised to Remotion's `7000ms` browser timeout floor when configured lower. The API has no authentication; publish its port only on a trusted network. diff --git a/renderer/docs/deployment.md b/renderer/docs/deployment.md index dd7196c..bcd3f28 100644 --- a/renderer/docs/deployment.md +++ b/renderer/docs/deployment.md @@ -28,15 +28,15 @@ Avoid for v1: ## Runtime -Required env vars: +Env vars, all optional (defaults shown): ```sh -PORT=3000 -HOST=0.0.0.0 -MAX_CONCURRENT_RENDERS=1 -RENDER_TIMEOUT_MS=15000 -MAX_OPTIONS=32 -MAX_OPTION_CHARS=40 +RENDERER_PORT=3000 +RENDERER_HOST=0.0.0.0 +RENDERER_MAX_CONCURRENT_RENDERS=1 +RENDERER_RENDER_TIMEOUT_MS=15000 +RENDERER_MAX_OPTIONS=32 +RENDERER_MAX_OPTION_CHARS=40 ``` The root `compose.yml` forwards the tuning values with `${VAR:-default}` @@ -50,7 +50,7 @@ including `libnspr4` and `libnss3`. Prefer Docker for consistent verification. The Docker image runs `npm run browser:ensure` during build so production requests do not need to download Chrome Headless Shell on first render. -`RENDER_TIMEOUT_MS` is a total render timeout. Values below `7000` are raised to +`RENDERER_RENDER_TIMEOUT_MS` is a total render timeout. Values below `7000` are raised to `7000` because Remotion's browser timeout has that minimum. ## Health diff --git a/renderer/src/config.js b/renderer/src/config.js index 3ecf93b..4c72922 100644 --- a/renderer/src/config.js +++ b/renderer/src/config.js @@ -30,14 +30,14 @@ const parsePositiveInt = (value, fallback) => { */ export const loadConfig = (env = process.env) => { return { - host: env.HOST || '0.0.0.0', - port: parsePositiveInt(env.PORT, 3000), - maxConcurrentRenders: parsePositiveInt(env.MAX_CONCURRENT_RENDERS, 1), + host: env.RENDERER_HOST || '0.0.0.0', + port: parsePositiveInt(env.RENDERER_PORT, 3000), + maxConcurrentRenders: parsePositiveInt(env.RENDERER_MAX_CONCURRENT_RENDERS, 1), renderTimeoutMs: Math.max( minRenderTimeoutMs, - parsePositiveInt(env.RENDER_TIMEOUT_MS, 15000), + parsePositiveInt(env.RENDERER_RENDER_TIMEOUT_MS, 15000), ), - maxOptions: parsePositiveInt(env.MAX_OPTIONS, 32), - maxOptionChars: parsePositiveInt(env.MAX_OPTION_CHARS, 40), + maxOptions: parsePositiveInt(env.RENDERER_MAX_OPTIONS, 32), + maxOptionChars: parsePositiveInt(env.RENDERER_MAX_OPTION_CHARS, 40), }; }; diff --git a/renderer/test/config.test.js b/renderer/test/config.test.js index f586ce1..42375d9 100644 --- a/renderer/test/config.test.js +++ b/renderer/test/config.test.js @@ -3,7 +3,7 @@ import {loadConfig, minRenderTimeoutMs} from '../src/config.js'; describe('loadConfig', () => { test('keeps render timeout compatible with Remotion browser timeout limits', () => { - const config = loadConfig({RENDER_TIMEOUT_MS: '500'}); + const config = loadConfig({RENDERER_RENDER_TIMEOUT_MS: '500'}); expect(config.renderTimeoutMs).toBe(minRenderTimeoutMs); });