Skip to content

Instantly share code, notes, and snippets.

@altafshaikh
Created May 13, 2026 05:59
Show Gist options
  • Select an option

  • Save altafshaikh/071735701834d13ce7edf46b3694b824 to your computer and use it in GitHub Desktop.

Select an option

Save altafshaikh/071735701834d13ce7edf46b3694b824 to your computer and use it in GitHub Desktop.

AWS EC2 deployment plan (DevOps runbook)

This document describes how to host CDA-AgentX on AWS EC2 using the repo Dockerfile, docker-compose.yml, and scripts/web-slack-entry.sh. It assumes ByteRover context lives under /app/.brv inside the container and Slack uses Socket Mode (no public Slack webhook URL).

1. What you are deploying

Component Role
Next.js (App Router, server.js) Web UI + API routes on port 3000 (PORT / HOSTNAME=0.0.0.0)
Slack Bolt (lib/slack/bot.ts) Socket Mode bot — no inbound HTTP from Slack; needs outbound HTTPS
ByteRover (brv) CLI baked into image; /app/.brv is the persistent context tree (same path as Compose volume)
MongoDB Optional but typical in prod — Atlas or self-managed; app degrades gracefully if DB is down

Image facts (from repo):

  • Multi-stage node:22-slim build; byterover-cli installed globally in base.
  • Next output: "standalone" — runtime copies .next/standalone, static assets, lib/, scripts/.
  • Default Dockerfile CMD: bash scripts/web-slack-entry.sh → starts Next then Slack after /api/health returns 200 or 503 (503 = degraded but alive, e.g. DB).
  • docker-compose.yml: cda-web = node server.js, cda-slack = node --import tsx lib/slack/bot.ts, shared volume brv-data:/app/.brv.

2. Choose EC2 topology (pick one)

Option A — Single container (recommended to mirror Render / one logical host)

  • Run the image with default CMD: bash scripts/web-slack-entry.sh.
  • One process group, one place to persist /app/.brv.
  • Fits: one EC2 instance, simple systemd + docker run, or ECS/Fargate one task.

Option B — docker-compose on EC2 (two containers, one volume)

  • cda-web and cda-slack share brv-data so both see the same ByteRover tree (matches local dev).
  • Do not deploy web on instance A and Slack on B unless both share storage (EFS/NFS). This app expects one coherent .brv.

3. AWS building blocks

Piece Recommendation
EC2 Amazon Linux 2023 or Ubuntu 22.04/24.04 LTS; t3.small minimum (t3.medium+ under load); private subnet OK with NAT for egress
EBS Durable GP3 volume; mount e.g. /data/cda-agent-x/brv and bind-mount to /app/.brv
Security groups Inbound 443/80 (ALB/nginx) → instance 3000, or bind 127.0.0.1:3000 if reverse proxy on host; outbound: 443 for Slack/LLM/Atlas/Google/ByteRover as needed
TLS ALB + ACM or nginx/Caddy on host with Let’s Encrypt
Secrets Secrets Manager or SSM Parameter Store (SecureString); inject at deploy — never bake into AMI
MongoDB Atlas with EC2 egress / NAT IP allowlist

4. EC2 host prep

  1. Install Docker CE (+ Docker Compose v2 if using Option B); enable docker service.
  2. Create persistent path, e.g. /data/cda-agent-x/brv, ownership compatible with container user (nextjs uid 1001 in image — match with chown on host or run with adjusted user mapping).
  3. Plan disk: ingestion can write raw/ under project root patterns; ByteRover context grows — monitor disk.

5. Container run examples

Option A — single container (matches Dockerfile default)

docker pull <YOUR_ECR_REPO>/cda-agent-x:<tag>

docker run -d --name cda-agent-x \
  --restart unless-stopped \
  -p 127.0.0.1:3000:3000 \
  -v /data/cda-agent-x/brv:/app/.brv \
  --env-file /etc/cda-agent-x.env \
  <YOUR_IMAGE>

Prefer 127.0.0.1:3000 if TLS terminates on nginx/ALB on the same host or upstream.

Option B — Compose on server

From the repo directory, with .env on the host (not committed):

docker compose up -d

For durability clarity, operators may replace the named brv-data volume with an explicit bind mount to /data/cda-agent-x/brv.

6. Environment variables

Canonical list: .env.example. Highlights from lib/config.ts and project conventions:

Core production:

  • GROQ_API_KEY and/or OPENAI_API_KEY (optional LLM_PROVIDER, LLM_MODEL, LLM_BASE_URL)
  • SLACK_BOT_TOKEN, SLACK_APP_TOKEN
  • If SLACK_ENV=personal: PERSONAL_SLACK_BOT_TOKEN, PERSONAL_SLACK_APP_TOKEN

Recommended:

  • MONGODB_URI, MONGODB_DB

ByteRover cloud bootstrap (ephemeral disks or disposable instances):

  • BYTEOVER_API_KEY — runs scripts/brv-remote-bootstrap.shbrv login + brv pull. See docs/brv-cloud-sync.md.

Optional:

  • BRV_PATH, BRV_PROJECT_ROOT

Build note: GROQ_API_KEY is set to a placeholder only during docker build; runtime must supply real keys.

7. Health checks and rollout

Check Detail
LB / scripted GET /api/health — treat 200 or 503 as “process up” (matches scripts/web-slack-entry.sh)
Compose Defined healthcheck on cda-web
Slack Validate Socket Mode connectivity + message in workspace

Rollback: pinned image digest/tag and previous container/task definition while keeping the .brv volume data.

8. Architecture flow

flowchart LR
  subgraph EC2["EC2 or ECS task"]
    D[Docker]
    N[Next server.js]
    S[Slack bot tsx]
    B["/app/.brv volume"]
    D --> N
    D --> S
    N --> B
    S --> B
  end
  User[Browser] --> ALB[ALB / nginx TLS]
  ALB --> N
  S <-->|Outbound wss/https| SlackAPI[Slack API]
  N --> LLM[Groq / OpenAI]
  N --> MG[(MongoDB)]
  EC2 <-->|Optional brv pull/push| BRVCloud[ByteRover cloud]
Loading
  1. CI builds Dockerfile, pushes to ECR.
  2. Provision EC2 + EBS + SG + TLS + secrets.
  3. First run: pull image, attach .brv, inject env from Secrets Manager/SSM.
  4. With BYTEOVER_API_KEY: bootstrap pull → Next → health → Slack.
  5. Upgrade: new image tag + preserve /app/.brv.

9. Operational checklist

  • Persistent /app/.brv on EBS (or EFS only if concurrency/file semantics are validated for ByteRover).
  • Outbound 443 for Slack, LLMs, Atlas, optional Google APIs, ByteRover.
  • IAM for secretsmanager:GetSecretValue or SSM reads; no secrets in user-data history.
  • brv push after important curates when using remote space — see scripts/brv-remote-push.sh and docs/brv-cloud-sync.md.
  • Atlas IP allowlist if EC2/NAT egress changes.
  • Alerts: Docker restarts, disk, /api/health failures from localhost.

10. Anti-patterns

  • Running cda-web and cda-slack on different hosts without a shared .brv — unsupported; context will diverge.

Related docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment