diff --git a/deploy/ecs/README.md b/deploy/ecs/README.md new file mode 100644 index 000000000..8960d2e9c --- /dev/null +++ b/deploy/ecs/README.md @@ -0,0 +1,91 @@ +# Deploy Workspace Backend to AWS ECS Fargate + +## Prerequisites + +- AWS CLI configured +- Docker installed +- An ECR repository for the image +- A PostgreSQL database (e.g., Supabase, Insforge, RDS) + +## 1. Create ECR Repository + +```bash +aws ecr create-repository --repository-name openagents-workspace-backend --region us-east-1 +``` + +## 2. Build and Push Image + +```bash +cd workspace/backend + +aws ecr get-login-password --region us-east-1 | \ + docker login --username AWS --password-stdin .dkr.ecr.us-east-1.amazonaws.com + +docker build --platform linux/amd64 -t .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest . +docker push .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest +``` + +## 3. Create ECS Resources + +```bash +# Create cluster +aws ecs create-cluster --cluster-name openagents-workspace + +# Create log group +aws logs create-log-group --log-group-name /ecs/openagents-workspace-backend + +# Edit task-definition.json with your values, then register it +aws ecs register-task-definition --cli-input-json file://deploy/ecs/task-definition.json +``` + +## 4. Create Service + +```bash +# Create a security group allowing port 8000 (or 443 if using ALB) +SG_ID=$(aws ec2 create-security-group \ + --group-name openagents-workspace-sg \ + --description "OpenAgents Workspace" \ + --vpc-id \ + --query 'GroupId' --output text) + +aws ec2 authorize-security-group-ingress \ + --group-id $SG_ID \ + --protocol tcp --port 8000 --cidr 0.0.0.0/0 + +# Create Fargate service +aws ecs create-service \ + --cluster openagents-workspace \ + --service-name workspace-backend \ + --task-definition openagents-workspace-backend \ + --desired-count 1 \ + --launch-type FARGATE \ + --network-configuration "awsvpcConfiguration={subnets=[,],securityGroups=[$SG_ID],assignPublicIp=ENABLED}" +``` + +## 5. Add HTTPS with ALB (Recommended) + +For a stable URL with SSL: + +1. Request an ACM certificate for your domain +2. Add DNS validation CNAME to Route 53 +3. Create an ALB with HTTPS listener forwarding to a target group on port 8000 +4. Update ECS service with the load balancer target group +5. Add a Route 53 A record (alias) pointing your domain to the ALB + +## 6. Update Image + +```bash +docker build --platform linux/amd64 -t .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest . +docker push .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest +aws ecs update-service --cluster openagents-workspace --service workspace-backend --force-new-deployment +``` + +## Environment Variables + +| Variable | Required | Description | +|----------|----------|-------------| +| `DATABASE_URL` | Yes | PostgreSQL connection string | +| `AUTH_MODE` | No | `workspace_token` (default) or `firebase` | +| `IDENTITY_MODE` | No | `standalone` (default) or `shared` | +| `CORS_ORIGINS` | No | Allowed origins, default `*` | +| `WORKSPACE_ENDPOINT` | No | Public URL of this service (used in manifests) | diff --git a/deploy/ecs/task-definition.json b/deploy/ecs/task-definition.json new file mode 100644 index 000000000..c4503a97a --- /dev/null +++ b/deploy/ecs/task-definition.json @@ -0,0 +1,36 @@ +{ + "family": "openagents-workspace-backend", + "networkMode": "awsvpc", + "requiresCompatibilities": ["FARGATE"], + "cpu": "512", + "memory": "1024", + "executionRoleArn": "arn:aws:iam:::role/ecsTaskExecutionRole", + "containerDefinitions": [ + { + "name": "workspace-backend", + "image": ".dkr.ecr..amazonaws.com/openagents-workspace-backend:latest", + "portMappings": [ + { + "containerPort": 8000, + "protocol": "tcp" + } + ], + "environment": [ + { "name": "DATABASE_URL", "value": "postgresql://user:pass@host:5432/dbname?sslmode=require" }, + { "name": "AUTH_MODE", "value": "workspace_token" }, + { "name": "IDENTITY_MODE", "value": "standalone" }, + { "name": "CORS_ORIGINS", "value": "*" }, + { "name": "WORKSPACE_ENDPOINT", "value": "https://your-domain.example.com" } + ], + "logConfiguration": { + "logDriver": "awslogs", + "options": { + "awslogs-group": "/ecs/openagents-workspace-backend", + "awslogs-region": "", + "awslogs-stream-prefix": "ecs" + } + }, + "essential": true + } + ] +} diff --git a/workspace/README.md b/workspace/README.md index c6b241837..81bafc1de 100644 --- a/workspace/README.md +++ b/workspace/README.md @@ -40,7 +40,39 @@ Events flow through a mod pipeline: `mod/auth` → `mod/workspace` → `mod/pers | `CORS_ORIGINS` | `*` | Allowed CORS origins (comma-separated) | | `AGENT_TIMEOUT_SECONDS` | `60` | Seconds before agent is considered offline | -## Deploy Frontend to Vercel / Insforge +## Self-Hosting + +### Run Locally (with external PostgreSQL) + +```bash +cd workspace/backend +pip install -r requirements.txt + +DATABASE_URL="postgresql://user:pass@host:5432/dbname?sslmode=require" \ +AUTH_MODE=workspace_token \ +PYTHONPATH=. \ +alembic upgrade head + +DATABASE_URL="postgresql://user:pass@host:5432/dbname?sslmode=require" \ +AUTH_MODE=workspace_token \ +PYTHONPATH=. \ +uvicorn app.main:app --host 0.0.0.0 --port 8000 +``` + +### Deploy to AWS ECS + +Build and push the Docker image: + +```bash +cd workspace/backend +aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin .dkr.ecr.us-east-1.amazonaws.com +docker build --platform linux/amd64 -t .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest . +docker push .dkr.ecr.us-east-1.amazonaws.com/openagents-workspace-backend:latest +``` + +See [`deploy/ecs/task-definition.json`](../deploy/ecs/task-definition.json) for the Fargate task definition template. + +### Deploy Frontend to Vercel / Insforge The frontend uses `output: 'standalone'` in `next.config.mjs` for Docker deployments. When deploying to Vercel or Insforge, remove that setting before deploying so the @@ -54,6 +86,30 @@ export default nextConfig; Set the environment variable `NEXT_PUBLIC_API_URL` to your backend URL (e.g. `https://your-backend.example.com`). +### Connect Agents + +```bash +# Create a workspace +curl -X POST https://your-endpoint/v1/workspaces \ + -H "Content-Type: application/json" \ + -d '{"name": "my-workspace"}' +# Returns: { "data": { "token": "", "slug": "" } } + +# Connect an agent +openagents create claude --name my-agent \ + --join-workspace \ + --endpoint https://your-endpoint \ + --no-browser +``` + +### Run Frontend + +```bash +cd workspace/frontend +npm install +NEXT_PUBLIC_API_URL=https://your-endpoint npm run dev +``` + ## Development ```bash