Skip to content

MinIO reverse-proxy (опционально)

Если пользователь грузит/скачивает медиа из браузера, а MinIO узла доступен только в Tailscale, включается reverse-proxy на стороне студии. Без него presigned-ссылки указывают на внутренний Tailscale-адрес http://100.x.x.x:9000/..., недоступный из браузера обычного пользователя.

Как это работает

  1. На backend задайте MINIO_PROXY_BASE_URL, например https://neurocast.tech/storage (.env.example:77-81). Когда переменная пуста — presigned-URL отдаются «как есть» (обратная совместимость).
  2. Студия переписывает URL: http://100.x.x.x:9000/bucket/objecthttps://<домен>/storage/100.x.x.x/9000/bucket/object.
  3. На nginx добавьте location-блок из готового референса docs/nginx-minio-proxy.conf в server { listen 443 ssl; }. Блок извлекает IP/порт из пути, проксирует на нужный узел, ограничивает цель диапазоном 100.64.0.0/10, поднимает client_max_body_size 2G и таймауты до 600s.

nginx location-блок

Референс: nginx-minio-proxy.conf.

nginx
# ── MinIO reverse proxy — dynamic target via path ──────────────────────
location ~ ^/storage/(100\.\d+\.\d+\.\d+)/(\d+)/(.*) {
    set $minio_host $1;
    set $minio_port $2;
    set $minio_path $3;

    # Resolver for variable proxy_pass (nginx requires explicit resolver
    # when target is a variable). Use systemd-resolved or public DNS.
    resolver 127.0.0.53 valid=30s ipv6=off;

    # Proxy to the Contour Node MinIO at the extracted Tailscale IP
    proxy_pass http://$minio_host:$minio_port/$minio_path$is_args$args;

    # Preserve Host header to match MinIO presigned signature
    proxy_set_header Host $minio_host:$minio_port;

    # Large file uploads: 2 GB max, no buffering, long timeouts
    client_max_body_size 2G;
    proxy_request_buffering off;
    proxy_connect_timeout 600s;
    proxy_send_timeout 600s;
    proxy_read_timeout 600s;
}

⚠️ proxy_set_header Host сохраняет IP:port, потому что подпись presigned-ссылки MinIO завязана на исходный Host — при его подмене скачивание/загрузка вернёт ошибку подписи.