From 333677dedfd8845b2c08d3024772a412c141bc8c Mon Sep 17 00:00:00 2001 From: emelinda Date: Wed, 22 Jul 2026 17:59:57 +0300 Subject: [PATCH] Add app-specific MinIO user with scoped bucket policy, update `.env.example`, `docker-compose.yaml`, and Nginx configuration accordingly --- .env.example | 9 +++++++-- docker-compose.yaml | 23 +++++++++++++++++------ nginx/templates/default.conf.template | 27 ++++++++------------------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/.env.example b/.env.example index b0f307a..71ae326 100644 --- a/.env.example +++ b/.env.example @@ -15,9 +15,14 @@ SAREX_RABBITMQ_PASSWORD=rabbit SAREX_MINIO_ROOT_USER=minioadmin SAREX_MINIO_ROOT_PASSWORD=minioadmin SAREX_MINIO_BUCKET=sarex-media-storage +# Отдельный пользователь приложения (не root) — под ним backend/celery ходят в S3. +# Секрет минимум 8 символов. Политика ограничена бакетом SAREX_MINIO_BUCKET. +SAREX_MINIO_APP_USER=sarex-app +SAREX_MINIO_APP_PASSWORD=sarex-app-secret +SAREX_MINIO_APP_POLICY=sarex-app-rw SAREX_MINIO_REGION=us-east-1 -# Внешний URL консоли MinIO (minio-домен, путь /console на верхнем nginx, https) -SAREX_MINIO_CONSOLE_URL=https://minio.sarex.local/console +# Внешний URL консоли MinIO (корень minio-домена на верхнем nginx, https) +SAREX_MINIO_CONSOLE_URL=https://minio.sarex.local # --- Домены верхнего nginx (замени на реальные, заведи в DNS/hosts) --- PLATFORM_DOMAIN=sarex.local # основной домен платформы (frontend + /api) diff --git a/docker-compose.yaml b/docker-compose.yaml index 368b0aa..cce1d13 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -149,12 +149,13 @@ services: environment: MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} - # Консоль отдаётся через верхний nginx на minio-домене по пути /console - MINIO_BROWSER_REDIRECT_URL: ${SAREX_MINIO_CONSOLE_URL:-https://minio.sarex.local/console} + # Консоль отдаётся через верхний nginx с корня minio-домена + MINIO_BROWSER_REDIRECT_URL: ${SAREX_MINIO_CONSOLE_URL:-https://minio.sarex.local} volumes: - sarex-minio-data:/data - # Одноразовый init: ждёт MinIO и создаёт бакет sarex-media-storage + # Одноразовый init: ждёт MinIO, создаёт бакет и отдельного пользователя + # приложения со scoped-политикой (доступ только к своему бакету). minio-init: image: cr.yandex/crp3ccidau046kdj8g9q/mc:250724 depends_on: @@ -167,11 +168,21 @@ services: echo 'waiting for minio...'; sleep 2; done mc mb -p "local/$$MINIO_BUCKET" - echo "bucket $$MINIO_BUCKET ready" + + # Пользователь приложения (не root) с доступом только к своему бакету + mc admin user add local "$$MINIO_APP_USER" "$$MINIO_APP_PASSWORD" + printf '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3:*"],"Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}]}' \ + "$$MINIO_BUCKET" "$$MINIO_BUCKET" > /tmp/app-policy.json + mc admin policy create local "$$MINIO_APP_POLICY" /tmp/app-policy.json || true + mc admin policy attach local "$$MINIO_APP_POLICY" --user "$$MINIO_APP_USER" || true + echo "bucket $$MINIO_BUCKET + user $$MINIO_APP_USER ready" environment: MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} MINIO_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage} + MINIO_APP_USER: ${SAREX_MINIO_APP_USER:-sarex-app} + MINIO_APP_PASSWORD: ${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret} + MINIO_APP_POLICY: ${SAREX_MINIO_APP_POLICY:-sarex-app-rw} restart: "no" # --------------------------------------------------------------------------- @@ -203,8 +214,8 @@ services: # S3 / объектное хранилище → MinIO (сервис minio) S3_HOST: http://minio:9000 AWS_S3_ENDPOINT_URL: http://minio:9000 - S3_LOGIN: ${SAREX_MINIO_ROOT_USER:-minioadmin} - S3_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} + S3_LOGIN: ${SAREX_MINIO_APP_USER:-sarex-app} + S3_PASSWORD: ${SAREX_MINIO_APP_PASSWORD:-sarex-app-secret} S3_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage} S3_REGION: ${SAREX_MINIO_REGION:-us-east-1} tty: true diff --git a/nginx/templates/default.conf.template b/nginx/templates/default.conf.template index ec4979f..fc0cb04 100644 --- a/nginx/templates/default.conf.template +++ b/nginx/templates/default.conf.template @@ -103,15 +103,17 @@ server { } # ============================== MinIO (отдельный домен) ===================== +# Консоль отдаётся с КОРНЯ домена (порт 9001) — так её статика (/static, /api, +# websocket) резолвится без сабпути. У сервиса minio: +# MINIO_BROWSER_REDIRECT_URL = https:// +# S3 API (:9000) здесь НЕ публикуется: backend ходит в minio:9000 по внутренней +# сети. Понадобится S3 наружу — заведи отдельный домен (напр. s3.<...>) на minio_s3. server { listen 80; listen 443 ssl; server_name ${MINIO_DOMAIN}; - # Веб-консоль администрирования (порт 9001). Требует у сервиса minio - # MINIO_BROWSER_REDIRECT_URL = http://:9080/console - location = /console { return 301 /console/; } # без слэша → на /console/ - location /console/ { + location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -121,23 +123,10 @@ server { proxy_set_header Connection $connection_upgrade; proxy_set_header X-NginX-Proxy true; chunked_transfer_encoding off; - proxy_pass http://minio_console; - } - - # S3 API (endpoint) на корне — Range/стриминг крупных объектов. - # Путь не переписываем, иначе ломается подпись SigV4. - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_http_version 1.1; - proxy_set_header Connection ""; - proxy_set_header Range $http_range; - proxy_set_header If-Range $http_if_range; + # крупные загрузки объектов через консоль proxy_buffering off; proxy_request_buffering off; proxy_max_temp_file_size 0; - proxy_pass http://minio_s3; + proxy_pass http://minio_console; } }