From ad17d3b6af2eff90fb1f21dcdf31eb6d13db823f Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Mon, 14 Sep 2026 11:50:42 +0000 Subject: [PATCH 1/3] docs: resolve a HaRP hostname per request in the nginx example With a container name in proxy_pass, nginx refuses to start whenever that container is absent and the whole server block goes down; a variable plus a resolver avoids it. Signed-off-by: Oleksandr Piskun --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index aa709a3..2676d82 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,20 @@ server { } ``` +If you point `proxy_pass` at a container or DNS name instead of an IP (for example `appapi-harp` on a Docker +network), do not write the name into `proxy_pass` directly: nginx resolves it once at startup and refuses to +start whenever that container is absent (`host not found in upstream`), which takes the whole server block down. +Put the upstream in a variable, which nginx resolves per request, and give it a resolver: + +```nginx + resolver 127.0.0.11 valid=30s; # Docker's embedded DNS; use your own resolver outside Docker + set $harp_upstream http://appapi-harp:8780; + location /exapps/ { + proxy_pass $harp_upstream; + # the same proxy_set_header and proxy_read_timeout lines as above + } +``` + ### Caddy Example ```caddyfile From 1db6b2e4ecbe4e2a251ee5ad7b3f8046a872cbf4 Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Fri, 25 Sep 2026 11:16:43 +0000 Subject: [PATCH 2/3] docs: make the nginx variable example a complete server block Signed-off-by: Oleksandr Piskun --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2676d82..8d347e2 100644 --- a/README.md +++ b/README.md @@ -127,16 +127,27 @@ server { If you point `proxy_pass` at a container or DNS name instead of an IP (for example `appapi-harp` on a Docker network), do not write the name into `proxy_pass` directly: nginx resolves it once at startup and refuses to -start whenever that container is absent (`host not found in upstream`), which takes the whole server block down. +start whenever that container is absent (`host not found in upstream`), which takes every site on that nginx down. Put the upstream in a variable, which nginx resolves per request, and give it a resolver: ```nginx +server { + listen 80; + server_name nextcloud.com; + resolver 127.0.0.11 valid=30s; # Docker's embedded DNS; use your own resolver outside Docker + # no /exapps/ suffix: with a variable, nginx would send every request to exactly that path set $harp_upstream http://appapi-harp:8780; + location /exapps/ { proxy_pass $harp_upstream; - # the same proxy_set_header and proxy_read_timeout lines as above + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 1800s; } +} ``` ### Caddy Example From 2c4a1e4911865073dad293e560ca75bfbcce04b8 Mon Sep 17 00:00:00 2001 From: Oleksandr Piskun Date: Fri, 25 Sep 2026 12:20:12 +0000 Subject: [PATCH 3/3] docs: pass WebSockets in the nginx examples and scope the resolver note Signed-off-by: Oleksandr Piskun --- README.md | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8d347e2..0fb4329 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,9 @@ server { location /exapps/ { proxy_pass http://127.0.0.1:8780/exapps/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -125,10 +128,14 @@ server { } ``` -If you point `proxy_pass` at a container or DNS name instead of an IP (for example `appapi-harp` on a Docker -network), do not write the name into `proxy_pass` directly: nginx resolves it once at startup and refuses to -start whenever that container is absent (`host not found in upstream`), which takes every site on that nginx down. -Put the upstream in a variable, which nginx resolves per request, and give it a resolver: +The `proxy_http_version` and the `Upgrade`/`Connection` headers let WebSocket connections through to ExApps; +nginx drops them otherwise. + +If you point `proxy_pass` at a container or DNS name instead of an IP (for example `appapi-harp` on a +user-defined Docker network), do not write the name into `proxy_pass` directly: nginx resolves it once at startup +and refuses to start whenever that container is absent (`host not found in upstream`), which takes every site on +that nginx down. Put the upstream in a variable, which nginx resolves per request, and give it a resolver. Use +this block instead of the one above, not next to it: ```nginx server { @@ -141,6 +148,9 @@ server { location /exapps/ { proxy_pass $harp_upstream; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -150,6 +160,10 @@ server { } ``` +`127.0.0.11` only answers inside containers on a user-defined network (such as a Compose network), not on the +default `bridge` network and not for nginx on the host. nginx's `resolver` also ignores `/etc/hosts`, so names +added with `--add-host` or `extra_hosts` do not resolve this way; keep the plain `proxy_pass` form for those. + ### Caddy Example ```caddyfile