Skip to content

feat(deploy): add Render blueprint, make Chromium optional in image - #1073

Open
Swaray10 wants to merge 1 commit into
rmyndharis:mainfrom
Swaray10:deploy/render-baileys
Open

feat(deploy): add Render blueprint, make Chromium optional in image#1073
Swaray10 wants to merge 1 commit into
rmyndharis:mainfrom
Swaray10:deploy/render-baileys

Conversation

@Swaray10

@Swaray10 Swaray10 commented Aug 5, 2026

Copy link
Copy Markdown

Description

Brief description of changes

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Checklist

  • Tests added/updated
  • Documentation updated
  • Lint passes
  • Self-reviewed

Screenshots (if applicable)

Related Issues

Closes #

@Swaray10

Swaray10 commented Aug 5, 2026

Copy link
Copy Markdown
Author

.

@rmyndharis

Copy link
Copy Markdown
Owner

Thanks for this, @Swaray10 — and welcome to the repo.

Straight answer up front: I'm not going to merge this as it stands. But there's a genuinely useful change buried in here, and I'd rather help you reshape it into something I can land than just close the tab. The detail below is meant to make a resubmission a short job rather than a guessing game.

What's right

I checked these rather than taking the comments at their word, and they hold up:

  • The default path is untouched. I expanded the apt-get install argument list from both main and your branch under /bin/sh: 24 packages on amd64, 26 on arm64, identical on both sides. Nothing in the repo passes the new build arg either — neither CI workflow nor either compose file sets build-args — so the published image is unaffected.
  • The Render mechanism is real. Render's Docker docs state it plainly: environment variables on a Docker-based service are translated into build arguments. You declared ARG INSTALL_CHROMIUM at production-stage scope, which is where both consumers live, so the wiring is correct.
  • A browserless image genuinely works for Baileys. Nothing in src/ ever stats or probes PUPPETEER_EXECUTABLE_PATH — its only consumer is configuration.ts:207, read at browser-launch time — so the dangling symlink is inert at boot and neither the health nor the infra-status controller mis-reports it.
  • The render.yaml prose is unusually well researched. The TRUSTED_PROXIES and CORS_ORIGINS passage in particular is accurate down to the spoofing trade-off, which is why leaving TRUSTED_PROXIES unset really is the right call there.

The build arg is the half worth keeping — but it's gating the wrong thing

This is the part I'd like to land, and it isn't Render-specific at all: it helps every Baileys-only operator on bare Docker, Compose, and the Helm chart.

I measured the published image on both architectures (compressed layer sizes, from the registry manifests):

Layer amd64 (822.3 MB total) arm64 (791.7 MB total)
apt-get install … 197.7 MB 338.0 MB — includes chromium
Chrome-for-Testing download 171.4 MB — (just an ln -s)

The browser cost sits in a different layer on each architecture. On amd64 it's the Chrome-for-Testing download; on arm64 it's the chromium package inside the apt layer — the ~140 MB difference between those two apt layers is essentially that package.

That points at a much smaller change than the one you wrote. Gate only these two things:

  1. the Chrome-for-Testing block at Dockerfile:146, and
  2. the $([ "$TARGETARCH" = arm64 ] && echo "chromium chromium-sandbox") on Dockerfile:79 — which already stands alone on its own line, so adding your flag to it costs nothing.

That's roughly a three-line diff, and it captures the bulk of the saving on both architectures.

What I'd leave alone is the collapse of the 17-package list into a multi-line quoted echo. That's the part with a real ongoing cost: this Dockerfile has changed 21 times in the last six months, and today a package add or removal is a one-line diff that I can eyeball. After this change it becomes a reflowed block, and a package accidentally left outside the quoted string wouldn't be caught by anything — there's no hadolint step and nothing builds the false path. If you think that half is worth keeping, I'd want an actual before/after docker image ls for it, because I couldn't find a measurement that justifies the reviewability trade.

Also, the ~400MB figure in the comment has no units and I couldn't reproduce it as written — worth restating with units once you've measured.

Two things the build-arg PR would need beyond the diff itself:

  • Reject unrecognised values. Only the exact string true keeps the browser today: True, 1, yes and an empty value all silently produce a browserless image, and the build stays green. That's a typo away from shipping something broken, which is exactly what the test -n "$chrome_path" guard next door exists to prevent.
  • Fail fast at runtime. A false image boots clean and reports healthy; the missing browser only surfaces at the first session start. That matters because docker-compose.yml forwards ENGINE_TYPE empty, so the app default is whatsapp-web.js — someone who builds false and runs standard Compose gets a broken default engine with no boot-time signal. A startup check (browser engine selected + executable path missing → refuse to boot with a clear message) turns a per-session mystery into a one-line diagnosis.
  • One CI arm that actually builds INSTALL_CHROMIUM=false (build-only, no push). Without it this path has no regression net at all.

Correctness issues in render.yaml

If the Render half comes back in any form, these need fixing — the first one is the important one:

  • The headline promise doesn't hold. The file says the disk means "redeploys reconnect silently from the stored credentials". AUTO_START_SESSIONS defaults to false (src/config/feature-flags.ts:33 is env.AUTO_START_SESSIONS === 'true') and the blueprint doesn't set it, so session.service.ts:142 returns before starting anything. The disk preserves the credentials, but nothing reconnects — every redeploy leaves sessions disconnected with no engine, and the operator has to start each one by hand. That's the entire stated justification for a mandatory, billed 5 GB disk, so it needs either AUTO_START_SESSIONS=true in the env list or a reworded claim.
  • API keys are in the wrong file. The inventory puts them in data/openwa.sqlite; they're on the main connection (auth.module.ts:14TypeOrmModule.forFeature([ApiKey], 'main')), i.e. data/main.sqlite. The line right below it already says so. Anyone planning a selective backup from that list would copy the wrong file.
  • The secret gate is oversold. assertNoDefaultSecretsInProduction rejects an empty value only for DATABASE_PASSWORD (Postgres) and the S3 keys; API_MASTER_KEY is rejected only when it's set to a known placeholder. This blueprint pins SQLite and local storage, so in this exact configuration that gate checks nothing at all — which makes "refuses to boot on empty secrets" and "a crash-loop is almost always this check" point an operator at the wrong suspect.
  • BASE_URL is missing, so the dashboard on a public Render deploy will advertise localhost as its API base.
  • Minor attribution slip: setGlobalPrefix lives in src/config/app-validation.ts, not main.ts. The path itself is right.

On shipping a Render blueprint at all

Separately from whether the file is correct — I don't think it belongs in the tree, at least not yet, and not at the root:

  • Nobody has asked for it. I went looking across issues and discussions and found no request for Render or a one-click PaaS deploy. That matters for a file whose only purpose is to be maintained.
  • Nothing would validate it. No workflow lints or deploys it, and no test would notice when it goes stale — and it will: a renamed env var, a new required setting, a new durable path under ./data, or a Dockerfile restructure all break it silently.
  • Placement. It would be the first vendor-specific PaaS descriptor at the repo root, which becomes the precedent every subsequent fly.toml / railway.json / app.json PR cites. Render doesn't require the file at the root, so deploy/render/ would at least be scoped — but honestly I think a "Deploy on Render" recipe in docs/10-devops-infrastructure.md is the better home, alongside the Helm section.

For reference, the shape I'd expect for platform work here is the one the Helm chart followed in #695: a feature request first so we can agree it's wanted, then the artifact in its own subdirectory, a line under CHANGELOG.md [Unreleased], and a short note in docs/. This PR touches two files and none of those.

A couple of process notes while we're here, both covered in CONTRIBUTING.md: the PR template is unfilled and Closes # is empty, and the commit body is blank — six months from now git log shows only the subject line, and the reasoning you clearly did have would be lost. The title itself is fine and Conventional Commits compliant.

If you'd like to resubmit

I'd very much welcome a PR containing just this:

  1. INSTALL_CHROMIUM gating only the Chrome-for-Testing block and the existing arm64 chromium conditional — apt list left as-is.
  2. A rejected-value check so an unrecognised value fails the build loudly.
  3. A runtime guard that refuses to boot when the browser engine is selected and the executable is missing.
  4. One build-only CI arm covering the false path.
  5. A CHANGELOG.md [Unreleased] line and a short note wherever the build args are described.

That's a change I'd be glad to have, and it stands on its own merits without any Render context.

If Render support is something you'd like to pursue afterwards, open a feature request describing your use case and we can talk about it there — the docs-recipe route is a much lower-maintenance way to get people deploying, and I'd happily review it.

Happy to look at a WIP or a rough draft before you polish anything.

@rmyndharis rmyndharis left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking the review state so this is visible from the PR list — the substance is in my comment above, and nothing here is new.

Short version: I'd like to see this split. The INSTALL_CHROMIUM build arg is worth landing on its own terms; the root render.yaml is the half I'm not taking. Happy to look again at a resubmission along the lines I sketched, and no rush on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants