Configuring MinIO for Public Read Access with Nginx Reverse Proxy
MinIO is an open-source object storage service based on the Apache License v2.0. It is compatible with the Amazon S3 cloud storage service interface and is very suitable for storing large amounts of unstructured data, such as images, videos, log files, backup data, and container/virtual machine images.
In a previous article titled Using Docker to Set Up MinIO Object Storage and Common mc Client Commands, we introduced how to set up MinIO. This article continues to share how to set MinIO buckets to public read and private write, and achieve public file access through Nginx reverse proxy.

Note: Users reading this article need a certain foundation in Linux knowledge and the habit of reading official documentation.
Prerequisites
You must have already set up the MinIO service, installed the mc client, and added the storage to the mc client configuration.
- For Docker setup, refer to: https://blog.xiaoz.org/archives/16215
- For other setup methods, refer to: http://docs.minio.org.cn/docs/ (Note: This Chinese version of the documentation may not be the latest; for the latest version, visit the English official website).
- Install the mc client: MinIO Client Quick Start Guide
Set MinIO Bucket to Public Read, Private Write
Users familiar with domestic object storage services may know that service providers offer a feature to set buckets to public read and private write, which is widely used for static file distribution. Since MinIO is compatible with the S3 protocol, S3 does not have the concept of "public read, private write" directly. Instead, S3 uses policy (access management policy).
To set a specific MinIO bucket to public read and private write, simply set the policy to download. The command is as follows:
# Set MinIO anonymous access policy. Options include: none, download, upload, public
mc policy set upload host/bucket/
# View anonymous policy
mc policy list host/bucket/
host: The name you set when runningmc config host add.bucket: The name of the bucket.
After setting, you can test by accessing http://IP:9000/bucket/file_name. If you can access the file directly without any parameters, the setting has taken effect.

Access via Nginx Reverse Proxy
MinIO's default access interface uses port 9000. Accessing it with the port number every time is inconvenient, so it is generally combined with Nginx reverse proxy. I have written an Nginx reverse proxy configuration that you can use as a reference:
server {
listen 443 ssl http2;
# Change to your own SSL certificate path
ssl_certificate /path/domain.com.crt;
ssl_certificate_key /path/domain.com.key;
ssl_session_timeout 1d;
# ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
proxy_buffering off;
# Change domain.com to your own domain
server_name domain.com;
# Path for website logs. Note that the Nginx user needs write permissions. If not needed, you can comment this out.
access_log /data/wwwlogs/domain.com.log combined;
charset utf-8,gbk;
location / {
# Enable custom error pages
proxy_intercept_errors on;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
# Change bucket to your own bucket name. Note: The end must have a /
proxy_pass http://127.0.0.1:9000/bucket/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Client cache time. Set to 7 days here, adjust according to your needs.
expires 7d;
add_header XCDN-Cache "$upstream_cache_status";
# You can upload an HTML file or image to the bucket beforehand to use as a 404 page, then change it to the absolute path under the bucket, starting with /. If not needed, you can comment it out.
error_page 404 /404.png;
}
}
server {
# 301 Redirect
listen 80;
server_name domain.com;
rewrite ^(.*) https://domain.com$1 redirect;
}
After setting, check if the configuration is correct with nginx -t, and reload the Nginx configuration with nginx -s reload. Then, test access via your domain http://domain.com/filename.
