# Musify edge. The nginx entrypoint renders this with envsubst into # /etc/nginx/conf.d/default.conf (replacing the image's stock file) using the # MUSIFY_* variables set in compose.prod.yml. # # Cloudflare (Full strict) terminates the public edge; this box only needs to # serve the Cloudflare Origin Certificate in nginx/certs/. Each vhost proxies to # a compose service by name through the embedded Docker DNS resolver, so nginx # re-resolves it instead of caching the IP of a container that may be recreated. resolver 127.0.0.11 valid=10s; # YouTube artwork the web player proxies from Google. Caching it on disk keeps # repeated searches off both the node process and Google, which answers 429 # once a client pulls a whole grid of covers at a time. proxy_cache_path /var/cache/nginx/thumbnails levels=1:2 keys_zone=thumbnails:10m max_size=${MUSIFY_THUMBNAIL_CACHE_SIZE} inactive=30d use_temp_path=off; map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name ${MUSIFY_ROOT_DOMAIN} www.${MUSIFY_ROOT_DOMAIN} api.${MUSIFY_ROOT_DOMAIN} auth.${MUSIFY_ROOT_DOMAIN} stream.${MUSIFY_ROOT_DOMAIN} s3.${MUSIFY_ROOT_DOMAIN}; return 301 https://$host$request_uri; } # Web player (SvelteKit, adapter-node). Uploads are posted to its own form # actions, so it needs the large body size too. server { listen 443 ssl; http2 on; server_name ${MUSIFY_ROOT_DOMAIN}; client_max_body_size ${MUSIFY_MAX_UPLOAD_SIZE}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; location = /api/youtube/thumbnail { set $upstream http://web-player:3000; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; proxy_cache thumbnails; proxy_cache_key $uri$is_args$args; proxy_cache_valid 200 30d; proxy_cache_valid 400 404 5m; proxy_cache_lock on; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_background_update on; add_header X-Cache-Status $upstream_cache_status; } location / { set $upstream http://web-player:3000; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; } } server { listen 443 ssl; http2 on; server_name www.${MUSIFY_ROOT_DOMAIN}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; return 301 https://${MUSIFY_ROOT_DOMAIN}$request_uri; } server { listen 443 ssl; http2 on; server_name api.${MUSIFY_ROOT_DOMAIN}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; location / { set $upstream http://api:5111; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; } } # Audio bytes. Buffering off keeps range requests (seeking) responsive. server { listen 443 ssl; http2 on; server_name stream.${MUSIFY_ROOT_DOMAIN}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; location / { set $upstream http://gateway:8081; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; proxy_buffering off; } } server { listen 443 ssl; http2 on; server_name auth.${MUSIFY_ROOT_DOMAIN}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; location / { set $upstream http://zitadel:8080; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; grpc_set_header Host $host; } } # Presigned S3 PUT/GET straight from the browser. server { listen 443 ssl; http2 on; server_name s3.${MUSIFY_ROOT_DOMAIN}; client_max_body_size ${MUSIFY_MAX_UPLOAD_SIZE}; ssl_certificate /etc/nginx/certs/origin.pem; ssl_certificate_key /etc/nginx/certs/origin.key; location / { set $upstream http://seaweedfs:8333; proxy_pass $upstream; include /etc/nginx/snippets/proxy.conf; proxy_request_buffering off; } }