Skip to content

По умолчанию загруженные файлы (вложения поддержки, изображения FAQ, файлы партнёров, PWA-ассеты) хранятся локально в ./uploads. Используйте S3-совместимое хранилище для масштабируемости и надёжности.

Настройка

Шаг 1: Добавьте настройки S3 в .env

bash
# S3 Storage
S3_ENABLED=true
S3_ENDPOINT=http://rustfs:9000
S3_ACCESS_KEY=your_access_key
S3_SECRET_KEY=your_secret_key
S3_PUBLIC_URL=https://s3.example.com
S3_REGION=us-east-1
S3_BUCKET=files

Шаг 2: Добавьте переменные S3 в сервис бота

Убедитесь, что в compose.yaml в секции environment сервиса бота прокинуты все S3-переменные:

yaml
environment:
  - S3_ENABLED=${S3_ENABLED}
  - S3_ENDPOINT=${S3_ENDPOINT}
  - S3_ACCESS_KEY=${S3_ACCESS_KEY}
  - S3_SECRET_KEY=${S3_SECRET_KEY}
  - S3_PUBLIC_URL=${S3_PUBLIC_URL}
  - S3_REGION=${S3_REGION}
  - S3_BUCKET=${S3_BUCKET}

Внимание

Без этих переменных контейнер бота не будет знать о настройках S3, даже если они указаны в .env. Docker Compose передаёт в контейнер только те переменные, которые явно перечислены в секции environment.

Шаг 3: Выберите провайдера S3

Используйте один из вариантов ниже.

RustFS (self-hosted)

Добавьте сервис в compose.yaml:

yaml
rustfs:
  image: rustfs/rustfs:latest
  container_name: rwp_shop_rustfs
  restart: unless-stopped
  command: server /data --console-address ":9001"
  environment:
    - RUSTFS_ROOT_USER=your_access_key
    - RUSTFS_ROOT_PASSWORD=your_secret_key
  volumes:
    - rustfs_data:/data
  ports:
    - "127.0.0.1:9001:9001"
  networks:
    - remnawave-network

Добавьте volume:

yaml
volumes:
  rwp_shop_db_data:
  rustfs_data:

Опубликуйте публичный URL (нужен для presigned URLs) через reverse proxy:

txt
s3.example.com {
    import security_headers
    reverse_proxy rustfs:9000
}
nginx
server {
    listen 443 ssl http2;
    server_name s3.example.com;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        client_max_body_size 100M;
    }
}

Yandex Object Storage

Создайте бакет в Yandex Cloud → Object Storage. Получите статический ключ доступа в сервисном аккаунте с ролью storage.editor.

bash
# Yandex Object Storage
S3_ENABLED=true
S3_ENDPOINT=https://storage.yandexcloud.net
S3_ACCESS_KEY=<KEY_ID>
S3_SECRET_KEY=<SECRET>
S3_PUBLIC_URL=https://<BUCKET>.storage.yandexcloud.net
S3_REGION=ru-central1
S3_BUCKET=<BUCKET>

Для публичного доступа включите ACL public-read на бакете или используйте Website hosting. Подключите свой домен через CNAME <BUCKET>.website.yandexcloud.net.

VK Cloud (Hotbox)

В панели VK Cloud → Cloud Storage создайте проект и Hotbox-бакет. Сгенерируйте S3 ключи в разделе аккаунта.

bash
# VK Cloud Hotbox
S3_ENABLED=true
S3_ENDPOINT=https://hb.ru-msk.vkcs.cloud
S3_ACCESS_KEY=<ACCESS_KEY>
S3_SECRET_KEY=<SECRET_KEY>
S3_PUBLIC_URL=https://<BUCKET>.hb.ru-msk.vkcs.cloud
S3_REGION=ru-msk
S3_BUCKET=<BUCKET>

Icebox дешевле, но не подходит — латентность высокая. Используйте только Hotbox.

Selectel Object Storage

Создайте контейнер в панели Selectel → Облачное хранилище. Выберите тип «S3-совместимый». Сгенерируйте сервисного пользователя с ключами S3.

