Under podman's pasta networking the container gets copies of the host's addresses, including its FIPS address, so relaying to the node's own npub connected back into the container and was refused (502). When the computed address is one of the container's own, send the request to the host's mapped address (host.containers.internal) instead. Other npubs still go straight over the mesh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
4.8 KiB
Nginx Configuration File
130 lines
4.8 KiB
Nginx Configuration File
# Main nginx config for the podsteadr-player image (replaces /etc/nginx/nginx.conf).
|
|
# Runs as the image's unprivileged user; everything writable lives in /tmp so the
|
|
# container can run with a read-only root filesystem.
|
|
|
|
load_module modules/ngx_http_js_module.so;
|
|
|
|
worker_processes auto;
|
|
pid /tmp/nginx.pid;
|
|
error_log /dev/stderr warn;
|
|
|
|
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
include /etc/nginx/mime.types;
|
|
default_type application/octet-stream;
|
|
access_log off;
|
|
server_tokens off;
|
|
sendfile on;
|
|
keepalive_timeout 65;
|
|
|
|
client_body_temp_path /tmp/client_temp;
|
|
proxy_temp_path /tmp/proxy_temp;
|
|
fastcgi_temp_path /tmp/fastcgi_temp;
|
|
uwsgi_temp_path /tmp/uwsgi_temp;
|
|
scgi_temp_path /tmp/scgi_temp;
|
|
|
|
js_path /etc/nginx/njs/;
|
|
js_import fips.js;
|
|
js_set $fips_addr fips.address;
|
|
|
|
# Generous: behind podman's port forwarding many clients can share one source address.
|
|
limit_req_zone $binary_remote_addr zone=fips_feeds:10m rate=10r/s;
|
|
limit_conn_zone $binary_remote_addr zone=fips_conns:10m;
|
|
|
|
server {
|
|
listen 8097;
|
|
listen [::]:8097;
|
|
server_name _;
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
add_header X-Content-Type-Options nosniff always;
|
|
add_header Referrer-Policy no-referrer always;
|
|
|
|
# Pure client-side SPA — everything else falls back to index.html.
|
|
location / {
|
|
add_header Cache-Control "no-cache";
|
|
add_header X-Content-Type-Options nosniff always;
|
|
add_header Referrer-Policy no-referrer always;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
# Content-hashed build output: safe to cache forever.
|
|
location /assets/ {
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
add_header X-Content-Type-Options nosniff always;
|
|
}
|
|
|
|
# The service worker must be revalidated on every load or updates never reach installed apps.
|
|
location = /sw.js {
|
|
add_header Cache-Control "no-cache";
|
|
add_header X-Content-Type-Options nosniff always;
|
|
}
|
|
|
|
location = /manifest.webmanifest {
|
|
default_type application/manifest+json;
|
|
add_header Cache-Control "no-cache";
|
|
add_header X-Content-Type-Options nosniff always;
|
|
}
|
|
|
|
location = /healthz {
|
|
access_log off;
|
|
default_type text/plain;
|
|
return 200 "ok\n";
|
|
}
|
|
|
|
# ---- FIPS gateway ----------------------------------------------------
|
|
# /fips/<npub>.fips/<port>/<path> -> http://[<fips address>]:<port>/<path>,
|
|
# used when the player is opened over HTTPS or a LAN address (a browser
|
|
# can't speak FIPS, and an https page can't load http:// URLs). The
|
|
# address is computed from the npub (njs/fips.js), so this needs only
|
|
# IPv6 egress to the mesh, not DNS. This node's own npub goes to the
|
|
# host (host.containers.internal) instead: under pasta the container
|
|
# shares the host's FIPS address, so it can't connect to it.
|
|
#
|
|
# Deliberately NOT a general mesh proxy: mesh peers expose things (node
|
|
# UIs, the peer API) that must not be reachable through this port. Only
|
|
# podcast content passes: podsteadr catalogs/feeds on 8095 and blossom
|
|
# blobs on 8098, GET/HEAD only, no client cookies or credentials.
|
|
|
|
location ~ "^/fips/(?<fips_host>npub1[02-9ac-hj-np-z]{58}\.fips)/8095/(?<fips_path>catalog\.opml|feeds/[A-Za-z0-9_-]+/feed\.xml)$" {
|
|
if ($fips_addr = "") { return 404; }
|
|
limit_except GET { deny all; }
|
|
limit_req zone=fips_feeds burst=40 nodelay;
|
|
|
|
# Host is what makes podsteadr write mesh (.fips) enclosure URLs into the feed.
|
|
proxy_pass http://$fips_addr:8095/$fips_path;
|
|
proxy_set_header Host $fips_host:8095;
|
|
proxy_set_header Cookie "";
|
|
proxy_set_header Authorization "";
|
|
proxy_hide_header Set-Cookie;
|
|
proxy_connect_timeout 20s;
|
|
proxy_read_timeout 30s;
|
|
}
|
|
|
|
location ~ "^/fips/(?<fips_host>npub1[02-9ac-hj-np-z]{58}\.fips)/8098/(?<fips_path>[0-9a-f]{64}(?:\.[a-z0-9]{1,8})?)$" {
|
|
if ($fips_addr = "") { return 404; }
|
|
limit_except GET { deny all; }
|
|
limit_conn fips_conns 32;
|
|
|
|
# Range/If-Range pass through untouched, so seeking works; stream, don't buffer.
|
|
proxy_pass http://$fips_addr:8098/$fips_path;
|
|
proxy_set_header Host $fips_host:8098;
|
|
proxy_set_header Cookie "";
|
|
proxy_set_header Authorization "";
|
|
proxy_hide_header Set-Cookie;
|
|
proxy_http_version 1.1;
|
|
proxy_buffering off;
|
|
proxy_connect_timeout 20s;
|
|
proxy_read_timeout 120s;
|
|
}
|
|
|
|
location /fips/ {
|
|
return 404;
|
|
}
|
|
}
|
|
}
|