feat: add ProxCenter swarm stack draft

This commit is contained in:
2026-06-05 16:33:09 +00:00
parent 4aee469478
commit 94e3608665
3 changed files with 221 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Real deployment environment files can contain secrets.
*.env
!.env.example
!*.env.example

163
proxcenter-compose.yml Normal file
View File

@@ -0,0 +1,163 @@
# ============================================
# ProxCenter Community Edition — Docker Swarm Stack
# ============================================
# Deploy (do NOT run until volumes/secrets exist):
# set -a; . ./proxcenter.env; set +a
# docker stack deploy -c proxcenter-compose.yml proxcenter
#
# Alternative if you prefer to render with docker compose first:
# docker compose --env-file proxcenter.env -f proxcenter-compose.yml config \
# | docker stack deploy -c - proxcenter
#
# Prerequisites — create external volumes before first deploy:
# docker volume create proxcenter_data
# docker volume create postgres_data
#
# Named volumes in Swarm are node-local by default. Both services are
# pinned to a labeled node so proxcenter_data and postgres_data stay on
# the same host. Label the intended primary Swarm node before deploying:
# docker node update --label-add proxcenter.storage=true <NODE_NAME>
# If you use a distributed volume driver (NFS/Longhorn/etc.), remove or
# change the placement constraints.
#
# Optional: use Docker Secrets instead of env vars for sensitive values.
# Create secrets before deploying, then uncomment the secrets: blocks:
# printf 'your-app-secret' | docker secret create app_secret -
# printf 'your-nextauth-secret' | docker secret create nextauth_secret -
# Then in the frontend service, swap the APP_SECRET / NEXTAUTH_SECRET
# env vars for APP_SECRET_FILE / NEXTAUTH_SECRET_FILE and uncomment
# the secrets: section on the service and at the bottom of this file.
# ============================================
services:
# ========================================
# Frontend (Next.js + WebSocket Proxy)
# ========================================
frontend:
image: ghcr.io/adminsyspro/proxcenter-frontend:${VERSION:-latest}
ports:
- "3000:3000"
environment:
- NODE_ENV=production
# Build the Postgres connection string from individual vars so
# POSTGRES_PASSWORD only needs to be set once (not duplicated in DATABASE_URL).
- DATABASE_URL=postgresql://${POSTGRES_USER:-proxcenter}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-proxcenter}?schema=public
- APP_SECRET=${APP_SECRET}
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- NEXTAUTH_URL=${NEXTAUTH_URL:-http://localhost:3000}
- APP_URL=${APP_URL:-http://localhost:3000}
# Docker Secrets alternative — comment out APP_SECRET / NEXTAUTH_SECRET above
# and uncomment these if you prefer file-based secrets:
# - APP_SECRET_FILE=/run/secrets/app_secret
# - NEXTAUTH_SECRET_FILE=/run/secrets/nextauth_secret
volumes:
- proxcenter_data:/app/data
# secrets:
# - app_secret
# - nextauth_secret
networks:
- proxcenter
# depends_on is intentionally omitted: it is ignored by docker stack deploy.
# Swarm relies on healthcheck + restart_policy to handle startup ordering.
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
deploy:
replicas: 1
placement:
constraints:
# Keep the node-local proxcenter_data volume on the intended primary node.
- node.labels.proxcenter.storage == true
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
window: 120s
update_config:
parallelism: 1
delay: 10s
order: start-first
failure_action: rollback
rollback_config:
parallelism: 1
delay: 5s
# ========================================
# Postgres (application database)
# ========================================
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=${POSTGRES_USER:-proxcenter}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB:-proxcenter}
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --locale=C
volumes:
- postgres_data:/var/lib/postgresql/data
# Port is intentionally not published. Postgres is reachable only
# over the internal overlay network. Uncomment to expose for debugging:
# ports:
# - "127.0.0.1:5432:5432"
networks:
- proxcenter
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-proxcenter} -d ${POSTGRES_DB:-proxcenter}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
window: 120s
update_config:
parallelism: 1
delay: 10s
# stop-first so the old container releases its data dir before the new one starts
order: stop-first
failure_action: rollback
rollback_config:
parallelism: 1
delay: 5s
placement:
constraints:
# Keep the node-local postgres_data volume on the intended primary node.
- node.labels.proxcenter.storage == true
# ========================================
# Networks
# ========================================
networks:
proxcenter:
driver: overlay
attachable: true
# ========================================
# Volumes (must be created externally)
# ========================================
# docker volume create proxcenter_data
# docker volume create postgres_data
volumes:
proxcenter_data:
external: true
postgres_data:
external: true
# ========================================
# Secrets (uncomment after creating them)
# ========================================
# printf 'your-app-secret' | docker secret create app_secret -
# printf 'your-nextauth-secret' | docker secret create nextauth_secret -
#
# secrets:
# app_secret:
# external: true
# nextauth_secret:
# external: true

54
proxcenter.env.example Normal file
View File

@@ -0,0 +1,54 @@
# ProxCenter Community Edition — Environment Variables
# Copy to proxcenter.env and fill in real values before deploying.
# Usage:
# cp proxcenter.env.example proxcenter.env
# edit proxcenter.env
# set -a; . ./proxcenter.env; set +a
# docker stack deploy -c proxcenter-compose.yml proxcenter
#
# Docker stack deploy does not support --env-file directly. If you do not
# want to source the env file, render the stack first:
# docker compose --env-file proxcenter.env -f proxcenter-compose.yml config \
# | docker stack deploy -c - proxcenter
#
# NEVER commit the real proxcenter.env file. Only commit this example.
# ========================================
# Image version pinning (optional)
# ========================================
# Leave commented to use the latest tag, or pin to a specific release:
# VERSION=1.2.3
VERSION=latest
# ========================================
# Application URLs
# ========================================
# Public-facing URL of your ProxCenter instance.
# Used for NextAuth callbacks, redirects, and link generation.
NEXTAUTH_URL=https://proxcenter.example.com
APP_URL=https://proxcenter.example.com
# ========================================
# Security secrets (required)
# ========================================
# Generate strong random values:
# openssl rand -base64 32
#
# Docker Secrets alternative: instead of setting these here, create
# Docker Swarm secrets and use APP_SECRET_FILE / NEXTAUTH_SECRET_FILE
# in the compose file. See comments in proxcenter-compose.yml.
APP_SECRET=change-me-generate-with-openssl-rand-base64-32
NEXTAUTH_SECRET=change-me-generate-with-openssl-rand-base64-32
# ========================================
# Postgres credentials (required)
# ========================================
# These are used by both the postgres service (to initialise the DB)
# and the frontend service (to build the DATABASE_URL connection string).
POSTGRES_USER=proxcenter
POSTGRES_PASSWORD=change-me-use-a-strong-password
POSTGRES_DB=proxcenter
# DATABASE_URL is built automatically from the variables above.
# Override only if pointing the frontend at an external Postgres instance:
# DATABASE_URL=postgresql://proxcenter:password@external-host:5432/proxcenter?schema=public