Skip to content

Add Traefik for parallel environments#4086

Merged
backspace merged 52 commits intomainfrom
traefik-cs-10284
Mar 6, 2026
Merged

Add Traefik for parallel environments#4086
backspace merged 52 commits intomainfrom
traefik-cs-10284

Conversation

@backspace
Copy link
Contributor

@backspace backspace commented Feb 27, 2026

This adds a BOXEL_ENVIRONMENT “environment mode” that lets us start any number of Boxel environments with isolated host, realm server, database, Synapse instance, and AI bot. The environment will be empty with the standard development users (user/password).

screencast.2026-03-04.12-04-16.mp4

The video skips through some slow steps (pnpm install, host build), some future improvements would be helpful:

  • integrating with mise for task consolidation/rationalisation
  • helpers to copy seed realms that exercise a developer’s current focus
  • scripts to start and destroy environments from PR numbers

But even as is this will make it much easier to check out PRs for review, especially if your development environment is in a weird state (as mine has been through the @cardstack/catalog/@cardstack/base migration).

Try it out

Check out the branch, ideally while already having a full environment running elsewhere to experience true parallel environments.

Setup:

git worktree add ../parallel
ln -s "$(pwd)/packages/boxel-icons/dist" ../parallel/packages/boxel-icons/dist # skip freshly building boxel-icons, which is quite slow
cd ../parallel

pnpm install

Start host:

cd packages/host
BOXEL_ENVIRONMENT=parallel pnpm start

near the top of the output:

boxel-traefik
Traefik started. Dashboard at http://localhost:4230
[environment-mode] Starting ember serve on dynamic port 53796
[environment-mode] Will be accessible at http://host.parallel.localhost
[environment-mode] Registered host at host.parallel.localhost -> localhost:53796

http://host.parallel.localhost is where you’ll access the application.

Start realm-server (in another tab):

cd packages/realm-server
BOXEL_ENVIRONMENT=parallel SKIP_CATALOG=true pnpm start:all

Start ai-bot if you want:

cd packages/ai-bot
OPENROUTER_API_KEY=whatever BOXEL_ENVIRONMENT=parallel pnpm start:development

Bonus script

Try this if any processes are lingering and/or you want to drop the database for the branch:

./scripts/stop-branch.sh --drop-db

It also has a --dry-run to see what processes it would end.

Todos

  • custom domain instead of localhost? was suggested earlier but Puppeteer blocked lvh.me so… seems unnecessary
  • cleanup of Synapse synapse-data-* directories?
  • are host builds v slow? no they’re slow everywhere
  • needing to run register-realm-users seems annoying
  • probably macOS-centric at the moment Claude says no?!
  • what’s the deal with localhost:4205 realm(s)
  • bot doesn’t integrate this yet

@backspace backspace self-assigned this Feb 27, 2026
@backspace backspace added the enhancement New feature or request label Feb 27, 2026
@github-actions
Copy link

Preview deployments

@github-actions
Copy link

github-actions bot commented Feb 27, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   2h 4m 42s ⏱️ + 2m 39s
1 955 tests ±0  1 940 ✅ +1  15 💤 ±0  0 ❌ ±0 
1 970 runs  ±0  1 955 ✅ +2  15 💤 ±0  0 ❌  - 1 

Results for commit 3e6c2df. ± Comparison against base commit 3c84a71.

♻️ This comment has been updated with latest results.

@habdelra
Copy link
Contributor

habdelra commented Mar 4, 2026

so how do you segregate the host app that the prerenderer uses so that it is the corresponding host app?

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b74ae5faa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@backspace
Copy link
Contributor Author

so how do you segregate the host app that the prerenderer uses so that it is the corresponding host app?

Traefik routes local subdomains (host.review.localhost in the video), the BOXEL_ENVIRONMENT tells the realm server and other things that start from there which domain to use for host.

@backspace
Copy link
Contributor Author

so how do you segregate the host app that the prerenderer uses so that it is the corresponding host app?

Traefik routes local subdomains (host.review.localhost in the video), the BOXEL_ENVIRONMENT tells the realm server and other things that start from there which domain to use for host.

hmm let me look more into this, though, maybe it’s not properly wired up, as I couldn’t see any prerenderer URLs in the logs when I added debug logging

@habdelra
Copy link
Contributor

habdelra commented Mar 4, 2026

regarding your TODO: "what’s the deal with localhost:4205 realm(s)" this is the isolated realm that we run programmatically in isolated-realm-server.ts. i would imagine that you could just also set the BOXEL_ENVIRONMENT env var in node in isolated-realm-server.ts#startServer() and that could be set just like when we run from the command line?

@backspace backspace marked this pull request as draft March 4, 2026 21:41
@backspace
Copy link
Contributor Author

@habdelra’s question about the prerenderer prompted me to look deeper and that part isn’t working with this yet. The part in the video can still be reviewed, but having a working prerenderer is definitely a requirement before this is usable.

@backspace
Copy link
Contributor Author

Work similar to host mode’s use of undici was required to get .environment-name.localhost domains working with prerendering, now cards are prerendered properly:

e8c0a21ef0e0f5101a0d9e590435203ca7bf96af 2026-03-04 14-47-39

I added SKIP_CATALOG support to start:all because it’s tedious to wait for that to be fully indexed before we’re able to get working with a realm.

So this is ready for review again.

@backspace backspace marked this pull request as ready for review March 4, 2026 22:48
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 216fa750f8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


cd ../matrix

pnpm assert-synapse-running

Choose a reason for hiding this comment

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

P1 Badge Fail immediately when Synapse readiness check fails

pnpm assert-synapse-running is executed without set -e (or an explicit || exit), so in environment mode a failed Synapse bootstrap can be ignored and the script can still exit successfully when the .users-registered marker already exists. In that case start:all treats Matrix setup as complete and only fails much later while waiting on Matrix URLs, which makes startup flaky and hard to diagnose when Docker/start-synapse fails.

Useful? React with 👍 / 👎.

for CONTAINER in $(docker ps --format '{{.Names}}' | grep '^boxel-synapse-'); do
SLUG="${CONTAINER#boxel-synapse-}"
# Check if any process is using this environment's slug (realm server, host, etc.)
if ! ps ax -o command 2>/dev/null | grep -q "${SLUG}\.localhost"; then

Choose a reason for hiding this comment

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

P2 Badge Broaden stale Synapse detection before auto-removal

The stale-container check removes boxel-synapse-<slug> whenever no process argv contains ${slug}.localhost, but active services are not guaranteed to include that token (for example, host is launched as ember serve --port ... in packages/host/scripts/ember-serve.js). This can incorrectly delete a live environment’s Synapse container when Traefik is started from another workspace, causing unexpected Matrix outages even though environment processes are still running.

Useful? React with 👍 / 👎.

@jurgenwerk
Copy link
Contributor

jurgenwerk commented Mar 6, 2026

I have gone through the steps in the description and was able to get my parallel environment working! Still need to go review code as it's quite a lot of changes.

This is really neat but unfortunately my machine (18GB, M3) struggles with the memory pressures even of a single boxel environment, but hoping this gets better once we get Vite working 😌

# Conflicts:
#	packages/realm-server/prerender/prerenderer.ts
@backspace
Copy link
Contributor Author

I have gone through the steps in the description and was able to get my parallel environment working! Still need to go review code as it's quite a lot of changes.

This is really neat but unfortunately my machine (18GB, M3) struggles with the memory pressures even of a single boxel environment, but hoping this gets better once we get Vite working 😌

thanks for noting this, I have 64GB RAM so I haven’t seen it. At worst this still works to review code without having to switch away from one’s current focus branch, even if they can’t both run at once. But I too hope Vite brings us optimisations here.

@backspace backspace merged commit 86301ac into main Mar 6, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants