Closes the Phase 5 P1 doc-drift checkbox and REVIEW_ACTIONS #5. The 3000-vs-3049 confusion came from prose claims in three docs that each picked a different "right" answer. The truth is: the web container listens on :3000; docker-compose maps `127.0.0.1:3049:3000`; production is fronted by Traefik on `https://devops.bytelyst.com`. Encoding that explicitly so future readers don't have to dig through compose files: - DEPLOYMENT.md becomes canonical. Its content is now the (more accurate) old DEPLOYMENT_GUIDE.md merged with a "Ports — quick reference" table covering Local dev / Docker Compose / Production Traefik, plus a Local-development section for `pnpm dev`. - DEPLOYMENT_GUIDE.md → 5-line redirect stub pointing at DEPLOYMENT.md (kept for `deploy.sh` and any external links). - deploy.sh updated to point at DEPLOYMENT.md. - README.md "Web port: 3000" line rewritten to spell out container vs Compose-host vs dev-mode and link to the port table. - ENDPOINTS.md gets a top-of-file note: every `localhost:3000` URL in that file is the `pnpm dev` workflow; substitute `:3049` for the Dockerized stack. - REVIEW_ACTIONS.md #5 marked RESOLVED with the rationale. No code, behavior, lint, or test changes. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
387 lines
11 KiB
Markdown
387 lines
11 KiB
Markdown
# DevOps & Admin Dashboard Deployment Guide
|
|
|
|
> Canonical deployment doc for `dashboard/`. The previous `DEPLOYMENT_GUIDE.md`
|
|
> has been folded into this file; it remains as a one-line redirect for
|
|
> backwards compatibility with `deploy.sh` and external links.
|
|
|
|
## Overview
|
|
|
|
This guide covers deploying both the DevOps Dashboard and Platform Admin Dashboard using the existing Traefik gateway infrastructure, following the same pattern as the trading dashboard (https://invttrdg.bytelyst.com).
|
|
|
|
## Public URLs
|
|
|
|
- **DevOps Dashboard**: `https://devops.bytelyst.com`
|
|
- **Admin Dashboard**: `https://admin.bytelyst.com`
|
|
- **API Gateway**: `https://api.bytelyst.com`
|
|
- Platform API: `https://api.bytelyst.com/platform/api`
|
|
- DevOps API: `https://api.bytelyst.com/api/devops`
|
|
|
|
## Ports — quick reference
|
|
|
|
The web container always listens on **3000** internally; what changes is what
|
|
the host exposes. Memorize the column for the deployment mode you're in:
|
|
|
|
| Mode | Web (host) | Backend (host) | Notes |
|
|
|-------------------------------------|--------------------|-------------------|--------------------------------------------------------------------|
|
|
| Local dev (`pnpm dev`) | `localhost:3000` | `localhost:4004` | Next listens directly on 3000. |
|
|
| Docker Compose (this repo) | `localhost:3049` | `localhost:4004` | `docker-compose.yml` maps `127.0.0.1:3049:3000` (loopback only). |
|
|
| Production (Traefik) | `https://devops.bytelyst.com` | `https://api.bytelyst.com/api/devops` | Traefik label `loadbalancer.server.port=3000` targets the container port. |
|
|
|
|
Whenever a doc says "the dashboard runs on port 3000", it means the **container
|
|
port** seen by Traefik / Next dev mode — not the host port for the deployed
|
|
stack. Use the table above instead of relying on prose.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Internet → Traefik Gateway → Services
|
|
├─ DevOps Web (container :3000, host :3049)
|
|
├─ DevOps Backend (:4004)
|
|
├─ Admin Web (:3001)
|
|
├─ Platform Service (:4003)
|
|
└─ Trading Dashboard (:3085)
|
|
```
|
|
|
|
- **Traefik**: API gateway and reverse proxy.
|
|
- **Docker network**: All services connect via `learning_ai_common_plat_default`.
|
|
- **Domain routing**: Traefik routes by host header.
|
|
- **SSL/TLS**: Managed by Traefik with Let's Encrypt.
|
|
|
|
## Prerequisites
|
|
|
|
1. Platform stack running with Traefik gateway.
|
|
2. Docker and Docker Compose installed.
|
|
3. Domain names configured with DNS pointing to your server.
|
|
4. Azure Cosmos DB account (shared with platform-service).
|
|
5. Platform Service running and accessible.
|
|
|
|
## Quick Start
|
|
|
|
### 1. Start the platform stack (if not running)
|
|
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_common_plat
|
|
docker-compose up -d
|
|
```
|
|
|
|
### 2. Deploy the dashboards
|
|
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_devops_tools/dashboard
|
|
./deploy.sh
|
|
```
|
|
|
|
This will:
|
|
- Deploy the DevOps Dashboard (backend + web)
|
|
- Deploy the Admin Dashboard via the platform stack
|
|
- Run health checks
|
|
- Print deployment information
|
|
|
|
## Local development
|
|
|
|
If you only need a non-containerized iteration loop (no Traefik, no Docker):
|
|
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_devops_tools/dashboard
|
|
|
|
# Resolve workspace deps
|
|
pnpm install:common-plat # uses sibling learning_ai_common_plat checkout
|
|
# or
|
|
pnpm install:gitea # uses local Gitea registry at localhost:3300
|
|
|
|
pnpm dev # backend on 4004, web on 3000 (NOT 3049)
|
|
```
|
|
|
|
Required env vars are documented under **Environment Configuration** below; for
|
|
local dev a minimal `.env` with `JWT_SECRET`, `COSMOS_*`, and
|
|
`PLATFORM_SERVICE_URL` is enough.
|
|
|
|
## Manual Docker deployment
|
|
|
|
### Deploy DevOps Dashboard
|
|
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_devops_tools/dashboard
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
### Deploy Admin Dashboard
|
|
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_common_plat
|
|
docker-compose up -d admin-web
|
|
```
|
|
|
|
## Environment Configuration
|
|
|
|
### DevOps Dashboard (`.env`)
|
|
|
|
```bash
|
|
# Backend
|
|
PORT=4004
|
|
PLATFORM_SERVICE_URL=http://platform-service:4003
|
|
COSMOS_ENDPOINT=https://your-cosmos-account.documents.azure.com:443/
|
|
COSMOS_KEY=your-cosmos-primary-key
|
|
COSMOS_DATABASE=bytelyst-platform
|
|
JWT_SECRET=your-production-jwt-secret
|
|
CSRF_SECRET=your-production-csrf-secret
|
|
ENCRYPTION_KEY=your-production-encryption-key
|
|
PRODUCT_ID=bytelyst-devops
|
|
PRODUCT_NAME=ByteLyst DevOps Dashboard
|
|
|
|
# Azure Key Vault (optional)
|
|
AZURE_TENANT_ID=your-tenant-id
|
|
AZURE_CLIENT_ID=your-client-id
|
|
AZURE_CLIENT_SECRET=your-client-secret
|
|
AZURE_KEY_VAULT_URL=https://your-keyvault.vault.azure.net/
|
|
|
|
# Frontend
|
|
NEXT_PUBLIC_DEVOPS_API_URL=https://api.bytelyst.com/devops
|
|
NEXT_PUBLIC_PLATFORM_URL=https://api.bytelyst.com/platform/api
|
|
NEXT_PUBLIC_ADMIN_WEB_URL=https://admin.bytelyst.com
|
|
NEXT_PUBLIC_PRODUCT_ID=bytelyst-devops
|
|
NEXT_PUBLIC_PRODUCT_NAME=ByteLyst DevOps Dashboard
|
|
```
|
|
|
|
### Platform Dashboard (`.env`)
|
|
|
|
Add to your platform `.env`:
|
|
|
|
```bash
|
|
# Admin Web Dashboard
|
|
NEXT_PUBLIC_PLATFORM_URL=https://api.bytelyst.com/platform/api
|
|
NEXT_PUBLIC_DEVOPS_WEB_URL=https://devops.bytelyst.com
|
|
```
|
|
|
|
## Traefik Configuration
|
|
|
|
Both dashboards use Traefik labels for routing.
|
|
|
|
### DevOps Web
|
|
|
|
```yaml
|
|
labels:
|
|
- 'traefik.enable=true'
|
|
- 'traefik.http.routers.devops-web.rule=Host(`devops.bytelyst.com`)'
|
|
- 'traefik.http.services.devops-web.loadbalancer.server.port=3000' # container port
|
|
```
|
|
|
|
### DevOps Backend API
|
|
|
|
```yaml
|
|
labels:
|
|
- 'traefik.enable=true'
|
|
- 'traefik.http.routers.devops-api.rule=PathPrefix(`/api/devops`)'
|
|
- 'traefik.http.services.devops-api.loadbalancer.server.port=4004'
|
|
```
|
|
|
|
### Admin Web
|
|
|
|
```yaml
|
|
labels:
|
|
- 'traefik.enable=true'
|
|
- 'traefik.http.routers.admin-web.rule=Host(`admin.bytelyst.com`)'
|
|
- 'traefik.http.services.admin-web.loadbalancer.server.port=3001'
|
|
```
|
|
|
|
## DNS Configuration
|
|
|
|
Add DNS records pointing to your Traefik gateway server:
|
|
|
|
```
|
|
devops.bytelyst.com A <your-server-ip>
|
|
admin.bytelyst.com A <your-server-ip>
|
|
api.bytelyst.com A <your-server-ip>
|
|
```
|
|
|
|
## SSL/TLS Configuration
|
|
|
|
Traefik can automatically handle SSL certificates with Let's Encrypt:
|
|
|
|
```yaml
|
|
command:
|
|
- '--certificatesresolvers.myresolver.acme.tlschallenge=true'
|
|
- '--certificatesresolvers.myresolver.acme.email=admin@bytelyst.com'
|
|
- '--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json'
|
|
```
|
|
|
|
Then update router labels:
|
|
|
|
```yaml
|
|
labels:
|
|
- 'traefik.http.routers.devops-web.tls=true'
|
|
- 'traefik.http.routers.devops-web.tls.certresolver=myresolver'
|
|
```
|
|
|
|
## Cross-Navigation
|
|
|
|
### DevOps Dashboard → Admin Dashboard
|
|
- Header includes a "Platform Admin" link with Shield icon.
|
|
- Opens admin dashboard in a new tab.
|
|
- Uses `NEXT_PUBLIC_ADMIN_WEB_URL`.
|
|
|
|
### Admin Dashboard → DevOps Dashboard
|
|
- Sidebar includes a "DevOps Dashboard" link with Server icon.
|
|
- Opens devops dashboard in a new tab.
|
|
- Uses `NEXT_PUBLIC_DEVOPS_WEB_URL`.
|
|
|
|
## Shared Authentication
|
|
|
|
1. **Platform Service Auth**: Both authenticate against platform-service.
|
|
2. **JWT Tokens**: Same `JWT_SECRET` validates tokens across services.
|
|
3. **Per-Product Access**: Admin access is checked per-product via membership roles.
|
|
4. **Single Sign-On**: Users stay logged in across both dashboards.
|
|
|
|
### Granting Access
|
|
|
|
To grant a user access to both dashboards:
|
|
|
|
1. Ensure user exists in platform-service.
|
|
2. Add admin membership for both products:
|
|
|
|
```json
|
|
{
|
|
"memberships": [
|
|
{ "productId": "bytelyst-devops", "role": "admin", "plan": "pro" },
|
|
{ "productId": "bytelyst-platform", "role": "admin", "plan": "pro" }
|
|
]
|
|
}
|
|
```
|
|
|
|
## Health Checks
|
|
|
|
- DevOps Backend: `http://localhost:4004/health`
|
|
- DevOps Web: `http://localhost:3049` (Docker Compose host port; container :3000)
|
|
- Admin Web: `http://localhost:3001`
|
|
- Traefik Dashboard: `http://localhost:8080`
|
|
|
|
## Troubleshooting
|
|
|
|
### Network issues
|
|
```bash
|
|
# Check if the platform network exists
|
|
docker network inspect learning_ai_common_plat_default
|
|
|
|
# Check container connectivity
|
|
docker network inspect learning_ai_common_plat_default | grep devops
|
|
```
|
|
|
|
### Traefik routing
|
|
```bash
|
|
# Traefik dashboard
|
|
http://localhost:8080
|
|
|
|
# Traefik logs
|
|
docker logs $(docker ps -q -f name=gateway)
|
|
|
|
# Router config for the devops web container
|
|
docker inspect devops-web | grep -A 10 Labels
|
|
```
|
|
|
|
### Authentication failures
|
|
- Verify `JWT_SECRET` matches across all services.
|
|
- Check platform-service is accessible: `curl http://localhost:4003/health`.
|
|
- Ensure the user has the right product memberships.
|
|
|
|
### Service not starting
|
|
```bash
|
|
docker logs devops-backend
|
|
docker logs devops-web
|
|
docker logs admin-web
|
|
docker ps
|
|
docker inspect devops-backend | grep -A 5 Health
|
|
```
|
|
|
|
### Workspace dependency errors
|
|
```bash
|
|
pnpm install:common-plat # local sibling checkout
|
|
pnpm install:gitea # local Gitea registry
|
|
```
|
|
|
|
## Service Management
|
|
|
|
### Stop services
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_devops_tools/dashboard
|
|
docker-compose down
|
|
|
|
cd /opt/bytelyst/learning_ai_common_plat
|
|
docker-compose stop admin-web
|
|
```
|
|
|
|
### Restart services
|
|
```bash
|
|
cd /opt/bytelyst/learning_ai_devops_tools/dashboard
|
|
docker-compose restart
|
|
|
|
cd /opt/bytelyst/learning_ai_common_plat
|
|
docker-compose restart admin-web
|
|
```
|
|
|
|
### View logs
|
|
```bash
|
|
# DevOps
|
|
docker logs -f devops-backend
|
|
docker logs -f devops-web
|
|
|
|
# Admin
|
|
docker logs -f admin-web
|
|
|
|
# Traefik
|
|
docker logs -f gateway
|
|
```
|
|
|
|
## Comparison with Trading Dashboard
|
|
|
|
| Feature | Trading | DevOps | Admin |
|
|
|--------------|----------------------|-------------------------|------------------------|
|
|
| Domain | invttrdg.bytelyst.com| devops.bytelyst.com | admin.bytelyst.com |
|
|
| Web Port | 3085 (host) | 3049 (host) / 3000 (ctr)| 3001 (host) |
|
|
| Backend Port | 4018 | 4004 | N/A |
|
|
| Network | platform_net | platform_net | default |
|
|
| Traefik | Yes | Yes | Yes |
|
|
| Auth | Platform | Platform | Platform |
|
|
|
|
## Production Checklist
|
|
|
|
- [ ] Platform stack running with Traefik.
|
|
- [ ] DNS records configured.
|
|
- [ ] SSL/TLS certificates configured in Traefik.
|
|
- [ ] Environment variables set for production.
|
|
- [ ] Cosmos DB connection configured.
|
|
- [ ] `JWT_SECRET` matches across all services.
|
|
- [ ] User memberships configured for access.
|
|
- [ ] Health checks passing.
|
|
- [ ] Cross-navigation links working.
|
|
- [ ] Monitoring and logging configured.
|
|
|
|
## Features Implemented
|
|
|
|
### Backend (port 4004)
|
|
- ✅ CI/CD pipeline with Gitea Actions
|
|
- ✅ E2E tests with Playwright (gated; see `.gitea/workflows/ci.yml`)
|
|
- ✅ Telemetry integration
|
|
- ✅ Error boundary
|
|
- ✅ CSRF protection with token refresh
|
|
- ✅ Service CRUD operations
|
|
- ✅ Deployment log retrieval (JSON polling — no SSE; see backend README)
|
|
- ✅ Audit logging
|
|
- ✅ Structured logging
|
|
- ✅ Database migrations
|
|
- ✅ Backup/restore functionality
|
|
- ✅ Performance monitoring (APM)
|
|
- ✅ System metrics (CPU, memory, disk)
|
|
- ✅ Docker cleanup endpoints
|
|
- ✅ OpenAPI/Swagger documentation at `/docs`
|
|
|
|
### Frontend (container :3000, host :3049 under Compose)
|
|
- ✅ Service management UI
|
|
- ✅ Deployment monitoring
|
|
- ✅ Health dashboard
|
|
- ✅ Metrics/charts page
|
|
- ✅ System management page
|
|
- ✅ Log viewer (poll-based)
|
|
- ✅ Accessibility features (ARIA, keyboard nav)
|
|
- ✅ PWA manifest
|
|
- ✅ Responsive design
|