services: # PostgreSQL database postgres: image: postgres:16-alpine container_name: certctl-postgres environment: POSTGRES_DB: certctl POSTGRES_USER: certctl POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-certctl} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ../migrations/000001_initial_schema.up.sql:/docker-entrypoint-initdb.d/001_schema.sql - ../migrations/000002_agent_metadata.up.sql:/docker-entrypoint-initdb.d/002_agent_metadata.sql - ../migrations/000003_certificate_profiles.up.sql:/docker-entrypoint-initdb.d/003_certificate_profiles.sql - ../migrations/000004_agent_groups.up.sql:/docker-entrypoint-initdb.d/004_agent_groups.sql - ../migrations/000005_revocation.up.sql:/docker-entrypoint-initdb.d/005_revocation.sql - ../migrations/000006_discovery.up.sql:/docker-entrypoint-initdb.d/006_discovery.sql - ../migrations/000007_network_discovery.up.sql:/docker-entrypoint-initdb.d/007_network_discovery.sql - ../migrations/000008_verification.up.sql:/docker-entrypoint-initdb.d/008_verification.sql - ../migrations/000009_issuer_config.up.sql:/docker-entrypoint-initdb.d/009_issuer_config.sql - ../migrations/000010_target_config.up.sql:/docker-entrypoint-initdb.d/010_target_config.sql - ../migrations/seed.sql:/docker-entrypoint-initdb.d/020_seed.sql networks: - certctl-network healthcheck: test: ["CMD-SHELL", "pg_isready -U certctl -d certctl"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped # Certctl Server (API + scheduler) certctl-server: build: context: .. dockerfile: Dockerfile container_name: certctl-server depends_on: postgres: condition: service_healthy environment: CERTCTL_DATABASE_URL: postgres://certctl:${POSTGRES_PASSWORD:-certctl}@postgres:5432/certctl?sslmode=disable CERTCTL_SERVER_HOST: 0.0.0.0 CERTCTL_SERVER_PORT: 8443 CERTCTL_LOG_LEVEL: info CERTCTL_AUTH_TYPE: none CERTCTL_KEYGEN_MODE: server # Demo uses server-side keygen; production should use "agent" CERTCTL_NETWORK_SCAN_ENABLED: "true" # Enable network scan GUI with seeded demo targets CERTCTL_CONFIG_ENCRYPTION_KEY: ${CERTCTL_CONFIG_ENCRYPTION_KEY:-change-me-32-char-encryption-key} # AES-256-GCM for dynamic issuer/target config ports: - "8443:8443" networks: - certctl-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8443/health"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped logging: driver: "json-file" options: max-size: "10m" max-file: "3" deploy: resources: limits: cpus: '1.0' memory: 512M # Certctl Agent certctl-agent: build: context: .. dockerfile: Dockerfile.agent container_name: certctl-agent depends_on: certctl-server: condition: service_healthy environment: CERTCTL_SERVER_URL: http://certctl-server:8443 CERTCTL_API_KEY: ${CERTCTL_API_KEY:-change-me-in-production} CERTCTL_AGENT_NAME: docker-agent CERTCTL_LOG_LEVEL: info CERTCTL_DISCOVERY_DIRS: /var/lib/certctl/keys # Agent scans this directory for existing certificates volumes: - agent_keys:/var/lib/certctl/keys networks: - certctl-network healthcheck: test: ["CMD-SHELL", "pgrep -f certctl-agent || exit 1"] interval: 30s timeout: 5s retries: 3 restart: unless-stopped logging: driver: "json-file" options: max-size: "10m" max-file: "3" deploy: resources: limits: cpus: '0.5' memory: 256M networks: certctl-network: driver: bridge volumes: postgres_data: driver: local agent_keys: driver: local