Skip to content

Commit 452efe9

Browse files
sjmiller609claude
andauthored
Rewrite chromium wrapper.sh as a Go binary (#234)
## Summary Replaces the bash `wrapper.sh` shipped in `chromium-headful` and `chromium-headless` with a single Go binary (`server/cmd/wrapper`) that detects the profile at boot from supervisor's `conf.d` (`xorg.conf` → headful, `xvfb.conf` → headless). The wrapper is split into two phases so identity-bound work doesn't block boot: - **Phase A** (identity-free) starts `xorg`/`xvfb`, `dbus`, `chromedriver`, and `chromium` in one `supervisorctl` call, then probes readiness concurrently. Per-service files (`chromium.go`, `display.go`, `envoy.go`, `probes.go`, `supervisord.go`, `system.go`) keep each concern isolated. - **Phase C** (identity-bound) renders the envoy bootstrap from `INST_NAME` / `JWT` / `XDS_SERVER` and brings up `kernel-images-api` + envoy once those are present. X11 socket readiness is a small shared package (`server/lib/x11`) used by both the wrapper and the chromium launcher so they agree on what "display ready" means. Per-service tweaks: - supervisor confs: `startsecs=2` → `0` so `supervisorctl start` returns immediately; the Go wrapper probes readiness directly. - `init-envoy.sh`: drop the trailing port poll / curl-through-proxy check — `waitAllReady` covers both, and the script now fails fast on any error. - `Kraftfile` `cmd` updated from `/wrapper.sh` to `/wrapper`. - Envoy proxy CA cert is baked at image build time. Other behaviour: - SIGTERM/SIGINT handler is registered before `supervisord` starts so signals during the seconds-long startup window are caught instead of killing the wrapper outright. - Critical boot scripts (`init-envoy.sh`) are streamed via `runStreamFatal` so failures abort boot instead of being silently swallowed, matching the old `set -o errexit`. - The ready log line reports per-probe durations, e.g. `ready in 2.6s (phaseA=251ms phaseC=289ms; cdp=2.646s chromedriver=1.468s forward-proxy=2.306s)`. Cosmetic + non-critical work (`pulseaudio`, `--no-sandbox` infobar dismissal) runs off the hot path. ## Test plan - [ ] `go build ./cmd/wrapper` and `go vet ./cmd/wrapper` pass - [ ] Build chromium-headless image and confirm container reaches CDP-ready - [ ] Build chromium-headful image and confirm container reaches CDP-ready - [ ] Confirm envoy comes up and the forward-proxy listener is reachable when `INST_NAME` / `XDS_SERVER` / `KERNEL_INSTANCE_JWT` are set - [ ] Confirm `RUN_AS_ROOT=true` headful flow still dismisses the `--no-sandbox` infobar - [ ] Confirm SIGTERM/SIGINT propagates to supervisord and child services exit cleanly <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it replaces the container entrypoint/startup orchestration for both headful and headless Chromium images and changes Envoy certificate/bootstrap behavior, which could affect boot readiness and proxy trust in production. > > **Overview** > **Replaces `wrapper.sh` with a single Go entrypoint (`/wrapper`)** for both `chromium-headful` and `chromium-headless`, updating Dockerfiles, Kraft `cmd`, and README examples to use the new binary. > > The new wrapper starts `supervisord` in foreground, brings up core services in parallel (X server, `dbus`, `chromedriver`, `chromium`), and performs explicit readiness probes (CDP, chromedriver, optional `neko`, optional Envoy) instead of relying on `supervisor` delays; corresponding supervisor `startsecs` values are set to `0`. > > **Envoy setup is split**: a new build-time `shared/envoy/bake-certs.sh` bakes the forward-proxy CA into system trust + NSS DBs, while `shared/envoy/init-envoy.sh` now only renders bootstrap from identity env and starts/restarts Envoy (dropping runtime cert generation and inline readiness/proxy tests). `chromium-launcher` now waits for X display (and `mutter` when headful) using a new `server/lib/x11` helper to avoid restart loops/WM decoration issues. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ae4b8d3. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: sjmiller609 <7516283+sjmiller609@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7be1cc6 commit 452efe9

29 files changed

Lines changed: 858 additions & 730 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Deployed successfully!
8383
├────── service: <service_name>
8484
├─ private fqdn: <id>
8585
├─── private ip: <ip>
86-
└───────── args: /wrapper.sh
86+
└───────── args: /wrapper
8787
```
8888

8989
### Unikernel Notes

images/chromium-headful/Dockerfile

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ RUN --mount=type=cache,target=/root/.cache/go-build,id=$CACHEIDPREFIX-go-build \
2727
GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
2828
go build -ldflags="-s -w" -o /out/chromium-launcher ./cmd/chromium-launcher
2929

30+
# Build container entrypoint wrapper (replaces wrapper.sh)
31+
RUN --mount=type=cache,target=/root/.cache/go-build,id=$CACHEIDPREFIX-go-build \
32+
--mount=type=cache,target=/go/pkg/mod,id=$CACHEIDPREFIX-go-pkg-mod \
33+
GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
34+
go build -ldflags="-s -w" -o /out/wrapper ./cmd/wrapper
35+
3036
# webrtc client
3137
FROM node:22-bullseye-slim AS client
3238
WORKDIR /src
@@ -356,7 +362,6 @@ COPY --from=xorg-deps /usr/local/lib/xorg/modules/input/neko_drv.so /usr/lib/xor
356362
COPY images/chromium-headful/image-chromium/ /
357363
COPY images/chromium-headful/start-pulseaudio.sh /images/chromium-headful/start-pulseaudio.sh
358364
RUN chmod +x /images/chromium-headful/start-pulseaudio.sh
359-
COPY images/chromium-headful/wrapper.sh /wrapper.sh
360365
COPY images/chromium-headful/supervisord.conf /etc/supervisor/supervisord.conf
361366
COPY images/chromium-headful/supervisor/services/ /etc/supervisor/conf.d/services/
362367
COPY shared/envoy/supervisor-envoy.conf /etc/supervisor/conf.d/services/envoy.conf
@@ -373,6 +378,7 @@ RUN chmod +x /usr/local/bin/init-envoy.sh
373378
# copy the kernel-images API binary built in the builder stage
374379
COPY --from=server-builder /out/kernel-images-api /usr/local/bin/kernel-images-api
375380
COPY --from=server-builder /out/chromium-launcher /usr/local/bin/chromium-launcher
381+
COPY --from=server-builder /out/wrapper /wrapper
376382

377383
# Copy and compile the Playwright daemon
378384
COPY server/runtime/playwright-daemon.ts /tmp/playwright-daemon.ts
@@ -389,4 +395,10 @@ RUN esbuild /tmp/playwright-daemon.ts \
389395

390396
RUN useradd -m -s /bin/bash kernel
391397

392-
ENTRYPOINT [ "/wrapper.sh" ]
398+
# Bake the envoy forward-proxy CA cert into the image (system trust store +
399+
# NSS DB for both root and kernel users). See bake-certs.sh for the security
400+
# rationale on sharing the cert across containers built from this image.
401+
COPY shared/envoy/bake-certs.sh /usr/local/bin/bake-certs.sh
402+
RUN chmod +x /usr/local/bin/bake-certs.sh && /usr/local/bin/bake-certs.sh && rm /usr/local/bin/bake-certs.sh
403+
404+
ENTRYPOINT [ "/wrapper" ]

images/chromium-headful/Kraftfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ labels:
99

1010
rootfs: ./initrd
1111

12-
cmd: ["/wrapper.sh"]
12+
cmd: ["/wrapper"]

images/chromium-headful/supervisor/services/chromedriver.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/usr/local/bin/chromedriver --port=9225 --allowed-ips=127.0.0.1 --log-level=INFO
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/chromedriver
77
redirect_stderr=true

images/chromium-headful/supervisor/services/dbus.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/bin/bash -lc 'mkdir -p /run/dbus && dbus-uuidgen --ensure && dbus-daemon --system --address=unix:path=/run/dbus/system_bus_socket --nopidfile --nosyslog --nofork'
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/dbus
77
redirect_stderr=true

images/chromium-headful/supervisor/services/kernel-images-api.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/bin/bash -lc 'mkdir -p "${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" && PORT="${KERNEL_IMAGES_API_PORT:-10001}" FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}" DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}" MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}" OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}" LOG_CDP_MESSAGES="${LOG_CDP_MESSAGES:-false}" exec /usr/local/bin/kernel-images-api'
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/kernel-images-api
77
redirect_stderr=true

images/chromium-headful/supervisor/services/mutter.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/bin/bash -lc 'XDG_SESSION_TYPE=x11 mutter --replace --sm-disable'
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/mutter
77
redirect_stderr=true

images/chromium-headful/supervisor/services/neko.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/usr/bin/neko serve --server.static /var/www --server.bind 0.0.0.0:8080
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/neko
77
redirect_stderr=true

images/chromium-headful/supervisor/services/xorg.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
command=/usr/bin/Xorg :1 -config /etc/neko/xorg.conf -noreset -nolisten tcp
33
autostart=false
44
autorestart=true
5-
startsecs=2
5+
startsecs=0
66
stdout_logfile=/var/log/supervisord/xorg
77
redirect_stderr=true

0 commit comments

Comments
 (0)