diff --git a/CHANGELOG.md b/CHANGELOG.md index b6596b1..fa81cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ First feature driven by a real consumer ([multis](https://github.com/hamr0/multi ### Documentation - **README — added a shared "The bare ecosystem" section** (Core / Optional-reach list covering all six modules: `bareagent` · `bareguard` · `litectx`, plus `barebrowse` · `baremobile` · `beeperbox`). beeperbox sits under optional reach as the messaging member. The same section now ships across all six repos. Docs only — no container/runtime change. +### Fixed — `docker restart` no longer segfaults the display `[PATCH]` +- **`docker restart` reliably wedged the container with a stale Xvfb lock.** `docker restart` re-runs the entrypoint but preserves the container's writable layer, so Xvfb's `/tmp/.X99-lock` from the previous boot survived into the new process. Xvfb then saw display `:99` as "already active", half-initialized it, and **segfaulted** (`(EE) Server is already active for display 99`) — the backend never bound `127.0.0.1:23373`, socat looped on connection-refused, and the container sat stuck in `health: starting`. Only a full `docker compose down && up` (which discards `/tmp`) recovered. The entrypoint now removes the stale `/tmp/.X99-lock` and `/tmp/.X11-unix/X99` before starting Xvfb, so `docker restart` — the natural operation after any config change — is survivable. No runtime-contract change (MCP tools, HTTP API, schemas, ports bit-identical); PATCH per the versioning policy. + ## [0.5.1] — 2026-05-25 `[PATCH]` Release-pipeline hardening and documentation. PATCH per the versioning policy — these change how releases are *built and described*, not what the running container does: the MCP tool surface, raw/HTTP API, `Chat`/`Message` schemas, and default ports are bit-identical to v0.5.0, and no client-code edits are required. The headline is that the release path is now **gated on the guard tests** with a `:previous` rollback tag, so a broken upstream Beeper can no longer silently become `:latest`. diff --git a/README.md b/README.md index 7dda891..1461404 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ echo "BEEPER_TOKEN=abc123..." > .env docker compose up -d ``` -Login and bridge state persist in a named volume — you won't log in again after restarts. +Login and bridge state persist in a named volume — you won't log in again after restarts, and `docker restart` recovers cleanly (the entrypoint clears the stale display lock that used to wedge a restarted container). **3. Talk to it** diff --git a/docs/PRD.md b/docs/PRD.md index 07f8fe6..2c0c47d 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -156,6 +156,7 @@ Every chat and message carries both `network` (machine slug: `whatsapp`, `telegr - **One-time login, persistent state.** Named volume holds login + bridge state; survives restart/rebuild/reboot. Bridges configured on an existing Beeper account (e.g. on a phone) inherit automatically — bridge state lives on Beeper's servers. - **Healthcheck.** Docker `HEALTHCHECK` probes the API through the same socat path external clients use, so a crashed API *or* forwarder marks the container unhealthy. Paired with `restart: unless-stopped`. - **Clean shutdown.** The entrypoint traps SIGTERM/SIGINT and forwards to Beeper Desktop, waiting for full reap so matrix sync / sqlite checkpoint flush before exit (no partial writes on `docker stop`). +- **Restart-survivable display.** `docker restart` preserves the container's writable layer, so the entrypoint clears the stale Xvfb lock (`/tmp/.X99-lock`, `/tmp/.X11-unix/X99`) before starting Xvfb — otherwise the surviving lock makes Xvfb half-initialize `:99` and segfault, wedging the stack until a full recreate. `docker restart` (the natural op after a config change) now recovers cleanly. - **Multi-instance density.** Env-overridable ports + container name let many single-tenant instances share one VPS (density guidance in [`GUIDE.md`](GUIDE.md)). --- diff --git a/entrypoint.sh b/entrypoint.sh index d5a7b88..c19f07d 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -5,6 +5,13 @@ echo "=== beeperbox ===" eval $(dbus-launch --sh-syntax) +# `docker restart` re-runs this entrypoint but preserves the container's +# writable layer, so Xvfb's lock from the previous boot survives in /tmp. +# A stale /tmp/.X99-lock makes Xvfb see ":99 already active", half-init the +# display, and segfault — wedging the whole stack. Recreate clears /tmp, which +# is why only `docker rm` recovered. Remove the stale lock so restart works. +rm -f /tmp/.X99-lock /tmp/.X11-unix/X99 + Xvfb :99 -screen 0 1024x768x24 -ac & sleep 1 echo "[ok] xvfb"