- Modern web interface for Supervisor process management - Built with Next.js 16 (App Router) and Tailwind CSS 4 - Full XML-RPC client implementation for Supervisor API - Real-time process monitoring with auto-refresh - Process control: start, stop, restart operations - Modern dashboard with system status and statistics - Dark/light theme with OKLCH color system - Docker multi-stage build with runtime env var configuration - Gitea CI/CD workflow for automated builds - Comprehensive documentation (README, IMPLEMENTATION, DEPLOYMENT) Features: - Backend proxy pattern for secure API communication - React Query for state management and caching - TypeScript strict mode with Zod validation - Responsive design with mobile support - Health check endpoint for monitoring - Non-root user security in Docker Environment Variables: - SUPERVISOR_HOST, SUPERVISOR_PORT - SUPERVISOR_USERNAME, SUPERVISOR_PASSWORD (optional) - Configurable at build-time and runtime 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
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:
- Runtime (highest priority) - Docker run
-eflags or docker-compose environment - Build-time - Docker build
--build-argflags - Dockerfile defaults (lowest priority)
Docker Build Arguments
You can customize the build with build arguments:
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
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:
SUPERVISOR_HOST=supervisor.example.com
SUPERVISOR_PORT=9001
SUPERVISOR_USERNAME=admin
SUPERVISOR_PASSWORD=secret
Run with env file:
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:
SUPERVISOR_HOST=supervisor.example.com
SUPERVISOR_PORT=9001
SUPERVISOR_USERNAME=admin
SUPERVISOR_PASSWORD=secret
The docker-compose.yml automatically picks up these variables:
docker-compose up -d
Option 4: Docker Compose with Inline Environment
Edit docker-compose.yml:
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:
- Push to main branch → Tagged as
latestandmain-<sha> - Push to develop branch → Tagged as
developanddevelop-<sha> - Git tags (v*.. pattern) → Tagged as version (e.g.,
v1.0.0,1.0,1) - Pull requests → Built but not pushed (validation only)
- 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
- Go to Gitea Settings → Applications → Generate New Token
- Name:
GitHub Actions Registry - Select scope:
write:package - Copy the generated token
- Go to Repository Settings → Secrets → Add Secret
- Name:
REGISTRY_TOKEN - Value: Paste the token
Registry Authentication
To pull images from the Gitea registry:
# 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:
# 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:
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:
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:
# 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:
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:
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:
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):
docker build --build-arg SUPERVISOR_PASSWORD=secret .
Good (credentials at runtime):
docker run -e SUPERVISOR_PASSWORD=secret ...
Better (use secrets management):
# Docker Swarm secrets
echo "secret_password" | docker secret create supervisor_password -
2. Network Isolation
Use Docker networks to isolate services:
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:
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:
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:
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:
docker inspect supervisor-ui --format='{{.State.Health.Status}}'
Integration with Monitoring Tools
Prometheus
Add health check as a target in prometheus.yml:
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:
docker logs supervisor-ui
Common issues:
- Port 3000 already in use
- Invalid environment variables
- Network connectivity issues
Can't connect to Supervisor
- Check if Supervisor is accessible:
# From host
curl http://supervisor-host:9001/RPC2
# From container
docker exec supervisor-ui curl http://supervisor-host:9001/RPC2
- Verify Supervisor configuration in
/etc/supervisor/supervisord.conf:
[inet_http_server]
port = *:9001 ; Listen on all interfaces, not just 127.0.0.1
- Check environment variables:
docker exec supervisor-ui env | grep SUPERVISOR
Authentication failures
Verify credentials match your Supervisor configuration:
# Test with curl
curl -u username:password http://supervisor-host:9001/RPC2
Rollback Strategy
Quick Rollback to Previous Version
# 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
# 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:
- Save your
.envfile or docker-compose.yml - Document your Supervisor connection details
To "restore":
- Pull the image
- Apply your saved environment configuration
- Start the container
Performance Tuning
Node.js Optimization
For better performance in production:
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:
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:
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