Перейти к содержанию

Файловое хранилище

Вложения и аватары хранятся как контентно-адресуемые blob-объекты: ключ хранилища вычисляется из хеша самого файла, поэтому одно и то же изображение, загруженное пятью людьми, хранится один раз, а при отдаче можно использовать неизменяемое кэширование.

Локальное хранилище (по умолчанию)

storage:
  driver: local

Blob-объекты находятся в user/data/forum-pro/ и отдаются по адресу {forum}/_file/<hash> с заголовками кэширования на очень долгий срок.

Предупреждение

Как и в случае с базой данных SQLite, стандартные конфигурации nginx не блокируют доступ к user/data/. См. примечание о nginx в разделе «Установка».

S3-совместимое хранилище

Направьте драйвер на любое S3-совместимое хранилище. Cloudflare R2 — рекомендуемый вариант, поскольку у него нет платы за исходящий трафик, но S3, Backblaze B2 и MinIO тоже работают.

storage:
  driver: s3
  s3:
    endpoint: https://<account>.r2.cloudflarestorage.com
    bucket: grav-forum
    region: auto
    access_key: '...'        # токен API R2 с правами Object Read & Write
    secret_key: '...'
    prefix: forum            # префикс ключей объектов внутри бакета
    public_url: ''           # публичный домен или домен CDN, когда он появится у бакета

Примечание

Учётные данные по замыслу доступны только в YAML. Не храните их в системе контроля версий — например, вынесите блок storage в конфигурацию для конкретного окружения или используйте псевдонимы конфигурации Grav и поддержку .env.

Зависимости от AWS SDK нет. Подпись запросов реализована в самом плагине, что уменьшает размер установки и избегает большого дерева транзитивных зависимостей.

Как взаимодействуют локальное и удалённое хранилище

Переход на s3 ничего не осиротит:

  • Новые загрузки отправляются в бакет и остаются в локальном кэше.
  • Blob-объект, отсутствующий локально, подгружается из бакета при первом запросе, а затем кэшируется.
  • Поэтому отдача никогда не зависит от доступности бакета для контента, который уже есть локально.

Доставка через CDN

Когда у бакета появится публичный домен, укажите его:

storage:
  s3:
    public_url: https://cdn.example.com

После этого страницы будут ссылаться на файлы напрямую в CDN. Это применяется во время рендеринга, а не записывается в базу, поэтому включение или отключение мгновенно и обратимо без перезаписи и миграции.

Перенос существующих файлов

Обе команды идемпотентны, поэтому прерванный запуск можно продолжить, выполнив команду снова.

bin/plugin forum-pro files-sync      # отправить локальные blob-объекты в S3/R2
bin/plugin forum-pro avatars-sync    # перенести старые аватары в blob-хранилище

avatars-sync нужна после обновления со старой структуры или после импорта, записавшего аватары вне blob-хранилища.

  1. Настройте storage.s3 с учётными данными, оставив public_url пустым.
  2. Установите driver: s3.
  3. Запустите files-sync, затем avatars-sync.
  4. Убедитесь, что вложения и аватары по-прежнему загружаются (они будут загружаться из локального кэша).
  5. Добавьте public_url и проверьте, что страницы теперь ссылаются на CDN.

Ограничения вложений

Ограничения проверяются до записи данных и задаются в блоке attachments:

attachments:
  enabled: true
  max_size_kb: 4096         # на файл
  max_per_post: 8
  member_daily_limit: 40    # 0 отключает
  draft_ttl_hours: 24       # невостребованные загрузки истекают через это время
  purge_grace_days: 7       # осиротевшие файлы удаляются через столько дней после пометки
  # allowed_extensions: [png, jpg, gif, webp, svg, pdf, zip, txt, log, md, yaml, json, csv, mp4, mov]

allowed_extensions доступен только в YAML. От svg стоит отказаться, если вы разрешаете загрузку недоверенным участникам, поскольку SVG — исполняемый формат в контексте браузера.

Очистка

У загрузок есть жизненный цикл:

  1. Файл, загруженный, но не прикреплённый к отправленному сообщению, считается черновиком и истекает через draft_ttl_hours.
  2. Файл, сообщение которого удалено, становится осиротевшим и помечается.
  3. Помеченные осиротевшие файлы удаляются фоновым процессом через purge_grace_days.

Льготный период существует для того, чтобы восстановление удалённого сообщения в пределах окна отмены также восстанавливало его вложения.

Временные участники

При provisional.block_attachments: true (значение по умолчанию) новые учётные записи вообще не могут загружать файлы. См. Защиту от спама.

Примечание о URL вложений

URL blob-объектов — это capability-URL без проверки авторизации: любой, у кого есть URL, может получить файл, включая вложения из личных сообщений. Это осознанный компромисс, который делает возможными контентно-адресуемую дедупликацию и доставку через CDN. Считайте вложение на форуме потенциально доступным при утечке, а не хранилищем приватных документов.