services: postgres: image: postgres:16-alpine container_name: proxpanel-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-proxpanel} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-proxpanel} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-proxpanel} -d ${POSTGRES_DB:-proxpanel}"] interval: 10s timeout: 5s retries: 10 backend: build: context: ../../backend container_name: proxpanel-backend restart: unless-stopped depends_on: postgres: condition: service_healthy environment: NODE_ENV: production PORT: 8080 DATABASE_URL: postgresql://${POSTGRES_USER:-proxpanel}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-proxpanel} JWT_SECRET: ${JWT_SECRET} JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-15m} JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-30d} CORS_ORIGIN: ${CORS_ORIGIN} RATE_LIMIT_WINDOW_MS: ${RATE_LIMIT_WINDOW_MS:-60000} RATE_LIMIT_MAX: ${RATE_LIMIT_MAX:-600} AUTH_RATE_LIMIT_WINDOW_MS: ${AUTH_RATE_LIMIT_WINDOW_MS:-60000} AUTH_RATE_LIMIT_MAX: ${AUTH_RATE_LIMIT_MAX:-20} ENABLE_SCHEDULER: ${ENABLE_SCHEDULER:-true} BILLING_CRON: ${BILLING_CRON:-0 * * * *} BACKUP_CRON: ${BACKUP_CRON:-*/15 * * * *} POWER_SCHEDULE_CRON: ${POWER_SCHEDULE_CRON:-* * * * *} MONITORING_CRON: ${MONITORING_CRON:-*/5 * * * *} PROXMOX_TIMEOUT_MS: ${PROXMOX_TIMEOUT_MS:-15000} ADMIN_EMAIL: ${ADMIN_EMAIL} ADMIN_PASSWORD: ${ADMIN_PASSWORD} expose: - "8080" ports: - "127.0.0.1:${BACKEND_PORT:-8080}:8080" healthcheck: test: ["CMD-SHELL", "wget -q -O - http://localhost:8080/api/health >/dev/null 2>&1 || exit 1"] interval: 15s timeout: 5s retries: 10 frontend: build: context: ../../ args: VITE_API_BASE_URL: "" container_name: proxpanel-frontend restart: unless-stopped depends_on: backend: condition: service_healthy ports: - "127.0.0.1:${FRONTEND_PORT:-80}:80" healthcheck: test: ["CMD-SHELL", "nginx -t >/dev/null 2>&1 || exit 1"] interval: 15s timeout: 5s retries: 10 volumes: postgres_data: