Spaces:
Sleeping
Sleeping
File size: 3,101 Bytes
930c3ef 63ac17f 930c3ef a38523f edf5b8c a38523f 930c3ef | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | // opencode-cloud as a GitHub Codespace — a third home alongside Hugging Face Spaces and
// Railway.
//
// The same Dockerfile serves all three. What differs here is that a dev container starts with
// its entrypoint overridden, so the image's ENTRYPOINT never runs: the server has to be
// started explicitly, and started again after every idle stop.
//
// Codespaces stop after 30 minutes idle by default. That is fine for this use — a stopped
// codespace keeps its disk and restarts under the same name and URL — but it does mean
// postStartCommand, not postCreateCommand, is what boots the server, because only the former
// runs on every resume.
{
"name": "opencode-cloud",
"build": {
"dockerfile": "../Dockerfile"
},
// The image ships no SSH server, and without one `gh codespace ssh` and `gh codespace logs`
// both refuse — so a codespace that fails to start the server cannot be inspected at all.
// This costs nothing at runtime and is the difference between a debuggable box and a black
// one.
"features": {
"ghcr.io/devcontainers/features/sshd:1": {}
},
// uid 1000, matching the image. The Dockerfile creates nothing else.
"remoteUser": "node",
// Hugging Face has no $PORT and falls back to 7860; keep the same here so one number
// describes the server everywhere.
"containerEnv": {
"PORT": "7860",
// entrypoint.sh persists sessions, logins and code under this root when it is writable.
// /data does not exist in a codespace, but /workspaces survives stop/start, so state
// outlives an idle timeout and is lost only when the codespace itself is deleted.
"OPENCODE_STATE_ROOT": "/workspaces/.opencode-state"
},
"forwardPorts": [7860],
"portsAttributes": {
"7860": {
"label": "opencode",
// The only way to expose a port without a human toggling it: there is no REST endpoint
// for port visibility, so a client that provisions codespaces has to declare it here.
//
// Public is safe *because* entrypoint.sh refuses to start without
// OPENCODE_SERVER_PASSWORD. Every route on this server runs shell commands, so basic
// auth is the only thing in front of it; a missing password fails loudly rather than
// publishing an open shell.
"visibility": "public",
"onAutoForward": "silent"
}
},
// Runs on create *and* on every resume from an idle stop, which is what makes the codespace
// behave like a server rather than a dev box you have to restart by hand. Verified across a
// stop/start cycle: the hook runs again and the server is serving within seconds.
//
// `bash -c` is not decoration. The hook is otherwise run by /bin/sh, where this line does
// not reliably detach and the server is lost the moment the hook returns — leaving a
// codespace that looks healthy and serves nothing.
"postStartCommand": "bash -c 'setsid nohup ${containerWorkspaceFolder}/.devcontainer/start-opencode.sh >> /tmp/opencode.log 2>&1 < /dev/null & sleep 2'",
"customizations": {
"vscode": {
"extensions": []
}
}
}
|