nextcloud / nextcloud/app_api

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

Open
#859 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement question
Dominant language
PHP
Stars
196
Forks
26
Avg merge
4d 15h
Merged PRs (30d)
31

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in DockerActions.php around lines 1171 and 1212-1218, then compare the handling in HarpService.php and ManualActions.php. Review the daemon registration UI and occ app_api:daemon:register entry points to expose OVERRIDE_APP_HOST through an official interface, and verify that a remote Docker deployment passes the configured host instead of 127.0.0.1.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, php
Domain
backend, devops
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.