Good callout on Host and buffering. SignatureDoesNotMatch after putting nginx in front of MinIO is almost always the Host header or the request body being altered. proxy_set_header Host $host is mandatory when clients signed against the public CDN hostname; forwarding 127.0.0.1:9000 breaks the canonical request. For large uploads I also keep proxy_request_buffering off and raise client_max_body_size, otherwise nginx spools to disk and timeouts show up as flaky PUTs rather than a clean 413.
On the TLS side I terminate at nginx and leave MinIO on the docker network only. That means health checks should hit the internal port from the proxy host, not the public name, or you chase certificate errors that are not MinIO’s fault. One operational check after compose up: compare Content-Length and Accept-Ranges behavior through nginx versus direct-to-MinIO on the overlay network — if ranges break, look at proxy buffering and chunked_transfer_encoding before blaming the bucket policy.