refactor(installer): replace sh compose generation with template copying
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -603,12 +603,22 @@ BOOTSTRAP_TOKEN=$(generate_password)
|
|||||||
# Docker
|
# Docker
|
||||||
DOCKER_SOCKET=${DOCKER_SOCKET}
|
DOCKER_SOCKET=${DOCKER_SOCKET}
|
||||||
DOCKER_GID=$(stat -c '%g' "${DOCKER_SOCKET}" 2>/dev/null || echo "0")
|
DOCKER_GID=$(stat -c '%g' "${DOCKER_SOCKET}" 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
POSTGRES_IMAGE=postgres:16-alpine
|
||||||
|
|
||||||
|
# Compose file assembly
|
||||||
|
COMPOSE_FILE=docker-compose.yml:docker-compose.server.yml$([ "$TLS_MODE" = "custom" ] && echo ":docker-compose.tls.yml")$([ -n "$MONITORING_NETWORK" ] && echo ":docker-compose.monitoring.yml")
|
||||||
EOF
|
EOF
|
||||||
if [ "$TLS_MODE" = "custom" ]; then
|
if [ "$TLS_MODE" = "custom" ]; then
|
||||||
echo "CERT_FILE=/user-certs/cert.pem" >> "$f"
|
echo "CERT_FILE=/user-certs/cert.pem" >> "$f"
|
||||||
echo "KEY_FILE=/user-certs/key.pem" >> "$f"
|
echo "KEY_FILE=/user-certs/key.pem" >> "$f"
|
||||||
[ -n "$CA_FILE" ] && echo "CA_FILE=/user-certs/ca.pem" >> "$f"
|
[ -n "$CA_FILE" ] && echo "CA_FILE=/user-certs/ca.pem" >> "$f"
|
||||||
fi
|
fi
|
||||||
|
if [ -n "$MONITORING_NETWORK" ]; then
|
||||||
|
echo "" >> "$f"
|
||||||
|
echo "# Monitoring" >> "$f"
|
||||||
|
echo "MONITORING_NETWORK=${MONITORING_NETWORK}" >> "$f"
|
||||||
|
fi
|
||||||
log_info "Generated .env"
|
log_info "Generated .env"
|
||||||
cp "$f" "$INSTALL_DIR/.env.bak"
|
cp "$f" "$INSTALL_DIR/.env.bak"
|
||||||
return
|
return
|
||||||
@@ -629,6 +639,7 @@ PUBLIC_PROTOCOL=${PUBLIC_PROTOCOL}
|
|||||||
HTTP_PORT=${HTTP_PORT}
|
HTTP_PORT=${HTTP_PORT}
|
||||||
HTTPS_PORT=${HTTPS_PORT}
|
HTTPS_PORT=${HTTPS_PORT}
|
||||||
LOGTO_CONSOLE_PORT=${LOGTO_CONSOLE_PORT}
|
LOGTO_CONSOLE_PORT=${LOGTO_CONSOLE_PORT}
|
||||||
|
LOGTO_CONSOLE_BIND=$([ "$LOGTO_CONSOLE_EXPOSED" = "true" ] && echo "0.0.0.0" || echo "127.0.0.1")
|
||||||
|
|
||||||
# PostgreSQL
|
# PostgreSQL
|
||||||
POSTGRES_USER=cameleer
|
POSTGRES_USER=cameleer
|
||||||
@@ -665,473 +676,46 @@ DOCKER_GID=$(stat -c '%g' "${DOCKER_SOCKET}" 2>/dev/null || echo "0")
|
|||||||
# Provisioning images
|
# Provisioning images
|
||||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=${REGISTRY}/cameleer-server:${VERSION}
|
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE=${REGISTRY}/cameleer-server:${VERSION}
|
||||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=${REGISTRY}/cameleer-server-ui:${VERSION}
|
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE=${REGISTRY}/cameleer-server-ui:${VERSION}
|
||||||
|
|
||||||
|
# Compose file assembly
|
||||||
|
COMPOSE_FILE=docker-compose.yml:docker-compose.saas.yml$([ "$TLS_MODE" = "custom" ] && echo ":docker-compose.tls.yml")$([ -n "$MONITORING_NETWORK" ] && echo ":docker-compose.monitoring.yml")
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ -n "$MONITORING_NETWORK" ]; then
|
||||||
|
echo "" >> "$f"
|
||||||
|
echo "# Monitoring" >> "$f"
|
||||||
|
echo "MONITORING_NETWORK=${MONITORING_NETWORK}" >> "$f"
|
||||||
|
fi
|
||||||
|
|
||||||
log_info "Generated .env"
|
log_info "Generated .env"
|
||||||
cp "$f" "$INSTALL_DIR/.env.bak"
|
cp "$f" "$INSTALL_DIR/.env.bak"
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_compose_file() {
|
copy_templates() {
|
||||||
|
local src
|
||||||
|
src="$(cd "$(dirname "$0")" && pwd)/templates"
|
||||||
|
|
||||||
|
# Base infra — always copied
|
||||||
|
cp "$src/docker-compose.yml" "$INSTALL_DIR/docker-compose.yml"
|
||||||
|
cp "$src/.env.example" "$INSTALL_DIR/.env.example"
|
||||||
|
|
||||||
|
# Mode-specific
|
||||||
if [ "$DEPLOYMENT_MODE" = "standalone" ]; then
|
if [ "$DEPLOYMENT_MODE" = "standalone" ]; then
|
||||||
generate_compose_file_standalone
|
cp "$src/docker-compose.server.yml" "$INSTALL_DIR/docker-compose.server.yml"
|
||||||
return
|
cp "$src/traefik-dynamic.yml" "$INSTALL_DIR/traefik-dynamic.yml"
|
||||||
fi
|
else
|
||||||
local f="$INSTALL_DIR/docker-compose.yml"
|
cp "$src/docker-compose.saas.yml" "$INSTALL_DIR/docker-compose.saas.yml"
|
||||||
: > "$f"
|
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
# Cameleer SaaS Platform
|
|
||||||
# Generated by Cameleer installer <20> do not edit manually
|
|
||||||
|
|
||||||
services:
|
|
||||||
cameleer-traefik:
|
|
||||||
image: ${TRAEFIK_IMAGE:-gitea.siegeln.net/cameleer/cameleer-traefik}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "${HTTP_PORT:-80}:80"
|
|
||||||
- "${HTTPS_PORT:-443}:443"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ "$LOGTO_CONSOLE_EXPOSED" = "true" ]; then
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
- "${LOGTO_CONSOLE_PORT:-3002}:3002"
|
|
||||||
EOF
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
# Optional overlays
|
||||||
environment:
|
|
||||||
PUBLIC_HOST: ${PUBLIC_HOST:-localhost}
|
|
||||||
CERT_FILE: ${CERT_FILE:-}
|
|
||||||
KEY_FILE: ${KEY_FILE:-}
|
|
||||||
CA_FILE: ${CA_FILE:-}
|
|
||||||
volumes:
|
|
||||||
- cameleer-certs:/certs
|
|
||||||
- ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ "$TLS_MODE" = "custom" ]; then
|
if [ "$TLS_MODE" = "custom" ]; then
|
||||||
cat >> "$f" << 'EOF'
|
cp "$src/docker-compose.tls.yml" "$INSTALL_DIR/docker-compose.tls.yml"
|
||||||
- ./certs:/user-certs:ro
|
|
||||||
EOF
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
- cameleer-traefik
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
if [ -n "$MONITORING_NETWORK" ]; then
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
cp "$src/docker-compose.monitoring.yml" "$INSTALL_DIR/docker-compose.monitoring.yml"
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
labels:
|
|
||||||
- "prometheus.io/scrape=true"
|
|
||||||
- "prometheus.io/port=8082"
|
|
||||||
- "prometheus.io/path=/metrics"
|
|
||||||
EOF
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
log_info "Copied docker-compose templates to $INSTALL_DIR"
|
||||||
|
|
||||||
cameleer-postgres:
|
|
||||||
image: ${POSTGRES_IMAGE:-gitea.siegeln.net/cameleer/cameleer-postgres}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: cameleer_saas
|
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-cameleer}
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- cameleer-pgdata:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER:-cameleer} -d cameleer_saas"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
|
|
||||||
cameleer-clickhouse:
|
|
||||||
image: ${CLICKHOUSE_IMAGE:-gitea.siegeln.net/cameleer/cameleer-clickhouse}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- cameleer-chdata:/var/lib/clickhouse
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "clickhouse-client --password $${CLICKHOUSE_PASSWORD} --query 'SELECT 1'"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
labels:
|
|
||||||
- "prometheus.io/scrape=true"
|
|
||||||
- "prometheus.io/port=9363"
|
|
||||||
- "prometheus.io/path=/metrics"
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
|
|
||||||
cameleer-logto:
|
|
||||||
image: ${LOGTO_IMAGE:-gitea.siegeln.net/cameleer/cameleer-logto}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
cameleer-postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
DB_URL: postgres://${POSTGRES_USER:-cameleer}:${POSTGRES_PASSWORD}@cameleer-postgres:5432/logto
|
|
||||||
ENDPOINT: ${PUBLIC_PROTOCOL:-https}://${PUBLIC_HOST:-localhost}
|
|
||||||
ADMIN_ENDPOINT: ${PUBLIC_PROTOCOL:-https}://${PUBLIC_HOST:-localhost}:${LOGTO_CONSOLE_PORT:-3002}
|
|
||||||
TRUST_PROXY_HEADER: 1
|
|
||||||
NODE_TLS_REJECT_UNAUTHORIZED: "${NODE_TLS_REJECT:-0}"
|
|
||||||
LOGTO_ENDPOINT: http://cameleer-logto:3001
|
|
||||||
LOGTO_ADMIN_ENDPOINT: http://cameleer-logto:3002
|
|
||||||
LOGTO_PUBLIC_ENDPOINT: ${PUBLIC_PROTOCOL:-https}://${PUBLIC_HOST:-localhost}
|
|
||||||
PUBLIC_HOST: ${PUBLIC_HOST:-localhost}
|
|
||||||
PUBLIC_PROTOCOL: ${PUBLIC_PROTOCOL:-https}
|
|
||||||
PG_HOST: cameleer-postgres
|
|
||||||
PG_USER: ${POSTGRES_USER:-cameleer}
|
|
||||||
PG_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
PG_DB_SAAS: cameleer_saas
|
|
||||||
SAAS_ADMIN_USER: ${SAAS_ADMIN_USER:-admin}
|
|
||||||
SAAS_ADMIN_PASS: ${SAAS_ADMIN_PASS:?SAAS_ADMIN_PASS must be set in .env}
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "node -e \"require('http').get('http://localhost:3001/oidc/.well-known/openid-configuration', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))\" && test -f /data/logto-bootstrap.json"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 60
|
|
||||||
start_period: 30s
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.cameleer-logto.rule=PathPrefix(`/`)
|
|
||||||
- traefik.http.routers.cameleer-logto.priority=1
|
|
||||||
- traefik.http.routers.cameleer-logto.entrypoints=websecure
|
|
||||||
- traefik.http.routers.cameleer-logto.tls=true
|
|
||||||
- traefik.http.routers.cameleer-logto.service=cameleer-logto
|
|
||||||
- traefik.http.routers.cameleer-logto.middlewares=cameleer-logto-cors
|
|
||||||
- "traefik.http.middlewares.cameleer-logto-cors.headers.accessControlAllowOriginList=${PUBLIC_PROTOCOL:-https}://${PUBLIC_HOST:-localhost}:${LOGTO_CONSOLE_PORT:-3002}"
|
|
||||||
- traefik.http.middlewares.cameleer-logto-cors.headers.accessControlAllowMethods=GET,POST,PUT,PATCH,DELETE,OPTIONS
|
|
||||||
- traefik.http.middlewares.cameleer-logto-cors.headers.accessControlAllowHeaders=Authorization,Content-Type
|
|
||||||
- traefik.http.middlewares.cameleer-logto-cors.headers.accessControlAllowCredentials=true
|
|
||||||
- traefik.http.services.cameleer-logto.loadbalancer.server.port=3001
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ "$LOGTO_CONSOLE_EXPOSED" = "true" ]; then
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
- traefik.http.routers.cameleer-logto-console.rule=PathPrefix(`/`)
|
|
||||||
- traefik.http.routers.cameleer-logto-console.entrypoints=admin-console
|
|
||||||
- traefik.http.routers.cameleer-logto-console.tls=true
|
|
||||||
- traefik.http.routers.cameleer-logto-console.service=cameleer-logto-console
|
|
||||||
- traefik.http.services.cameleer-logto-console.loadbalancer.server.port=3002
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
volumes:
|
|
||||||
- cameleer-bootstrapdata:/data
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
|
|
||||||
cameleer-saas:
|
|
||||||
image: ${CAMELEER_IMAGE:-gitea.siegeln.net/cameleer/cameleer-saas}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
cameleer-logto:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
# SaaS database
|
|
||||||
SPRING_DATASOURCE_URL: jdbc:postgresql://cameleer-postgres:5432/cameleer_saas
|
|
||||||
SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:-cameleer}
|
|
||||||
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
# Identity (Logto)
|
|
||||||
CAMELEER_SAAS_IDENTITY_LOGTOENDPOINT: http://cameleer-logto:3001
|
|
||||||
CAMELEER_SAAS_IDENTITY_LOGTOPUBLICENDPOINT: ${PUBLIC_PROTOCOL:-https}://${PUBLIC_HOST:-localhost}
|
|
||||||
# Provisioning — passed to per-tenant server containers
|
|
||||||
CAMELEER_SAAS_PROVISIONING_PUBLICHOST: ${PUBLIC_HOST:-localhost}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_PUBLICPROTOCOL: ${PUBLIC_PROTOCOL:-https}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_NETWORKNAME: ${COMPOSE_PROJECT_NAME:-cameleer-saas}_cameleer
|
|
||||||
CAMELEER_SAAS_PROVISIONING_TRAEFIKNETWORK: cameleer-traefik
|
|
||||||
CAMELEER_SAAS_PROVISIONING_DATASOURCEUSERNAME: ${POSTGRES_USER:-cameleer}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_DATASOURCEPASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_CLICKHOUSEPASSWORD: ${CLICKHOUSE_PASSWORD}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_SERVERIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERIMAGE:-gitea.siegeln.net/cameleer/cameleer-server:latest}
|
|
||||||
CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE: ${CAMELEER_SAAS_PROVISIONING_SERVERUIIMAGE:-gitea.siegeln.net/cameleer/cameleer-server-ui:latest}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.saas.rule=PathPrefix(`/platform`)
|
|
||||||
- traefik.http.routers.saas.entrypoints=websecure
|
|
||||||
- traefik.http.routers.saas.tls=true
|
|
||||||
- traefik.http.services.saas.loadbalancer.server.port=8080
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
- "prometheus.io/scrape=true"
|
|
||||||
- "prometheus.io/port=8080"
|
|
||||||
- "prometheus.io/path=/platform/actuator/prometheus"
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
volumes:
|
|
||||||
- cameleer-bootstrapdata:/data/bootstrap:ro
|
|
||||||
- cameleer-certs:/certs
|
|
||||||
- ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Detect Docker socket GID for container access
|
|
||||||
local docker_gid
|
|
||||||
docker_gid=$(stat -c '%g' "${DOCKER_SOCKET:-/var/run/docker.sock}" 2>/dev/null || echo "0")
|
|
||||||
cat >> "$f" << EOF
|
|
||||||
group_add:
|
|
||||||
- "${docker_gid}"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
EOF
|
|
||||||
cat >> "$f" << 'EOF'
|
|
||||||
cameleer-pgdata:
|
|
||||||
cameleer-chdata:
|
|
||||||
cameleer-certs:
|
|
||||||
cameleer-bootstrapdata:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
cameleer:
|
|
||||||
driver: bridge
|
|
||||||
cameleer-traefik:
|
|
||||||
name: cameleer-traefik
|
|
||||||
driver: bridge
|
|
||||||
EOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
cat >> "$f" << EOF
|
|
||||||
${MONITORING_NETWORK}:
|
|
||||||
external: true
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Generated docker-compose.yml"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_compose_file_standalone() {
|
|
||||||
local f="$INSTALL_DIR/docker-compose.yml"
|
|
||||||
: > "$f"
|
|
||||||
|
|
||||||
cat >> "$f" << 'COMPOSEEOF'
|
|
||||||
# Cameleer Server (standalone)
|
|
||||||
# Generated by Cameleer installer — do not edit manually
|
|
||||||
|
|
||||||
services:
|
|
||||||
cameleer-traefik:
|
|
||||||
image: ${TRAEFIK_IMAGE:-gitea.siegeln.net/cameleer/cameleer-traefik}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "${HTTP_PORT:-80}:80"
|
|
||||||
- "${HTTPS_PORT:-443}:443"
|
|
||||||
environment:
|
|
||||||
PUBLIC_HOST: ${PUBLIC_HOST:-localhost}
|
|
||||||
CERT_FILE: ${CERT_FILE:-}
|
|
||||||
KEY_FILE: ${KEY_FILE:-}
|
|
||||||
CA_FILE: ${CA_FILE:-}
|
|
||||||
volumes:
|
|
||||||
- cameleer-certs:/certs
|
|
||||||
- ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro
|
|
||||||
- ./traefik-dynamic.yml:/etc/traefik/dynamic.yml:ro
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
if [ "$TLS_MODE" = "custom" ]; then
|
|
||||||
echo " - ./certs:/user-certs:ro" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'COMPOSEEOF'
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
- cameleer-traefik
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'COMPOSEEOF'
|
|
||||||
|
|
||||||
cameleer-postgres:
|
|
||||||
image: postgres:16-alpine
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-cameleer}
|
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-cameleer}
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- cameleer-pgdata:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER:-cameleer} -d $${POSTGRES_DB:-cameleer}"]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat >> "$f" << 'COMPOSEEOF'
|
|
||||||
|
|
||||||
cameleer-clickhouse:
|
|
||||||
image: ${CLICKHOUSE_IMAGE:-gitea.siegeln.net/cameleer/cameleer-clickhouse}:${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- cameleer-chdata:/var/lib/clickhouse
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "clickhouse-client --password $${CLICKHOUSE_PASSWORD} --query 'SELECT 1'"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 3
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
echo " - ${MONITORING_NETWORK}" >> "$f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Detect Docker socket GID
|
|
||||||
local docker_gid
|
|
||||||
docker_gid=$(stat -c '%g' "${DOCKER_SOCKET:-/var/run/docker.sock}" 2>/dev/null || echo "0")
|
|
||||||
|
|
||||||
cat >> "$f" << COMPOSEEOF
|
|
||||||
|
|
||||||
cameleer-server:
|
|
||||||
image: \${SERVER_IMAGE:-gitea.siegeln.net/cameleer/cameleer-server}:\${VERSION:-latest}
|
|
||||||
container_name: cameleer-server
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
cameleer-postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
CAMELEER_SERVER_TENANT_ID: default
|
|
||||||
SPRING_DATASOURCE_URL: jdbc:postgresql://cameleer-postgres:5432/\${POSTGRES_DB:-cameleer}?currentSchema=tenant_default
|
|
||||||
SPRING_DATASOURCE_USERNAME: \${POSTGRES_USER:-cameleer}
|
|
||||||
SPRING_DATASOURCE_PASSWORD: \${POSTGRES_PASSWORD}
|
|
||||||
CAMELEER_SERVER_CLICKHOUSE_URL: jdbc:clickhouse://cameleer-clickhouse:8123/cameleer
|
|
||||||
CAMELEER_SERVER_CLICKHOUSE_USERNAME: default
|
|
||||||
CAMELEER_SERVER_CLICKHOUSE_PASSWORD: \${CLICKHOUSE_PASSWORD}
|
|
||||||
CAMELEER_SERVER_SECURITY_BOOTSTRAPTOKEN: \${BOOTSTRAP_TOKEN}
|
|
||||||
CAMELEER_SERVER_SECURITY_UIUSER: \${SERVER_ADMIN_USER:-admin}
|
|
||||||
CAMELEER_SERVER_SECURITY_UIPASSWORD: \${SERVER_ADMIN_PASS:?SERVER_ADMIN_PASS must be set in .env}
|
|
||||||
CAMELEER_SERVER_SECURITY_CORSALLOWEDORIGINS: \${PUBLIC_PROTOCOL:-https}://\${PUBLIC_HOST:-localhost}
|
|
||||||
CAMELEER_SERVER_RUNTIME_ENABLED: "true"
|
|
||||||
CAMELEER_SERVER_RUNTIME_SERVERURL: http://cameleer-server:8081
|
|
||||||
CAMELEER_SERVER_RUNTIME_ROUTINGDOMAIN: \${PUBLIC_HOST:-localhost}
|
|
||||||
CAMELEER_SERVER_RUNTIME_ROUTINGMODE: path
|
|
||||||
CAMELEER_SERVER_RUNTIME_JARSTORAGEPATH: /data/jars
|
|
||||||
CAMELEER_SERVER_RUNTIME_DOCKERNETWORK: cameleer-apps
|
|
||||||
CAMELEER_SERVER_RUNTIME_JARDOCKERVOLUME: cameleer-jars
|
|
||||||
CAMELEER_SERVER_RUNTIME_BASEIMAGE: gitea.siegeln.net/cameleer/cameleer-runtime-base:\${VERSION:-latest}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.server-api.rule=PathPrefix(\`/api\`)
|
|
||||||
- traefik.http.routers.server-api.entrypoints=websecure
|
|
||||||
- traefik.http.routers.server-api.tls=true
|
|
||||||
- traefik.http.services.server-api.loadbalancer.server.port=8081
|
|
||||||
- traefik.docker.network=cameleer-traefik
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "curl -sf http://localhost:8081/api/v1/health || exit 1"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 30
|
|
||||||
start_period: 30s
|
|
||||||
volumes:
|
|
||||||
- jars:/data/jars
|
|
||||||
- cameleer-certs:/certs:ro
|
|
||||||
- \${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock
|
|
||||||
group_add:
|
|
||||||
- "${docker_gid}"
|
|
||||||
networks:
|
|
||||||
- cameleer
|
|
||||||
- cameleer-traefik
|
|
||||||
- cameleer-apps
|
|
||||||
|
|
||||||
cameleer-server-ui:
|
|
||||||
image: \${SERVER_UI_IMAGE:-gitea.siegeln.net/cameleer/cameleer-server-ui}:\${VERSION:-latest}
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
cameleer-server:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
CAMELEER_API_URL: http://cameleer-server:8081
|
|
||||||
BASE_PATH: ""
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.ui.rule=PathPrefix(\`/\`)
|
|
||||||
- traefik.http.routers.ui.priority=1
|
|
||||||
- traefik.http.routers.ui.entrypoints=websecure
|
|
||||||
- traefik.http.routers.ui.tls=true
|
|
||||||
- traefik.http.services.ui.loadbalancer.server.port=80
|
|
||||||
- traefik.docker.network=cameleer-traefik
|
|
||||||
networks:
|
|
||||||
- cameleer-traefik
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
cat >> "$f" << 'COMPOSEEOF'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
cameleer-pgdata:
|
|
||||||
cameleer-chdata:
|
|
||||||
cameleer-certs:
|
|
||||||
jars:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
cameleer:
|
|
||||||
driver: bridge
|
|
||||||
cameleer-traefik:
|
|
||||||
name: cameleer-traefik
|
|
||||||
driver: bridge
|
|
||||||
cameleer-apps:
|
|
||||||
name: cameleer-apps
|
|
||||||
driver: bridge
|
|
||||||
COMPOSEEOF
|
|
||||||
|
|
||||||
if [ -n "$MONITORING_NETWORK" ]; then
|
|
||||||
cat >> "$f" << EOF
|
|
||||||
${MONITORING_NETWORK}:
|
|
||||||
external: true
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Generate standalone traefik dynamic config (overrides baked-in redirect)
|
|
||||||
cat > "$INSTALL_DIR/traefik-dynamic.yml" << 'TRAEFIKEOF'
|
|
||||||
tls:
|
|
||||||
stores:
|
|
||||||
default:
|
|
||||||
defaultCertificate:
|
|
||||||
certFile: /certs/cert.pem
|
|
||||||
keyFile: /certs/key.pem
|
|
||||||
TRAEFIKEOF
|
|
||||||
|
|
||||||
log_info "Generated docker-compose.yml (standalone)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Docker operations ---
|
# --- Docker operations ---
|
||||||
@@ -1700,7 +1284,7 @@ handle_rerun() {
|
|||||||
load_config_file "$INSTALL_DIR/cameleer.conf"
|
load_config_file "$INSTALL_DIR/cameleer.conf"
|
||||||
load_env_overrides
|
load_env_overrides
|
||||||
merge_config
|
merge_config
|
||||||
generate_compose_file
|
copy_templates
|
||||||
docker_compose_pull
|
docker_compose_pull
|
||||||
docker_compose_down
|
docker_compose_down
|
||||||
docker_compose_up
|
docker_compose_up
|
||||||
@@ -1725,9 +1309,12 @@ handle_rerun() {
|
|||||||
log_info "Reinstalling..."
|
log_info "Reinstalling..."
|
||||||
docker_compose_down 2>/dev/null || true
|
docker_compose_down 2>/dev/null || true
|
||||||
(cd "$INSTALL_DIR" && docker compose -p "${COMPOSE_PROJECT:-cameleer-saas}" down -v 2>/dev/null || true)
|
(cd "$INSTALL_DIR" && docker compose -p "${COMPOSE_PROJECT:-cameleer-saas}" down -v 2>/dev/null || true)
|
||||||
rm -f "$INSTALL_DIR/.env" "$INSTALL_DIR/docker-compose.yml" \
|
rm -f "$INSTALL_DIR/.env" "$INSTALL_DIR/.env.bak" "$INSTALL_DIR/.env.example" \
|
||||||
|
"$INSTALL_DIR/docker-compose.yml" "$INSTALL_DIR/docker-compose.saas.yml" \
|
||||||
|
"$INSTALL_DIR/docker-compose.server.yml" "$INSTALL_DIR/docker-compose.tls.yml" \
|
||||||
|
"$INSTALL_DIR/docker-compose.monitoring.yml" "$INSTALL_DIR/traefik-dynamic.yml" \
|
||||||
"$INSTALL_DIR/cameleer.conf" "$INSTALL_DIR/credentials.txt" \
|
"$INSTALL_DIR/cameleer.conf" "$INSTALL_DIR/credentials.txt" \
|
||||||
"$INSTALL_DIR/INSTALL.md" "$INSTALL_DIR/.env.bak"
|
"$INSTALL_DIR/INSTALL.md"
|
||||||
rm -rf "$INSTALL_DIR/certs"
|
rm -rf "$INSTALL_DIR/certs"
|
||||||
IS_RERUN=false
|
IS_RERUN=false
|
||||||
return
|
return
|
||||||
@@ -1788,7 +1375,7 @@ main() {
|
|||||||
|
|
||||||
# Generate configuration files
|
# Generate configuration files
|
||||||
generate_env_file
|
generate_env_file
|
||||||
generate_compose_file
|
copy_templates
|
||||||
write_config_file
|
write_config_file
|
||||||
|
|
||||||
# Pull and start
|
# Pull and start
|
||||||
|
|||||||
Reference in New Issue
Block a user