bash
# Selectel Object Storage
S3_ENABLED=true
S3_ENDPOINT=https://s3.ru-1.storage.selcloud.ru
S3_ACCESS_KEY=<ACCESS_KEY>
S3_SECRET_KEY=<SECRET_KEY>
S3_PUBLIC_URL=https://<BUCKET>.s3.ru-1.storage.selcloud.ru
S3_REGION=ru-1
S3_BUCKET=<BUCKET>

Для публичных файлов установите контейнеру тип «публичный» в панели. Альтернативно — подключите CDN Selectel.

Timeweb Cloud Storage

В панели Timeweb Cloud → Облачное хранилище создайте бакет. Ключи доступа в разделе «API и интеграции».

bash
# Timeweb Cloud Storage
S3_ENABLED=true
S3_ENDPOINT=https://s3.timeweb.cloud
S3_ACCESS_KEY=<ACCESS_KEY>
S3_SECRET_KEY=<SECRET_KEY>
S3_PUBLIC_URL=https://<BUCKET>.s3.timeweb.cloud
S3_REGION=ru-1
S3_BUCKET=<BUCKET>

Установите политику бакета public-read через AWS CLI, либо включите публичный доступ в панели.

Cloud.ru Evolution Object Storage

Создайте бакет в Cloud.ru → Evolution Object Storage. Сгенерируйте ключи в IAM.

bash
# Cloud.ru Evolution Object Storage
S3_ENABLED=true
S3_ENDPOINT=https://s3.cloud.ru
S3_ACCESS_KEY=<TENANT_ID>:<KEY_ID>
S3_SECRET_KEY=<SECRET>
S3_PUBLIC_URL=https://<BUCKET>.s3.cloud.ru
S3_REGION=ru-central-1
S3_BUCKET=<BUCKET>

S3_ACCESS_KEY формируется как <tenant_id>:<key_id> — особенность Cloud.ru. Публичный доступ настраивается через политику бакета.

Cloudflare R2

Создайте бакет и S3 API ключи в панели Cloudflare. R2 использует S3-совместимый endpoint формата https://<ACCOUNT_ID>.r2.cloudflarestorage.com.

bash
# Cloudflare R2
S3_ENABLED=true
S3_ENDPOINT=https://<ACCOUNT_ID>.r2.cloudflarestorage.com
S3_ACCESS_KEY=<R2_ACCESS_KEY_ID>
S3_SECRET_KEY=<R2_SECRET_ACCESS_KEY>
S3_PUBLIC_URL=https://<YOUR_PUBLIC_BUCKET_URL>
S3_REGION=auto              # R2 использует "auto" как регион
S3_BUCKET=files             # рекомендуется для R2 free tier (лимит бакетов)

S3_PUBLIC_URL должен указывать на публичный URL бакета, включённый в R2 (custom domain или управляемый r2.dev). Egress бесплатный — выгодно для раздачи медиа.

Настройка CORS

Для прямой загрузки/скачивания через presigned URLs настройте CORS на бакете. Пример правила:

json
[
  {
    "AllowedOrigins": ["https://your-domain.com"],
    "AllowedMethods": ["GET", "PUT", "HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 86400
  }
]

Замените https://your-domain.com на домен фронтенда/Mini App. Для wildcard поддоменов: https://*.your-domain.com.

Шаг 4: Перезапустите бота

bash
docker compose up -d

Примечание

Переменные окружения

ПеременнаяОписание
S3_ENABLEDВключить S3 хранилище (true/false)
S3_ENDPOINTEndpoint S3 API
S3_ACCESS_KEYКлюч доступа S3
S3_SECRET_KEYСекретный ключ S3
S3_PUBLIC_URLПубличный HTTPS URL для presigned URLs
S3_REGIONРегион S3 (по умолчанию: us-east-1). Требуется для AWS и некоторых S3-совместимых провайдеров
S3_BUCKETОпциональное имя родительского бакета. Если задано, все логические бакеты становятся префиксами ключей внутри одного бакета

Внимание

S3_PUBLIC_URL обязателенS3_PUBLIC_URL должен быть публичным HTTPS URL. Он используется для генерации presigned URLs для прямых скачиваний файлов.