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).
70 lines
2.5 KiB
Plaintext
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;
|
|
}
|