Skip to content

SSL_TYPE=upstream breaks Enketo (openRosaServer URLs seems hardcoded to https://)Β #1695

@boulate

Description

@boulate

Description

When running ODK Central behind a reverse proxy with SSL_TYPE=upstream, all Enketo form access fails (preview, public access links, submission editing). Enketo cannot fetch form definitions from the ODK API because it tries to connect over HTTPS:443, but nginx only listens on HTTP:80 in upstream mode.

Environment

  • ODK Central: latest (main)
  • Enketo: ghcr.io/enketo/enketo:7.5.1
  • Reverse proxy: Caddy (but applies to any reverse proxy setup using SSL_TYPE=upstream)
  • Docker Compose with external reverse proxy on a separate Docker network

Expected behavior

All Enketo form access (preview, fill, edit) works when SSL_TYPE=upstream is set β€” Enketo successfully fetches form XML from the ODK API.

Observed behavior

Opening any form (preview, fill link, or edit) returns a 500 error:

{"code": 500, "message": "Could not connect with Form Server"}

Reproducing from inside the Enketo container confirms that HTTPS to the domain is unreachable:

$ node -e "require('https').get('https://my-domain.example/').on('error', e => console.log(e.message))"
connect ECONNREFUSED 192.168.x.x:443

This is not a forced HTTPS call β€” it reproduces exactly what Enketo does internally when it reads the openRosaServer URL stored in Redis (which is always https://).

Root cause

Two parts of ODK Central contradict each other when SSL_TYPE=upstream:

  1. setup-odk.sh strips all SSL from nginx:

    perl -i -ne 's/listen 443.*/listen 80;/; print if ! /\bssl_/' /etc/nginx/conf.d/odk.conf

    After this, nginx only listens on port 80. Port 443 is completely gone.

  2. The service container registers forms with Enketo using an openRosaServer URL that is always https://:

    openRosaServer = https://my-domain.example/v1/key/.../projects/1/forms/myform/draft
    

    This URL is stored per-form in Redis and is what Enketo uses for all API calls to fetch form XML.

When Enketo tries to call https://my-domain.example, Docker DNS resolves it to nginx's IP, but nginx doesn't serve HTTPS β†’ ECONNREFUSED on port 443.

This works fine with SSL_TYPE=letsencrypt, selfsign, or customssl because in all those modes nginx retains its HTTPS listener on port 443. Only upstream removes it.

What does NOT work as a fix

  • Setting "server url": "http://..." in Enketo's config.json.template: This only changes the default server URL in the config. The per-form openRosaServer stored in Redis (set by the service container at registration time) remains https:// and that's what Enketo actually uses for API calls.

  • Adding a Docker DNS alias so Enketo resolves the domain to nginx: Enketo resolves the name correctly, but still tries HTTPS:443, which nginx doesn't serve.

Current workaround

We use extra_hosts: "${DOMAIN}:host-gateway" on the Enketo container so that https://my-domain.example routes through the Docker host to the external reverse proxy (Caddy), which has a valid TLS certificate and proxies back to nginx on HTTP:80.

# docker-compose.override.yml
services:
  enketo:
    extra_hosts:
      - "${DOMAIN}:host-gateway"

This works but adds an unnecessary round-trip through the reverse proxy for internal traffic.

Suggested fix

When SSL_TYPE=upstream, the service container should register forms with Enketo using http:// instead of https:// for the openRosaServer URL, since nginx is explicitly configured to not serve TLS in this mode.

Alternatively, setup-odk.sh could preserve a self-signed HTTPS listener on nginx in upstream mode (the self-signed cert is already generated at lines 19-23 of the script) so that internal HTTPS calls still work. This would require setting NODE_TLS_REJECT_UNAUTHORIZED=0 on the Enketo container.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    πŸ“₯ inbox

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions