Files
supervisor-ui/DEPLOYMENT.md

551 lines
12 KiB
Markdown
Raw Normal View History

# Deployment Guide - Supervisor UI
## Environment Variables
The Supervisor UI supports flexible configuration through environment variables that can be set at both build-time and runtime.
### Available Environment Variables
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `SUPERVISOR_HOST` | Supervisor API host/IP address | `localhost` | Yes |
| `SUPERVISOR_PORT` | Supervisor API port | `9001` | Yes |
| `SUPERVISOR_USERNAME` | Basic auth username (if enabled) | - | No |
| `SUPERVISOR_PASSWORD` | Basic auth password (if enabled) | - | No |
| `NODE_ENV` | Node environment | `production` | No |
| `PORT` | Application port | `3000` | No |
### Configuration Priority
Environment variables can be set at different stages, with runtime taking precedence:
1. **Runtime** (highest priority) - Docker run `-e` flags or docker-compose environment
2. **Build-time** - Docker build `--build-arg` flags
3. **Dockerfile defaults** (lowest priority)
## Docker Build Arguments
You can customize the build with build arguments:
```bash
docker build -t supervisor-ui \
--build-arg SUPERVISOR_HOST=supervisor.example.com \
--build-arg SUPERVISOR_PORT=9001 \
--build-arg SUPERVISOR_USERNAME=admin \
--build-arg SUPERVISOR_PASSWORD=secret \
.
```
**Note**: Build arguments are embedded in the image layer. For sensitive credentials, prefer runtime environment variables.
## Docker Runtime Configuration
### Option 1: Environment Variables via Docker Run
```bash
docker run -d \
--name supervisor-ui \
-p 3000:3000 \
-e SUPERVISOR_HOST=supervisor.example.com \
-e SUPERVISOR_PORT=9001 \
-e SUPERVISOR_USERNAME=admin \
-e SUPERVISOR_PASSWORD=secret \
dev.pivoine.art/valknar/supervisor-ui:latest
```
### Option 2: Environment File
Create an `.env` file:
```env
SUPERVISOR_HOST=supervisor.example.com
SUPERVISOR_PORT=9001
SUPERVISOR_USERNAME=admin
SUPERVISOR_PASSWORD=secret
```
Run with env file:
```bash
docker run -d \
--name supervisor-ui \
-p 3000:3000 \
--env-file .env \
dev.pivoine.art/valknar/supervisor-ui:latest
```
### Option 3: Docker Compose
Create a `.env` file in the same directory as `docker-compose.yml`:
```env
SUPERVISOR_HOST=supervisor.example.com
SUPERVISOR_PORT=9001
SUPERVISOR_USERNAME=admin
SUPERVISOR_PASSWORD=secret
```
The `docker-compose.yml` automatically picks up these variables:
```bash
docker-compose up -d
```
### Option 4: Docker Compose with Inline Environment
Edit `docker-compose.yml`:
```yaml
services:
supervisor-ui:
image: dev.pivoine.art/valknar/supervisor-ui:latest
environment:
- SUPERVISOR_HOST=supervisor.example.com
- SUPERVISOR_PORT=9001
- SUPERVISOR_USERNAME=admin
- SUPERVISOR_PASSWORD=secret
```
## CI/CD - Gitea Workflows
### Automatic Builds
The project includes a Gitea Actions workflow that automatically builds and pushes Docker images to the Gitea registry.
**Workflow file**: `.gitea/workflows/docker-build-push.yml`
### Trigger Events
Images are built and pushed on:
1. **Push to main branch** → Tagged as `latest` and `main-<sha>`
2. **Push to develop branch** → Tagged as `develop` and `develop-<sha>`
3. **Git tags** (v*.*.* pattern) → Tagged as version (e.g., `v1.0.0`, `1.0`, `1`)
4. **Pull requests** → Built but not pushed (validation only)
5. **Manual workflow dispatch** → Custom tag specified by user
### Workflow Secrets
The workflow requires one secret to be configured in your Gitea repository:
- `REGISTRY_TOKEN` - Gitea personal access token with registry push permissions
#### Creating the Registry Token
1. Go to Gitea Settings → Applications → Generate New Token
2. Name: `GitHub Actions Registry`
3. Select scope: `write:package`
4. Copy the generated token
5. Go to Repository Settings → Secrets → Add Secret
6. Name: `REGISTRY_TOKEN`
7. Value: Paste the token
### Registry Authentication
To pull images from the Gitea registry:
```bash
# Login to registry
docker login dev.pivoine.art
# Pull image
docker pull dev.pivoine.art/valknar/supervisor-ui:latest
```
### Image Tags
After pushing to main, the following tags are available:
```bash
# Latest stable
dev.pivoine.art/valknar/supervisor-ui:latest
# Specific commit
dev.pivoine.art/valknar/supervisor-ui:main-abc1234
# Version tags (from git tags)
dev.pivoine.art/valknar/supervisor-ui:v1.0.0
dev.pivoine.art/valknar/supervisor-ui:1.0
dev.pivoine.art/valknar/supervisor-ui:1
# Development branch
dev.pivoine.art/valknar/supervisor-ui:develop
```
## Production Deployment Scenarios
### Scenario 1: Supervisor on Same Host
Deploy UI on the same host as Supervisor:
```bash
docker run -d \
--name supervisor-ui \
--network host \
-e SUPERVISOR_HOST=localhost \
-e SUPERVISOR_PORT=9001 \
dev.pivoine.art/valknar/supervisor-ui:latest
```
Using `--network host` allows the container to access localhost services.
### Scenario 2: Supervisor on Different Host
Deploy UI on a different host:
```bash
docker run -d \
--name supervisor-ui \
-p 3000:3000 \
-e SUPERVISOR_HOST=192.168.1.100 \
-e SUPERVISOR_PORT=9001 \
dev.pivoine.art/valknar/supervisor-ui:latest
```
Ensure the Supervisor inet_http_server is accessible from the UI host (not bound to 127.0.0.1).
### Scenario 3: Multiple Supervisor Instances (Future)
While the current version connects to a single instance, you can run multiple UI containers:
```bash
# Production Supervisor UI
docker run -d \
--name supervisor-ui-prod \
-p 3000:3000 \
-e SUPERVISOR_HOST=prod.supervisor.local \
dev.pivoine.art/valknar/supervisor-ui:latest
# Staging Supervisor UI
docker run -d \
--name supervisor-ui-staging \
-p 3001:3000 \
-e SUPERVISOR_HOST=staging.supervisor.local \
dev.pivoine.art/valknar/supervisor-ui:latest
```
### Scenario 4: Behind Reverse Proxy (nginx/Traefik)
Example nginx configuration:
```nginx
server {
listen 80;
server_name supervisor.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Example Traefik docker-compose labels:
```yaml
services:
supervisor-ui:
image: dev.pivoine.art/valknar/supervisor-ui:latest
environment:
- SUPERVISOR_HOST=supervisor.local
- SUPERVISOR_PORT=9001
labels:
- "traefik.enable=true"
- "traefik.http.routers.supervisor-ui.rule=Host(`supervisor.example.com`)"
- "traefik.http.routers.supervisor-ui.entrypoints=websecure"
- "traefik.http.routers.supervisor-ui.tls.certresolver=letsencrypt"
- "traefik.http.services.supervisor-ui.loadbalancer.server.port=3000"
```
### Scenario 5: Docker Compose Stack
Complete production-ready stack with reverse proxy:
```yaml
version: '3.8'
services:
supervisor-ui:
image: dev.pivoine.art/valknar/supervisor-ui:latest
container_name: supervisor-ui
restart: unless-stopped
environment:
- SUPERVISOR_HOST=${SUPERVISOR_HOST}
- SUPERVISOR_PORT=${SUPERVISOR_PORT}
- SUPERVISOR_USERNAME=${SUPERVISOR_USERNAME}
- SUPERVISOR_PASSWORD=${SUPERVISOR_PASSWORD}
networks:
- supervisor-network
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
labels:
- "traefik.enable=true"
- "traefik.http.routers.supervisor-ui.rule=Host(`supervisor.yourdomain.com`)"
- "traefik.http.services.supervisor-ui.loadbalancer.server.port=3000"
networks:
supervisor-network:
external: true
```
## Security Considerations
### 1. Credentials Management
**Bad** (credentials in image):
```bash
docker build --build-arg SUPERVISOR_PASSWORD=secret .
```
**Good** (credentials at runtime):
```bash
docker run -e SUPERVISOR_PASSWORD=secret ...
```
**Better** (use secrets management):
```bash
# Docker Swarm secrets
echo "secret_password" | docker secret create supervisor_password -
```
### 2. Network Isolation
Use Docker networks to isolate services:
```yaml
services:
supervisor-ui:
networks:
- internal # Only accessible from other containers
nginx:
networks:
- internal
- public # Exposed to internet
```
### 3. Read-only Filesystem
For enhanced security, run with read-only root filesystem:
```bash
docker run -d \
--read-only \
--tmpfs /tmp \
-e SUPERVISOR_HOST=supervisor.local \
dev.pivoine.art/valknar/supervisor-ui:latest
```
### 4. Resource Limits
Prevent resource exhaustion:
```yaml
services:
supervisor-ui:
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
```
## Monitoring & Health Checks
### Health Check Endpoint
The application provides a health check at `/api/health`:
```bash
curl http://localhost:3000/api/health
# {"status":"healthy","timestamp":"2025-11-23T17:00:00.000Z"}
```
### Docker Health Check
Built-in health check monitors the API:
```bash
docker inspect supervisor-ui --format='{{.State.Health.Status}}'
```
### Integration with Monitoring Tools
#### Prometheus
Add health check as a target in `prometheus.yml`:
```yaml
scrape_configs:
- job_name: 'supervisor-ui'
metrics_path: '/api/health'
static_configs:
- targets: ['supervisor-ui:3000']
```
#### Uptime Kuma
Add HTTP(s) monitor:
- Monitor Type: HTTP(s)
- URL: `http://supervisor-ui:3000/api/health`
- Interval: 60 seconds
## Troubleshooting
### Container won't start
Check logs:
```bash
docker logs supervisor-ui
```
Common issues:
- Port 3000 already in use
- Invalid environment variables
- Network connectivity issues
### Can't connect to Supervisor
1. Check if Supervisor is accessible:
```bash
# From host
curl http://supervisor-host:9001/RPC2
# From container
docker exec supervisor-ui curl http://supervisor-host:9001/RPC2
```
2. Verify Supervisor configuration in `/etc/supervisor/supervisord.conf`:
```ini
[inet_http_server]
port = *:9001 ; Listen on all interfaces, not just 127.0.0.1
```
3. Check environment variables:
```bash
docker exec supervisor-ui env | grep SUPERVISOR
```
### Authentication failures
Verify credentials match your Supervisor configuration:
```bash
# Test with curl
curl -u username:password http://supervisor-host:9001/RPC2
```
## Rollback Strategy
### Quick Rollback to Previous Version
```bash
# Stop current version
docker stop supervisor-ui
docker rm supervisor-ui
# Run previous version
docker run -d \
--name supervisor-ui \
-p 3000:3000 \
--env-file .env \
dev.pivoine.art/valknar/supervisor-ui:v1.0.0 # Specific version
```
### Using Docker Compose
```bash
# Edit docker-compose.yml to use previous tag
# Then:
docker-compose up -d --force-recreate
```
## Backup & Recovery
### No Persistent Data
The Supervisor UI is stateless and doesn't store any data. All configuration is in environment variables.
To "backup" your deployment:
1. Save your `.env` file or docker-compose.yml
2. Document your Supervisor connection details
To "restore":
1. Pull the image
2. Apply your saved environment configuration
3. Start the container
## Performance Tuning
### Node.js Optimization
For better performance in production:
```bash
docker run -d \
-e NODE_OPTIONS="--max-old-space-size=256" \
-e SUPERVISOR_HOST=supervisor.local \
dev.pivoine.art/valknar/supervisor-ui:latest
```
### Caching Strategies
The application uses React Query with intelligent caching:
- System info: 5 second stale time
- Processes: 3 second stale time
- Logs: 2 second stale time
These are optimized for real-time monitoring while minimizing API calls.
## Scaling Considerations
### Horizontal Scaling
The application is stateless and can be scaled horizontally:
```yaml
services:
supervisor-ui:
image: dev.pivoine.art/valknar/supervisor-ui:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
```
### Load Balancing
Use nginx or Traefik to load balance across replicas:
```nginx
upstream supervisor_ui {
server supervisor-ui-1:3000;
server supervisor-ui-2:3000;
server supervisor-ui-3:3000;
}
server {
location / {
proxy_pass http://supervisor_ui;
}
}
```
---
**Last Updated**: November 23, 2025
**Version**: 0.1.0