mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-03 11:33:27 +00:00
Captures the stock-LangGraph deployment of this fork at Sea Haven: - systemd/open-swe.service: langgraph dev (:2024) + store seed ExecStartPost - seed_store.sh: re-seeds team_settings + user_mappings (in-memory store resets on restart); env-parameterized, no secrets - nginx/openswe.conf: dashboard SPA + scoped /dashboard/api proxy (security boundary; agent API not exposed) - aegra/: deferred self-hosted-runtime alternative (not active on stock) - DEPLOYMENT.md: full runbook (models, build, ingress, OAuth callback) Secrets and internal infra identifiers are intentionally excluded (public fork); real values live in private IT docs.
99 lines
5.6 KiB
Markdown
99 lines
5.6 KiB
Markdown
# Sea Haven — Open SWE self-hosted deployment
|
||
|
||
How this fork is deployed at Sea Haven. The runtime is the **stock LangGraph dev
|
||
server** (not the Aegra path — see [Aegra](#aegra-deferred)). Internal addresses,
|
||
ARNs, and account IDs are shown as `<PLACEHOLDERS>`; the real values live in the
|
||
private IT docs (Confluence "AWS Architecture Map") — **do not commit them to this
|
||
public fork.**
|
||
|
||
## Topology
|
||
|
||
```
|
||
GitHub / Slack ──▶ hooks.seahavenind.com ──┐
|
||
│ (public ALB :443, host+path rule)
|
||
Browser ─────────▶ openswe.seahavenind.com ─┤
|
||
▼
|
||
AWS ALB ──(Site-to-Site VPN)──▶ on-prem VM
|
||
├─ nginx :80 (dashboard SPA + /dashboard/api proxy)
|
||
└─ langgraph dev :2024 (3+ graphs + FastAPI webapp)
|
||
└─▶ LangSmith cloud sandbox (build/git/PR)
|
||
```
|
||
|
||
- The VM is **internet-closed**; all inbound rides the existing ALB over the VPN.
|
||
- **Webhooks** (`hooks.seahavenind.com`) → ALB listener rule scoped to `/webhooks/*`
|
||
only → VM `:2024`. The unauthenticated LangGraph API (`/threads`, `/runs`,
|
||
`/assistants`, `/store`) is never path-forwarded.
|
||
- **Dashboard** (`openswe.seahavenind.com`) → ALB → VM `:80` (nginx). nginx is the
|
||
security boundary: it serves the static SPA and proxies **only** `/dashboard/api/`
|
||
to `:2024`; the agent API is not reachable through it.
|
||
|
||
## VM components
|
||
|
||
| Component | What |
|
||
|---|---|
|
||
| `langgraph dev` | systemd `open-swe.service` — `--host 0.0.0.0 --port 2024 --no-browser --no-reload`. In-memory runtime. |
|
||
| Store seeding | `seed_store.sh` as `ExecStartPost` (re-seeds team settings + user mappings, which the in-memory store loses on restart). |
|
||
| nginx | `nginx/openswe.conf` — SPA from `/var/www/openswe`, proxy `/dashboard/api/` → `:2024`. |
|
||
| Postgres | present (was for the Aegra path); unused by the stock in-memory runtime. |
|
||
| swap | 8 GB swapfile — **required**: the dashboard (`ui/`) Nitro build OOMs on an 8 GB box without it. |
|
||
|
||
### Models
|
||
Model selection is **store-driven**, not env. `LLM_MODEL_ID` is effectively dead for
|
||
runtime selection; the `team_settings/default` store doc wins (then per-user profile,
|
||
then per-thread). Defaults seeded by `seed_store.sh`:
|
||
- builder: `anthropic:claude-opus-4-8` (effort `high`)
|
||
- reviewer (cross-family): `openai:gpt-5.5` (effort `high`) — `openai:gpt-4.1` is **not**
|
||
in this fork's `SUPPORTED_MODELS` (`agent/dashboard/options.py`); a raw value is
|
||
silently rewritten to gpt-5.5. Add it to `SUPPORTED_MODELS` first if you need 4.1.
|
||
- `analyzer` graph is hardcoded to the code default and ignores team settings.
|
||
|
||
## Build & deploy the dashboard (`ui/`)
|
||
|
||
`ui/` is a **TanStack Start + Nitro** app (build with `bun`, not plain Vite):
|
||
|
||
```bash
|
||
cd ui
|
||
export PATH="$HOME/.bun/bin:$PATH"
|
||
export NODE_OPTIONS=--max-old-space-size=6144 # + the 8 GB swapfile, or the build OOMs
|
||
bun install
|
||
bun run build # -> .output/public (static SPA, _shell.html)
|
||
sudo cp -r .output/public/. /var/www/openswe/ # served by nginx
|
||
```
|
||
|
||
Served as a static SPA (per `ui/vercel.json`); the Nitro `.output/server` is unused.
|
||
|
||
## Install / wire-up checklist
|
||
|
||
1. App config in `.env` (gitignored — never commit): LLM keys, GitHub App creds,
|
||
`LANGSMITH_API_KEY*` + `DEFAULT_SANDBOX_SNAPSHOT_ID` (`SANDBOX_TYPE=langsmith` — the
|
||
only sandbox provider with working in-sandbox git/gh auth), `LANGGRAPH_URL=http://127.0.0.1:2024`,
|
||
dashboard vars (`DASHBOARD_JWT_SECRET`, `CONFIGURED_ADMINS`, `DASHBOARD_*_URL=https://openswe.seahavenind.com`).
|
||
2. `systemd/open-swe.service` → `/etc/systemd/system/`, `seed_store.sh` on the VM with
|
||
`OPENSWE_*` env exported (owner login/email, default repo, model ids).
|
||
3. `nginx/openswe.conf` → `/etc/nginx/sites-available/openswe`, symlink into
|
||
`sites-enabled`, remove the default site, `nginx -t && systemctl reload nginx`.
|
||
4. AWS (real IDs in Confluence): IP target groups → `<VM_LAN_IP>:2024` and `:80`;
|
||
ALB SG **egress** rules to those ports (the ALB SG is allow-listed — health checks
|
||
time out without them); `:443` listener rules for the two hostnames; Route53 ALIAS
|
||
records → ALB. Webhook rule must stay path-scoped to `/webhooks/*`.
|
||
5. GitHub App: webhook URL `https://hooks.seahavenind.com/webhooks/github`; subscribe to
|
||
the events the install guide lists (Issue comment, PR review×2, check_run/suite,
|
||
workflow_run, status) — add **Issues** too if you want issue-title/body triggers.
|
||
6. **GitHub App OAuth callback (manual, UI-only — not API-settable):**
|
||
`https://openswe.seahavenind.com/dashboard/api/auth/callback` — without it, dashboard
|
||
login fails with a `redirect_uri` mismatch.
|
||
|
||
## Triggering
|
||
|
||
Start a task by mentioning **`@openswe`** in a GitHub issue comment (the documented
|
||
intake — the `open-swe` *label* path needs the `Issues` event subscription). The
|
||
commenter must have a `user_mappings` entry or the run is skipped.
|
||
|
||
## Aegra (deferred)
|
||
|
||
`aegra/aegra.json` + `aegra/aegra_entry.py` are the self-hosted-runtime alternative
|
||
(Apache-2.0, avoids the LangGraph-Platform Elastic license). Not active on the stock
|
||
deployment. To use: place both at the repo root, run `aegra serve` (:2026), and point
|
||
`LANGGRAPH_URL` at `:2026`. Aegra gives a Postgres-backed durable store/checkpointer,
|
||
which removes the need for `seed_store.sh` and survives restarts (paused HITL
|
||
interrupts persist).
|