Skip to content

AppAPI: OVERRIDE_APP_HOST inaccessible via any official interface, causing APP_HOST=127.0.0.1 on remote Docker deployments and breaking Ex-App heartbeat #859

@techsurrusr

Description

@techsurrusr

AppAPI: OVERRIDE_APP_HOST inaccessible via any official interface, causing APP_HOST=127.0.0.1 on remote Docker deployments and breaking Ex-App heartbeat

Running Nextcloud 33.0.3 with AppAPI 33.0.0, and have fully confirmed a bug where deploying Ex-Apps to a remote Docker host always results in APP_HOST=127.0.0.1 being passed to the container — making it impossible for Nextcloud to reach the container for the heartbeat check, causing all Ex-App deployments to fail silently.

The setup is a standard production configuration: Nextcloud runs on a dedicated LXC container, and the Docker daemon runs on a separate host on the same internal network. This is a common architecture for self-hosted environments where Docker workloads are isolated from the application server.

The Problem

When AppAPI deploys an Ex-App container using docker-install with --net host on a remote Docker host, it hardcodes APP_HOST=127.0.0.1 in the container's environment. The container then binds Uvicorn exclusively to 127.0.0.1:23000 — unreachable from the Nextcloud server — causing the heartbeat check to fail and the deployment to roll back with ExApp heartbeat check failed.

The root cause is in DockerActions.php at line 1171:

sprintf('APP_HOST=%s', $params['host']),

When using host networking on a remote Docker host, $params['host'] resolves to the loopback address. The container starts correctly, pulls the image, runs — but binds only on localhost and is unreachable from Nextcloud.

The Hidden Override

OVERRIDE_APP_HOST exists in the AppAPI source code and is explicitly checked at lines 1212-1218 of DockerActions.php:

if (isset($deployConfig['additional_options']['OVERRIDE_APP_HOST']) &&
    $deployConfig['additional_options']['OVERRIDE_APP_HOST'] !== ''
) {
    if (!in_array($deployConfig['additional_options']['OVERRIDE_APP_HOST'], $wideNetworkAddresses)) {
        // use OVERRIDE_APP_HOST value
    }
}

This mechanism exists and works correctly — but it is completely inaccessible through any official interface:

  • ❌ Not exposed in the Web UI daemon registration form
  • ❌ Not available as a parameter in occ app_api:daemon:register
  • ❌ Not documented anywhere in the AppAPI documentation
  • ❌ The same pattern exists in HarpService.php and ManualActions.php — all unreachable

The only way to set it is by directly manipulating the database:

UPDATE oc_ex_apps_daemons
SET deploy_config = JSON_SET(
  deploy_config,
  '$.additional_options',
  JSON_OBJECT('OVERRIDE_APP_HOST', '<docker_host_ip>')
)
WHERE name = '<daemon_name>';

Once set this way, deployments succeed immediately — APP_HOST is correctly set to the Docker host IP and the heartbeat check passes.

Impact

This effectively makes AppAPI non-functional for any deployment where Docker runs on a separate host from Nextcloud — which is a common and recommended production architecture. The failure mode is particularly confusing because:

  1. The connection check reports "Daemon connection successful"
  2. The image pull succeeds
  3. The container starts and reports healthy
  4. The deployment silently fails at the heartbeat step with no actionable error message

There is no indication in the UI or logs that OVERRIDE_APP_HOST exists or needs to be set.

Proposed Fix

OVERRIDE_APP_HOST should be exposed through official interfaces. At minimum one of the following:

Option A — Add to occ app_api:daemon:register:

--override_app_host=OVERRIDE_APP_HOST   Override the APP_HOST passed to deployed
                                         Ex-App containers. Required when Docker
                                         runs on a separate host from Nextcloud.

Option B — Add to the Web UI daemon registration form under "Deploy options" as an optional field labeled "ExApp host override (APP_HOST)" with appropriate help text explaining when it is needed.

Option C — Auto-detect remote hosts: When the daemon host is not localhost, 127.0.0.1, or a Unix socket path, AppAPI should automatically resolve and use the daemon's hostname/IP as APP_HOST rather than defaulting to loopback.

Option C is the most user-friendly as it requires no manual intervention for the common case.

Environment

  • Nextcloud: 33.0.3
  • AppAPI: 33.0.0
  • Docker host: separate from Nextcloud, internal network only
  • DSP image: ghcr.io/nextcloud/nextcloud-appapi-dsp:latest
  • Deployment method: docker-install, --net host

Kind Regards,

Kim @ njordium.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested
    No fields configured for Enhancement.

    Projects

    Status

    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions