- Add multi-language support (NL, AR, EN) with RTL
- Improve health checks (SSL-tolerant, multi-endpoint)
- Add DELETE /api/stack/:name for cleanup
- Add persistent storage (portal-ai-workspace-{name})
- Improve rollback (delete domain, app, project)
- Increase SSE timeout to 255s
- Add deployment strategy documentation
291 lines
8.3 KiB
Markdown
291 lines
8.3 KiB
Markdown
# AI Stack Deployer - Deployment Strategy
|
|
|
|
## Overview
|
|
|
|
Deploy the AI Stack Deployer portal to production, making it accessible at `deploy.ai.flexinit.nl`.
|
|
|
|
## User Stack Container (oh-my-opencode-free)
|
|
|
|
### Image Details
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Registry | `git.app.flexinit.nl` |
|
|
| Image | `oussamadouhou/oh-my-opencode-free:latest` |
|
|
| Base | `oven/bun:debian` |
|
|
| Port | 8080 (OpenCode server) |
|
|
| CI/CD | Gitea Actions (auto-build on push) |
|
|
|
|
### Pre-configured Free Models
|
|
|
|
| Agent | Model | Purpose |
|
|
|-------|-------|---------|
|
|
| Sisyphus (main) | `glm-4.7-free` | Primary coding |
|
|
| Oracle | `gpt-5-nano` | Architecture |
|
|
| Librarian | `minimax-m2.1-free` | Documentation |
|
|
| Explore | `grok-code` | Codebase search |
|
|
| Frontend | `glm-4.7-free` | UI/UX |
|
|
| Document Writer | `gpt-5-nano` | Docs |
|
|
|
|
### Baked Configuration
|
|
|
|
```
|
|
/shared/config/
|
|
├── opencode.json # CLI config
|
|
├── opencode.jsonc # Permissions
|
|
└── oh-my-opencode.json # Agent model assignments
|
|
```
|
|
|
|
### Persistent Storage (per user)
|
|
|
|
| Volume | Mount Path | Purpose |
|
|
|--------|------------|---------|
|
|
| `workspace-{name}` | `/workspace` | User projects |
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Internet
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────┐
|
|
│ Traefik (144.76.116.169) │
|
|
│ - SSL termination (wildcard *.ai.flexinit.nl)│
|
|
│ - Routes deploy.ai.flexinit.nl → portal │
|
|
└─────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────┐
|
|
│ AI Stack Deployer Container │
|
|
│ - Port 3000 │
|
|
│ - Needs access to 10.100.0.20 (Dokploy) │
|
|
└─────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────┐
|
|
│ Dokploy (10.100.0.20:3000) │
|
|
│ - Creates user stacks │
|
|
│ - Manages containers │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Deployment Options
|
|
|
|
### Option A: Deploy via Dokploy (Recommended)
|
|
|
|
**Pros**: Self-service, consistent with stack deployments, automatic restarts
|
|
**Cons**: Circular dependency (if Dokploy is down, can't redeploy)
|
|
|
|
### Option B: Direct Docker on Traefik Host
|
|
|
|
**Pros**: Independent of Dokploy, simpler network (same host as Traefik)
|
|
**Cons**: Manual management, no Dokploy UI
|
|
|
|
### Option C: Separate VM with Docker Compose
|
|
|
|
**Pros**: Isolation, can use docker-compose.yml directly
|
|
**Cons**: Extra VM, network routing complexity
|
|
|
|
**Decision: Option A (Dokploy)** - Eat our own dog food, leverage existing infrastructure.
|
|
|
|
## Step-by-Step Deployment
|
|
|
|
### Phase 1: Prepare Image
|
|
|
|
```bash
|
|
# 1. Build and tag image
|
|
docker build -t git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest .
|
|
|
|
# 2. Push to registry
|
|
docker push git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest
|
|
```
|
|
|
|
### Phase 2: Create Dokploy Project
|
|
|
|
1. Open Dokploy UI: https://app.flexinit.nl
|
|
2. Create project: `ai-stack-deployer-portal`
|
|
3. Create application:
|
|
- Name: `deployer`
|
|
- Type: Docker Image
|
|
- Image: `git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest`
|
|
|
|
### Phase 3: Configure Environment
|
|
|
|
Set these environment variables in Dokploy:
|
|
|
|
| Variable | Value | Source |
|
|
|----------|-------|--------|
|
|
| `NODE_ENV` | `production` | Static |
|
|
| `PORT` | `3000` | Static |
|
|
| `HOST` | `0.0.0.0` | Static |
|
|
| `DOKPLOY_URL` | `http://10.100.0.20:3000` | Static |
|
|
| `DOKPLOY_API_TOKEN` | `<token>` | BWS: `6b3618fc-ba02-49bc-bdc8-b3c9004087bc` |
|
|
| `STACK_DOMAIN_SUFFIX` | `ai.flexinit.nl` | Static |
|
|
| `STACK_IMAGE` | `git.app.flexinit.nl/oussamadouhou/oh-my-opencode-free:latest` | Static |
|
|
| `RESERVED_NAMES` | `admin,api,www,root,system,test,demo,portal,deploy` | Static |
|
|
|
|
### Phase 4: Configure Domain
|
|
|
|
1. In Dokploy application settings, add domain:
|
|
- Host: `deploy.ai.flexinit.nl`
|
|
- HTTPS: Enabled
|
|
- Port: 3000
|
|
|
|
2. DNS is already configured (wildcard `*.ai.flexinit.nl` → 144.76.116.169)
|
|
|
|
### Phase 5: Deploy
|
|
|
|
1. Click "Deploy" in Dokploy UI
|
|
2. Wait for container to start (~30s)
|
|
3. Verify health: `curl https://deploy.ai.flexinit.nl/health`
|
|
|
|
## Network Requirements
|
|
|
|
The deployer container MUST be able to reach:
|
|
- `10.100.0.20:3000` - Dokploy API (internal network)
|
|
|
|
This works automatically when deployed via Dokploy since containers share the internal network.
|
|
|
|
## Secrets Management
|
|
|
|
### Using BWS
|
|
|
|
```bash
|
|
# Get Dokploy token
|
|
bws secret get 6b3618fc-ba02-49bc-bdc8-b3c9004087bc
|
|
|
|
# Set in Dokploy environment variables (manually or via API)
|
|
```
|
|
|
|
### Rotation Strategy
|
|
|
|
1. Generate new token in Dokploy UI
|
|
2. Store in BWS
|
|
3. Update environment variable in Dokploy
|
|
4. Redeploy application
|
|
|
|
## Monitoring
|
|
|
|
### Health Checks
|
|
|
|
- **Endpoint**: `GET /health`
|
|
- **Interval**: 30 seconds
|
|
- **Expected**: `{"status":"healthy",...}`
|
|
|
|
### Alerting
|
|
|
|
Set up monitoring for:
|
|
- Health endpoint failures
|
|
- High error rates in deployment logs
|
|
- Circuit breaker state changes
|
|
|
|
## Rollback Procedure
|
|
|
|
### Quick Rollback
|
|
|
|
```bash
|
|
# Via Dokploy UI
|
|
1. Go to application → Deployments
|
|
2. Click "Rollback" on previous successful deployment
|
|
```
|
|
|
|
### Manual Rollback
|
|
|
|
```bash
|
|
# Re-deploy previous image tag
|
|
docker pull git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:v0.1.0
|
|
# Update image in Dokploy and redeploy
|
|
```
|
|
|
|
## CI/CD Pipeline (Future)
|
|
|
|
```yaml
|
|
# .github/workflows/deploy.yml
|
|
name: Deploy
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Build and push
|
|
run: |
|
|
docker build -t git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:${{ github.sha }} .
|
|
docker push git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:${{ github.sha }}
|
|
|
|
- name: Deploy via Dokploy API
|
|
run: |
|
|
curl -X POST "$DOKPLOY_URL/api/application.update" \
|
|
-H "x-api-key: $DOKPLOY_API_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"applicationId": "$APP_ID", "dockerImage": "...:${{ github.sha }}"}'
|
|
|
|
curl -X POST "$DOKPLOY_URL/api/application.deploy" \
|
|
-H "x-api-key: $DOKPLOY_API_TOKEN" \
|
|
-d '{"applicationId": "$APP_ID"}'
|
|
```
|
|
|
|
## Pre-Deployment Checklist
|
|
|
|
- [ ] Docker image builds successfully: `docker build -t test .`
|
|
- [ ] TypeScript compiles: `bun run typecheck`
|
|
- [ ] Health endpoint works locally: `curl localhost:3000/health`
|
|
- [ ] Dokploy API token is valid
|
|
- [ ] Registry credentials configured
|
|
- [ ] Domain DNS resolves correctly
|
|
|
|
## Post-Deployment Verification
|
|
|
|
```bash
|
|
# 1. Health check
|
|
curl https://deploy.ai.flexinit.nl/health
|
|
|
|
# 2. Name validation
|
|
curl https://deploy.ai.flexinit.nl/api/check/test-name
|
|
|
|
# 3. Frontend loads
|
|
curl -s https://deploy.ai.flexinit.nl | grep -q "AI Stack Deployer"
|
|
|
|
# 4. Full deployment test (optional)
|
|
curl -X POST https://deploy.ai.flexinit.nl/api/deploy \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "smoke-test"}'
|
|
|
|
# 5. Cleanup test
|
|
curl -X DELETE https://deploy.ai.flexinit.nl/api/stack/smoke-test
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **No public auth yet** - Consider adding authentication for production
|
|
2. **Rate limiting** - Not implemented, consider adding
|
|
3. **API token exposure** - Stored in Dokploy env vars (encrypted at rest)
|
|
4. **Delete endpoint** - Should require authentication in production
|
|
|
|
## Estimated Timeline
|
|
|
|
| Phase | Duration | Notes |
|
|
|-------|----------|-------|
|
|
| Image build & push | 5 min | Automated |
|
|
| Dokploy project setup | 10 min | One-time |
|
|
| Environment config | 5 min | One-time |
|
|
| Deployment | 2 min | Per deploy |
|
|
| Verification | 5 min | Per deploy |
|
|
| **Total first deploy** | ~30 min | |
|
|
| **Subsequent deploys** | ~10 min | |
|
|
|
|
## Next Steps
|
|
|
|
1. Build and push Docker image
|
|
2. Create Dokploy project and application
|
|
3. Configure environment variables
|
|
4. Add domain
|
|
5. Deploy and verify
|
|
6. Set up monitoring
|
|
7. (Optional) Implement CI/CD
|