Files
openconcho/docker/nginx.conf.template
Offending Commit 66b299a28e fix(docker): derive nginx resolver from container DNS
Hardcoded resolver 127.0.0.11 only exists on user-defined networks, so a plain
docker run on the default bridge 502'd (DNS connection refused). Render the
resolver from /etc/resolv.conf at start so per-request proxy_pass resolves on
both the default bridge (host DNS) and compose networks (embedded DNS).
2026-06-02 13:33:50 -05:00

70 lines
2.5 KiB
Plaintext

# OpenConcho — nginx site config.
# Serves the React SPA and header-driven same-origin /api proxy to Honcho.
# The browser sends X-Honcho-Upstream per request; nginx forwards server-side (no browser CORS).
server {
listen 8080;
listen [::]:8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Don't leak the nginx version.
server_tokens off;
# The resolver (required for per-request DNS with a runtime-variable proxy_pass)
# is rendered by the entrypoint into conf.d from the container's own DNS, so it
# works on both user-defined networks (127.0.0.11) and the default bridge.
# Header-driven same-origin proxy: the browser names the Honcho upstream per
# request via X-Honcho-Upstream, so the browser never makes a cross-origin call.
# $allow_upstream is provided by the allowlist map in conf.d (entrypoint-rendered).
location ^~ /api/ {
set $upstream $http_x_honcho_upstream;
if ($upstream = "") {
add_header X-Honcho-Proxy-Reject "no-upstream" always;
return 421;
}
if ($allow_upstream = 0) {
add_header X-Honcho-Proxy-Reject "allowlist" always;
return 403;
}
rewrite ^/api/(.*)$ /$1 break;
proxy_pass $upstream;
proxy_ssl_server_name on;
proxy_set_header Host $proxy_host;
proxy_set_header X-Honcho-Upstream "";
}
# Runtime config — regenerated per container start, must never be cached.
location = /config.js {
add_header Cache-Control "no-cache, no-store, must-revalidate";
try_files $uri =404;
}
# Long-cache static assets — Vite hashes filenames so they're immutable.
location ~* \.(?:js|mjs|css|woff2?|ttf|otf|eot|svg|png|jpg|jpeg|gif|ico|webp|avif|wasm)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
try_files $uri =404;
}
# Container healthcheck (local; distinct from Honcho's /health).
location = /healthz {
access_log off;
default_type text/plain;
return 200 "ok\n";
}
# SPA fallback: unknown paths return index.html so the router resolves them.
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
}