Problem
The opencti service healthcheck hardcodes a plain-HTTP probe:
wget -qO- http://opencti:8080/health?health_access_key=...
When the platform is configured to serve HTTPS natively (APP__HTTPS_CERT__CRT / APP__HTTPS_CERT__KEY), port 8080 speaks TLS and this probe fails permanently. With a self-signed certificate (the common case for internal/air-gapped deployments), even switching the URL to https:// fails, because BusyBox wget delegates TLS to ssl_client, which validates against the system trust store:
SSL routines:tls_post_process_server_certificate:certificate verify failed
ssl_client: SSL_connect
wget: error getting response: Connection reset by peer
Impact is stack-wide: every worker and connector in this compose file gates on depends_on: opencti: condition: service_healthy, so a failing healthcheck prevents the entire stack from starting — not just the probe.
Proposed change
Replace the probe with an HTTPS-first attempt (with --no-check-certificate)
falling back to plain HTTP:
healthcheck:
- test: ["CMD", "wget", "-qO-", "http://opencti:8080/health?health_access_key=${OPENCTI_HEALTHCHECK_ACCESS_KEY}"]
+ test: ["CMD-SHELL", "wget -qO- --no-check-certificate https://opencti:8080/health?health_access_key=${OPENCTI_HEALTHCHECK_ACCESS_KEY} || wget -qO- http://opencti:8080/health?health_access_key=${OPENCTI_HEALTHCHECK_ACCESS_KEY}"]
interval: 10s
timeout: 5s
retries: 20
This makes the healthcheck work out of the box in every scenario:
| Scenario |
Before |
After |
| HTTP (default) |
✅ |
✅ (falls back to HTTP probe) |
| HTTPS, CA-signed cert |
❌ |
✅ |
| HTTPS, self-signed cert |
❌ |
✅ |
No new environment variables, no image changes.
Why --no-check-certificate is appropriate here
- BusyBox
wget supports no CA-pinning flag (--ca-certificate does not exist in the applet); this is the only TLS option available without rebuilding the image or mounting a trust store.
- The probe is a liveness check from the container to itself over the Docker bridge network. There is no meaningful MITM surface, and the check carries no sensitive payload beyond the health access key already present in the container's environment.
- Certificate verification for real clients (browsers, workers, connectors) is unaffected by this change.
Alternative considered
A single-probe version parameterizing the scheme was considered:
wget -qO- --no-check-certificate ${OPENCTI_INTERNAL_SCHEME:-http}://opencti:8080/health?...
Not preferred because it introduces a new .env variable and a corresponding documentation change, and requires users enabling HTTPS to know about and set the knob. The HTTPS-first/HTTP-fallback approach keeps the reference compose zero-configuration in all scenarios. Happy to switch to the parameterized version if maintainers prefer an explicit knob over a fallback probe.
Relationship to the reverse-proxy pattern
The recommended production pattern remains TLS termination at a reverse proxy, keeping container-to-container traffic on plain HTTP — this change does not alter that guidance, and the default HTTP deployment is completely unaffected (the fallback probe reproduces today's behavior). However, native HTTPS via APP__HTTPS_CERT__* is a documented platform feature, and some environments (hardening baselines, air-gapped/internal deployments) mandate end-to-end TLS to the node process. The reference compose file should not hard-break — with the entire stack failing to start — when a documented configuration option is used.
Testing
- Default
.env, HTTP: docker compose up -d → opencti reaches healthy,
dependent services start.
APP__HTTPS_CERT__CRT/APP__HTTPS_CERT__KEY set with a self-signed cert:
opencti reaches healthy, workers/connectors start (previously stuck in
Created/Waiting).
Problem
The
openctiservice healthcheck hardcodes a plain-HTTP probe:When the platform is configured to serve HTTPS natively (
APP__HTTPS_CERT__CRT/APP__HTTPS_CERT__KEY), port 8080 speaks TLS and this probe fails permanently. With a self-signed certificate (the common case for internal/air-gapped deployments), even switching the URL tohttps://fails, because BusyBoxwgetdelegates TLS tossl_client, which validates against the system trust store:Impact is stack-wide: every worker and connector in this compose file gates on
depends_on: opencti: condition: service_healthy, so a failing healthcheck prevents the entire stack from starting — not just the probe.Proposed change
Replace the probe with an HTTPS-first attempt (with
--no-check-certificate)falling back to plain HTTP:
This makes the healthcheck work out of the box in every scenario:
No new environment variables, no image changes.
Why
--no-check-certificateis appropriate herewgetsupports no CA-pinning flag (--ca-certificatedoes not exist in the applet); this is the only TLS option available without rebuilding the image or mounting a trust store.Alternative considered
A single-probe version parameterizing the scheme was considered:
Not preferred because it introduces a new
.envvariable and a corresponding documentation change, and requires users enabling HTTPS to know about and set the knob. The HTTPS-first/HTTP-fallback approach keeps the reference compose zero-configuration in all scenarios. Happy to switch to the parameterized version if maintainers prefer an explicit knob over a fallback probe.Relationship to the reverse-proxy pattern
The recommended production pattern remains TLS termination at a reverse proxy, keeping container-to-container traffic on plain HTTP — this change does not alter that guidance, and the default HTTP deployment is completely unaffected (the fallback probe reproduces today's behavior). However, native HTTPS via
APP__HTTPS_CERT__*is a documented platform feature, and some environments (hardening baselines, air-gapped/internal deployments) mandate end-to-end TLS to the node process. The reference compose file should not hard-break — with the entire stack failing to start — when a documented configuration option is used.Testing
.env, HTTP:docker compose up -d→openctireacheshealthy,dependent services start.
APP__HTTPS_CERT__CRT/APP__HTTPS_CERT__KEYset with a self-signed cert:openctireacheshealthy, workers/connectors start (previously stuck inCreated/Waiting).