# Production overlay for the ITWorx Pulse deployment on the Unraid host. # # Usage: # docker compose -f deploy/compose.yaml -f deploy/compose.prod.yaml up -d # # The base compose file deliberately publishes no host port: ADR-0010 requires a # controlled proxy edge and forbids guessing a host port. The port is no longer a # guess — 1238 was chosen by the operator for this host (ADR-0011) — so it is # recorded here, in a separate overlay, rather than being baked into the base file # that other environments share. # # Only pulse-web is published. pulse-api stays on the internal-only network and is # reached exclusively through nginx inside pulse-web, so the API cannot be addressed # directly from the LAN even by accident. # # The bind address is configurable and defaults to all interfaces, because Nginx # Proxy Manager runs in its own container and cannot reach a 127.0.0.1 binding on the # host. If NPM is configured to reach Pulse over a shared Docker network instead, set # PULSE_PUBLISH_ADDRESS=127.0.0.1 to remove the LAN exposure entirely. services: pulse-web: ports: - "${PULSE_PUBLISH_ADDRESS:-0.0.0.0}:${PULSE_HOST_PORT:-1238}:8080" pulse-api: environment: PULSE_ENV: production # Must match the externally reachable URL that terminates TLS, not the # host:port published above, because the OIDC redirect and every absolute # link the API emits have to be valid from the browser's point of view. PULSE_PUBLIC_URL: ${PULSE_PUBLIC_URL:?PULSE_PUBLIC_URL must be set to the externally reachable HTTPS URL} # Fail Compose resolution before touching the running stack if no # identity claim can be mapped onto a bounded Pulse role. PULSE_OIDC_ROLE_MAPPING: ${PULSE_OIDC_ROLE_MAPPING:?PULSE_OIDC_ROLE_MAPPING must contain at least one claim=role entry} PULSE_OIDC_GROUPS_CLAIM: ${PULSE_OIDC_GROUPS_CLAIM:-groups} # The host path is interpolated into the bind mount below; inside the # container the manager always receives this fixed, non-secret path. PULSE_BACKUP_DIR: /var/lib/pulse/backups PULSE_BACKUP_RETENTION: ${PULSE_BACKUP_RETENTION:-5} volumes: - type: bind source: ${PULSE_BACKUP_DIR:?PULSE_BACKUP_DIR must be an operator-owned host directory outside the database volume} target: /var/lib/pulse/backups pulse-worker: environment: PULSE_ENV: production pulse-agent: environment: PULSE_ENV: production # The kernel reports the container's own name through the UTS namespace, so # the real host name has to be supplied explicitly. PULSE_AGENT_HOST_NAME: ${PULSE_AGENT_HOST_NAME:?PULSE_AGENT_HOST_NAME must be set to the Unraid host name} PULSE_UNRAID_CA_FILE: /run/pulse/unraid-ca.pem volumes: - type: bind source: ${PULSE_UNRAID_CA_FILE_HOST:?PULSE_UNRAID_CA_FILE_HOST must point to the public Unraid TLS certificate} target: /run/pulse/unraid-ca.pem read_only: true # Resolve the certificate hostname from PULSE_UNRAID_URL to the explicitly # discovered reachable Unraid host address. This avoids host networking and # keeps normal certificate hostname verification active. extra_hosts: - "${PULSE_UNRAID_HOST_NAME:?PULSE_UNRAID_HOST_NAME must match the hostname in PULSE_UNRAID_URL}:${PULSE_UNRAID_HOST_GATEWAY:?PULSE_UNRAID_HOST_GATEWAY must be the reachable address of this Unraid host}"