Merge pull request 'CUB-126: Update Control Center deployment for Go + React' (#40) from agent/pip/CUB-126-deployment-go-react into dev
All checks were successful
Dev Build / build-test (push) Successful in 1m26s
All checks were successful
Dev Build / build-test (push) Successful in 1m26s
This commit was merged in pull request #40.
This commit is contained in:
45
.env.example
Normal file
45
.env.example
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Control Center - Environment Variables
|
||||||
|
# ======================================
|
||||||
|
|
||||||
|
# ── Backend Variables ───────────────────────────────────────────────────
|
||||||
|
# Server configuration
|
||||||
|
PORT=8080
|
||||||
|
CORS_ORIGIN=http://localhost:3000
|
||||||
|
LOG_LEVEL=info
|
||||||
|
ENVIRONMENT=development
|
||||||
|
|
||||||
|
# Database connection (PostgreSQL DSN)
|
||||||
|
# Format: postgresql://user:password@host:port/database?sslmode=disable
|
||||||
|
DATABASE_URL=postgresql://controlcenter:controlcenter@localhost:5432/controlcenter?sslmode=disable
|
||||||
|
|
||||||
|
# Gateway (OpenClaw) connection
|
||||||
|
# URL to the OpenClaw gateway API for polling agent states
|
||||||
|
GATEWAY_URL=http://localhost:18789/api/agents
|
||||||
|
# Polling interval for agent state updates
|
||||||
|
GATEWAY_POLL_INTERVAL=5s
|
||||||
|
|
||||||
|
# ── Frontend Variables (via Vite) ───────────────────────────────────────
|
||||||
|
# The Vite config exposes these as import.meta.env.VITE_*
|
||||||
|
# Set via environment variable when building: VITE_API_URL
|
||||||
|
# VITE_API_URL=http://localhost:8080
|
||||||
|
|
||||||
|
# ── Docker Compose Specific ─────────────────────────────────────────────
|
||||||
|
# When using docker-compose, these are set in the services section
|
||||||
|
# See docker-compose.yml for service-specific environment variables
|
||||||
|
|
||||||
|
# ── Database Configuration ─────────────────────────────────────────────
|
||||||
|
# Set in the db service environment section of docker-compose.yml
|
||||||
|
# POSTGRES_USER=controlcenter
|
||||||
|
# POSTGRES_PASSWORD=controlcenter
|
||||||
|
# POSTGRES_DB=controlcenter
|
||||||
|
|
||||||
|
# ── Development Notes ───────────────────────────────────────────────────
|
||||||
|
# For local development without Docker:
|
||||||
|
# 1. Start PostgreSQL locally
|
||||||
|
# 2. Run: go run ./cmd/server/main.go
|
||||||
|
# 3. Run: npm run dev in frontend/
|
||||||
|
#
|
||||||
|
# For Docker deployment:
|
||||||
|
# 1. Copy .env.example to .env (backend only)
|
||||||
|
# 2. Run: docker compose up -d
|
||||||
|
# 3. Access frontend at http://localhost:3000
|
||||||
268
README-deployment.md
Normal file
268
README-deployment.md
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
# Control Center Deployment Guide
|
||||||
|
|
||||||
|
This document covers the Docker Compose deployment and kiosk configuration for the Control Center Go + React application.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start all services (backend, frontend, database)
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose logs -f
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
docker compose down
|
||||||
|
|
||||||
|
# Stop and remove volumes (database data)
|
||||||
|
docker compose down -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ Frontend │ Port 3000 (host) → 80 (container)
|
||||||
|
│ React + nginx │ Serves SPA, proxies /api/ to backend
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
│ HTTP
|
||||||
|
│
|
||||||
|
┌────────▼────────┐
|
||||||
|
│ Backend │ Port 8080 (host) → 8080 (container)
|
||||||
|
│ Go HTTP API │ PostgreSQL-backed REST API
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
│ PostgreSQL
|
||||||
|
│
|
||||||
|
┌────────▼────────┐
|
||||||
|
│ PostgreSQL │ Port 5432 (internal only)
|
||||||
|
│ Database │ Persistent volume at /var/lib/postgresql/data
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
### Backend (`go-backend`)
|
||||||
|
|
||||||
|
- **Image**: Custom `alpine:latest` with Go binary
|
||||||
|
- **Port**: 8080
|
||||||
|
- **Build**: Multi-stage from `go-backend/Dockerfile`
|
||||||
|
- **Environment Variables**:
|
||||||
|
- `PORT` (default: 8080)
|
||||||
|
- `DATABASE_URL` (PostgreSQL DSN)
|
||||||
|
- `CORS_ORIGIN` (default: `*`)
|
||||||
|
- `LOG_LEVEL` (default: `info`)
|
||||||
|
- `ENVIRONMENT` (default: `development`)
|
||||||
|
- `GATEWAY_URL` (OpenClaw gateway endpoint)
|
||||||
|
|
||||||
|
### Frontend (`frontend`)
|
||||||
|
|
||||||
|
- **Image**: `nginx:1.27-alpine`
|
||||||
|
- **Port**: 80 (internal) → 3000 (host)
|
||||||
|
- **Build**: Multi-stage from `frontend/Dockerfile`
|
||||||
|
- Node 22 for build
|
||||||
|
- Nginx 1.27 for serving
|
||||||
|
- **Config**: Custom nginx config in `frontend/nginx.conf`
|
||||||
|
- **Environment Variables**:
|
||||||
|
- `VITE_API_URL` (passed at build time via Vite config)
|
||||||
|
|
||||||
|
### Database (`db`)
|
||||||
|
|
||||||
|
- **Image**: `postgres:16-alpine`
|
||||||
|
- **Port**: 5432 (internal only)
|
||||||
|
- **Volume**: `postgres-data:/var/lib/postgresql/data`
|
||||||
|
- **Environment Variables**:
|
||||||
|
- `POSTGRES_USER` (default: `controlcenter`)
|
||||||
|
- `POSTGRES_PASSWORD` (default: `controlcenter`)
|
||||||
|
- `POSTGRES_DB` (default: `controlcenter`)
|
||||||
|
|
||||||
|
## Kiosk Mode
|
||||||
|
|
||||||
|
For dedicated display installations (e.g., control center dashboard), Chromium can run in kiosk mode.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
1. **Install the systemd service** (on Debian/Ubuntu with systemd):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo cp kiosk/control-center-kiosk.service /etc/systemd/system/
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Enable auto-start**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable control-center-kiosk
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start the service**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl start control-center-kiosk
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Check status and logs**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl status control-center-kiosk
|
||||||
|
sudo journalctl -u control-center-kiosk -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Launch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From project root
|
||||||
|
./kiosk/start-kiosk.sh http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop and disable service
|
||||||
|
sudo systemctl stop control-center-kiosk
|
||||||
|
sudo systemctl disable control-center-kiosk
|
||||||
|
sudo rm /etc/systemd/system/control-center-kiosk.service
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kiosk Requirements
|
||||||
|
|
||||||
|
- **Browser**: `chromium-browser` (install via `apt-get install chromium`)
|
||||||
|
- **Display**: X11 session with `DISPLAY=:0`
|
||||||
|
- **User**: Must run as a user with X11 access (typically `overseer`)
|
||||||
|
- **Permissions**: Read access to the project directory
|
||||||
|
|
||||||
|
## Environment Variables Reference
|
||||||
|
|
||||||
|
### Backend (`go-backend/.env`)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PORT=8080
|
||||||
|
DATABASE_URL=postgresql://controlcenter:controlcenter@localhost:5432/controlcenter?sslmode=disable
|
||||||
|
CORS_ORIGIN=*
|
||||||
|
LOG_LEVEL=info
|
||||||
|
ENVIRONMENT=development
|
||||||
|
GATEWAY_URL=http://localhost:18789/api/agents
|
||||||
|
GATEWAY_POLL_INTERVAL=5s
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend (build-time)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VITE_API_URL=http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
Set via `services.<name>.environment` in `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=...
|
||||||
|
frontend:
|
||||||
|
environment:
|
||||||
|
- VITE_API_URL=...
|
||||||
|
db:
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=...
|
||||||
|
- POSTGRES_PASSWORD=...
|
||||||
|
- POSTGRES_DB=...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Local Development (non-Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend
|
||||||
|
cd go-backend
|
||||||
|
go run ./cmd/server/main.go
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Migrations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# If using pgx/migrate or similar
|
||||||
|
# The database is created automatically on first connection if it doesn't exist
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backend won't connect to database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check database container status
|
||||||
|
docker compose ps
|
||||||
|
|
||||||
|
# View database logs
|
||||||
|
docker compose logs db
|
||||||
|
|
||||||
|
# Test database connectivity from backend
|
||||||
|
docker compose exec backend ping db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend can't reach backend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check network connectivity
|
||||||
|
docker compose exec frontend ping backend
|
||||||
|
|
||||||
|
# Verify backend is running
|
||||||
|
docker compose logs backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kiosk browser won't start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Chromium installation
|
||||||
|
which chromium-browser
|
||||||
|
|
||||||
|
# Check X11 forwarding
|
||||||
|
echo $DISPLAY
|
||||||
|
|
||||||
|
# Manual launch for debugging
|
||||||
|
./kiosk/start-kiosk.sh http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port conflicts
|
||||||
|
|
||||||
|
If ports 8080, 3000, or 5432 are already in use, modify `docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
ports:
|
||||||
|
- "8081:8080" # Change host port
|
||||||
|
frontend:
|
||||||
|
ports:
|
||||||
|
- "3001:80" # Change host port
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Considerations
|
||||||
|
|
||||||
|
1. **HTTPS**: Add a reverse proxy (nginx/Traefik) for SSL termination
|
||||||
|
2. **Database security**: Use strong passwords, enable SSL
|
||||||
|
3. **CORS**: Restrict `CORS_ORIGIN` to production domain
|
||||||
|
4. **Logs**: Configure log aggregation (e.g., ELK, Loki)
|
||||||
|
5. **Backups**: Regular PostgreSQL volume backups
|
||||||
|
6. **Monitoring**: Add health checks and alerting
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File/Directory | Purpose |
|
||||||
|
|----------------|---------|
|
||||||
|
| `docker-compose.yml` | Service definitions and configuration |
|
||||||
|
| `.env.example` | Environment variable template |
|
||||||
|
| `go-backend/Dockerfile` | Backend build definition |
|
||||||
|
| `frontend/Dockerfile` | Frontend build definition |
|
||||||
|
| `frontend/nginx.conf` | Nginx config for SPA routing |
|
||||||
|
| `kiosk/start-kiosk.sh` | Kiosk browser startup script |
|
||||||
|
| `kiosk/control-center-kiosk.service` | Systemd unit for auto-start |
|
||||||
72
docker-compose.yml
Normal file
72
docker-compose.yml
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Control Center - Go + React + PostgreSQL Deployment
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ── Backend Service (Go) ───────────────────────────────────────────────
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./go-backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgresql://controlcenter:controlcenter@db:5432/controlcenter?sslmode=disable
|
||||||
|
- CORS_ORIGIN=http://localhost:3000
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
- ENVIRONMENT=production
|
||||||
|
- PORT=8080
|
||||||
|
- GATEWAY_URL=http://host.docker.internal:18789/api/agents
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- control-center-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Frontend Service (React) ───────────────────────────────────────────
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
environment:
|
||||||
|
- VITE_API_URL=http://localhost:8080
|
||||||
|
networks:
|
||||||
|
- control-center-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Database Service (PostgreSQL 16) ───────────────────────────────────
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: control-center-db
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=controlcenter
|
||||||
|
- POSTGRES_PASSWORD=controlcenter
|
||||||
|
- POSTGRES_DB=controlcenter
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U controlcenter -d controlcenter"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
networks:
|
||||||
|
- control-center-network
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
control-center-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
42
kiosk/control-center-kiosk.service
Normal file
42
kiosk/control-center-kiosk.service
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Control Center Kiosk Service
|
||||||
|
# =============================
|
||||||
|
# Systemd unit file for auto-starting the Control Center kiosk on boot
|
||||||
|
#
|
||||||
|
# Install: sudo cp control-center-kiosk.service /etc/systemd/system/
|
||||||
|
# Enable: sudo systemctl enable control-center-kiosk
|
||||||
|
# Start: sudo systemctl start control-center-kiosk
|
||||||
|
# Status: sudo systemctl status control-center-kiosk
|
||||||
|
# Logs: sudo journalctl -u control-center-kiosk -f
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Control Center Kiosk - Chrome Browser Dashboard
|
||||||
|
Documentation=https://code.cubecraftcreations.com/CubeCraft-Creations/Control-Center
|
||||||
|
After=graphical-session.target network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/home/overseer/projects/Control-Center/kiosk/start-kiosk.sh http://localhost:3000
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
Environment=DISPLAY=:0
|
||||||
|
Environment=XAUTHORITY=/home/overseer/.Xauthority
|
||||||
|
WorkingDirectory=/home/overseer/projects/Control-Center
|
||||||
|
User=overseer
|
||||||
|
Group=overseer
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=control-center-kiosk
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ReadWritePaths=/home/overseer/.config/chromium
|
||||||
|
ReadWritePaths=/var/log/journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=graphical-session.target
|
||||||
88
kiosk/start-kiosk.sh
Executable file
88
kiosk/start-kiosk.sh
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Control Center Kiosk Startup Script
|
||||||
|
# ====================================
|
||||||
|
# This script launches Chromium in kiosk mode for the Control Center dashboard
|
||||||
|
# Usage: ./start-kiosk.sh [frontend-url]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FRONTEND_URL="${1:-http://localhost:3000}"
|
||||||
|
BROWSER_WINDOW="chromium-browser"
|
||||||
|
|
||||||
|
# ── Functions ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
log "Stopping kiosk browser..."
|
||||||
|
pkill -f "chromium-browser.*--kiosk" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT SIGTERM
|
||||||
|
|
||||||
|
# ── Check prerequisites ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
check_browser() {
|
||||||
|
if ! command -v chromium-browser &> /dev/null; then
|
||||||
|
log "ERROR: chromium-browser not found"
|
||||||
|
log "Install with: sudo apt-get install chromium"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_x_server() {
|
||||||
|
if [ -z "$DISPLAY" ]; then
|
||||||
|
log "ERROR: DISPLAY environment variable not set"
|
||||||
|
log "This script requires an X server session"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Main ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
main() {
|
||||||
|
log "Starting Control Center Kiosk..."
|
||||||
|
log "Frontend URL: $FRONTEND_URL"
|
||||||
|
|
||||||
|
check_browser
|
||||||
|
check_x_server
|
||||||
|
|
||||||
|
# Clean up any existing browser instances
|
||||||
|
cleanup
|
||||||
|
|
||||||
|
# Launch Chromium in kiosk mode
|
||||||
|
# --kiosk: Fullscreen without browser UI
|
||||||
|
# --incognito: Clean session
|
||||||
|
# --noerrdialogs: Suppress error dialogs
|
||||||
|
# --disable-notifications: Disable notifications
|
||||||
|
# --disable-extensions: Disable extensions
|
||||||
|
# --disable-plugins-discovery: Disable plugins
|
||||||
|
# --disable-sync: Disable sync
|
||||||
|
# --disable-web-security: Allow CORS (needed for local API calls)
|
||||||
|
# --ignore-certificate-errors: Ignore SSL errors (for local dev)
|
||||||
|
# --gpu: Enable GPU acceleration
|
||||||
|
# --start-fullscreen: Start in fullscreen mode
|
||||||
|
chromium-browser \
|
||||||
|
--kiosk \
|
||||||
|
--incognito \
|
||||||
|
--noerrdialogs \
|
||||||
|
--disable-notifications \
|
||||||
|
--disable-extensions \
|
||||||
|
--disable-plugins-discovery \
|
||||||
|
--disable-sync \
|
||||||
|
--disable-web-security \
|
||||||
|
--ignore-certificate-errors \
|
||||||
|
--gpu \
|
||||||
|
--start-fullscreen \
|
||||||
|
"$FRONTEND_URL" &
|
||||||
|
|
||||||
|
KIOSK_PID=$!
|
||||||
|
log "Kiosk browser started (PID: $KIOSK_PID)"
|
||||||
|
|
||||||
|
# Wait for browser to exit
|
||||||
|
wait $KIOSK_PID
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user