Files
ai-stack-deployer/docs/DEPLOYMENT_STRATEGY.md
Oussama Douhou 2f306f7d68 feat: production-ready deployment with multi-language UI
- 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
2026-01-10 09:56:33 +01:00

8.3 KiB

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

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

# 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

# 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

# Via Dokploy UI
1. Go to application → Deployments
2. Click "Rollback" on previous successful deployment

Manual Rollback

# 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)

# .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

# 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