Deploy
How PixelRAG runs in production. (Host-specific details — the actual machine, secrets, live
state — are intentionally not in this public repo; they live in an out-of-repo file the
root CLAUDE.md imports on the deploy host.)
Topology
- Frontend (
web/) — deployed on Vercel frommain, automatically. - Search API (
serve/) —pixelrag servebehind nginx, run blue-green (two slots). - Chat agent (
web/agent-server.mjs) — a Node service that calls the search API.
CD — self-hosted runner (egress-only)
Continuous deployment uses a self-hosted GitHub Actions runner on the deploy box. The runner dials out to GitHub (no inbound access, no SSH keys or hostnames in the repo/secrets), so the machine stays private and works behind a firewall.
.github/workflows/deploy.yml triggers only on push to main (post-merge = trusted code) and
manual dispatch — never pull_request — so fork PRs can't run on the runner. All CI stays on
GitHub-hosted runners.
On each deploy, deploy/deploy.sh fast-forwards the checkout and restarts only what changed:
uv.lock→uv syncweb/agent-server.mjs→ restart the agent (cheap)serve/**→ flagged only (a search-index reload is expensive — use blue-green instead)
It refuses to run unless the checkout is on a clean main (the deploy box doubles as a dev
machine, so it must never clobber in-progress work).
Blue-green search API
Two slots — blue and green — each an independent pixelrag serve on its own port, fronted
by an nginx upstream (pixelrag-api-upstream.conf → /etc/nginx/conf.d/). To roll out a new
index or model with zero downtime:
- Bring up the idle slot with the new config (
pixelrag-api-green.serviceis the green slot). deploy/api-switch.sh <port>— health- and smoke-checks the target, flips the nginx upstream with a graceful reload (no dropped connections), and repoints + restarts the agent.- Rollback =
deploy/api-switch.sh <other-port>.
This is preferred over restarting a slot in place, which reloads the (large) FAISS index and would mean minutes of downtime.
Files
deploy.sh— CD restart logic (invoked by the Deploy workflow)api-switch.sh— blue-green cutover + rollbackpixelrag-api.service,pixelrag-api-green.service— the two search-API slotspixelrag-agent.service— the chat agentpixelrag-api-upstream.conf— nginx upstream the switch script rewrites