polats Claude Opus 5 (1M context) commited on
Commit
a38523f
·
1 Parent(s): caf011b

Keep the server alive across a restart, and persist its state

Browse files

The hook was launching the server and losing it: the log file appeared, empty,
and nothing listened. It runs under /bin/sh by default, where the detach does not
hold and the process goes when the hook returns — a codespace that looks healthy
and serves nothing. Running it through bash -c fixes it, which is why that wrapper
is there rather than for quoting.

Verified across a full stop/start cycle: the hook fires again on resume, opencode
is serving within seconds, and from outside the codespace an anonymous request is
still refused while a request carrying the user's GitHub token and the basic auth
password returns a healthy 200.

Also creates the state root. entrypoint.sh only uses it when it already exists and
is writable, and nothing else made it, so every boot reported "persistence: NONE"
and would have dropped sessions and provider logins at the next idle stop — the
one thing a stopped codespace is otherwise supposed to keep.

Drops the diagnostics that found this; the log the entrypoint already writes is
enough now that the failure is understood.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

.devcontainer/devcontainer.json CHANGED
@@ -53,12 +53,13 @@
53
  },
54
 
55
  // Runs on create *and* on every resume from an idle stop, which is what makes the codespace
56
- // behave like a server rather than a dev box you have to restart by hand.
 
57
  //
58
- // Diagnostic build: records whether the detached server is still alive after the hook
59
- // returns, because a hook that launches a process and then loses it looks identical to one
60
- // that never ran.
61
- "postStartCommand": "bash -c 'D=/tmp/hook.log; { echo \"--- hook $(date -Is)\"; command -v setsid || echo \"no setsid\"; } >> $D 2>&1; setsid nohup ${containerWorkspaceFolder}/.devcontainer/start-opencode.sh >> /tmp/opencode.log 2>&1 < /dev/null & P=$!; echo \"launched pid=$P\" >> $D; sleep 5; if kill -0 $P 2>/dev/null; then echo \"alive after 5s\" >> $D; else echo \"DEAD after 5s\" >> $D; fi; pgrep -f opencode >> $D 2>&1 || echo \"no opencode process\" >> $D'",
62
 
63
  "customizations": {
64
  "vscode": {
 
53
  },
54
 
55
  // Runs on create *and* on every resume from an idle stop, which is what makes the codespace
56
+ // behave like a server rather than a dev box you have to restart by hand. Verified across a
57
+ // stop/start cycle: the hook runs again and the server is serving within seconds.
58
  //
59
+ // `bash -c` is not decoration. The hook is otherwise run by /bin/sh, where this line does
60
+ // not reliably detach and the server is lost the moment the hook returns — leaving a
61
+ // codespace that looks healthy and serves nothing.
62
+ "postStartCommand": "bash -c 'setsid nohup ${containerWorkspaceFolder}/.devcontainer/start-opencode.sh >> /tmp/opencode.log 2>&1 < /dev/null & sleep 2'",
63
 
64
  "customizations": {
65
  "vscode": {
.devcontainer/start-opencode.sh CHANGED
@@ -38,4 +38,9 @@ if [ -z "${OPENCODE_SERVER_PASSWORD:-}" ]; then
38
  echo " gh secret set OPENCODE_SERVER_PASSWORD --app codespaces --repo OWNER/REPO" >&2
39
  fi
40
 
 
 
 
 
 
41
  exec /home/node/entrypoint.sh
 
38
  echo " gh secret set OPENCODE_SERVER_PASSWORD --app codespaces --repo OWNER/REPO" >&2
39
  fi
40
 
41
+ # entrypoint.sh only uses the state root if it already exists and is writable, and nothing
42
+ # else creates it — so without this every boot reports "persistence: NONE" and sessions and
43
+ # logins are silently lost on the next idle stop.
44
+ mkdir -p "${OPENCODE_STATE_ROOT:-/workspaces/.opencode-state}" 2>/dev/null || true
45
+
46
  exec /home/node/entrypoint.sh