Развёртывание · s5w

Настройка

S5W настраивается только переменными окружения — конфигурационных файлов нет. Ни одна переменная не обязательна для запуска хранилища; для входа в панель нужны две — логин и пароль.

API и раздача :9090Панель :9091Данные /var/lib/s5wПрименение при старте контейнера

Когда применяются изменения

Переменные читаются при старте. Чтобы изменение вступило в силу, контейнер нужно пересоздать: docker compose up -d (compose сам пересоздаст изменённый сервис) или docker rm -f s5w и новый docker run с тем же томом. Простого docker restart недостаточно — он не меняет окружение контейнера.

Рекомендуемый запуск

docker compose

docker-compose.yml
services:
  s5w:
    image: flytachi/s5w:latest
    ports:
      - "9090:9090"   # API и раздача
      - "9091:9091"   # админ-панель
    environment:
      ADMIN_LOGIN: admin
      ADMIN_PASSWORD: ${S5W_ADMIN_PASSWORD}   # из .env рядом с compose-файлом
      PUBLIC_BASE_URL: https://files.example.com
      TIME_ZONE: Asia/Tashkent
      LOG_LEVEL: warning
    volumes:
      - s5w_data:/var/lib/s5w
    # Сначала останавливается приложение (до 35 с), потом PostgreSQL. Стандартных
    # 10 с у Docker не хватает: после SIGKILL база восстанавливается при следующем старте.
    stop_grace_period: 45s
    restart: unless-stopped

volumes:
  s5w_data:

docker run

bash
docker run -d --name s5w -p 9090:9090 -p 9091:9091 \
  -e ADMIN_LOGIN=admin -e ADMIN_PASSWORD="$S5W_ADMIN_PASSWORD" \
  -e PUBLIC_BASE_URL=https://files.example.com \
  -e TIME_ZONE=Asia/Tashkent \
  -e LOG_LEVEL=warning \
  -v s5w_data:/var/lib/s5w \
  --stop-timeout 45 \
  --restart unless-stopped \
  flytachi/s5w:latest

Все переменные

Переменная По умолчанию Кратко
ADMIN_LOGIN — Логин панели. Без него вход закрыт.
ADMIN_PASSWORD — Пароль панели. Без него вход закрыт.
ADMIN_UI true Запускать ли панель на 9091.
ADMIN_API (от ADMIN_UI) Откуда принимать admin API: local или public.
TRUSTED_PROXIES private Каким прокси верить в X-Forwarded-For.
PUBLIC_BASE_URL (адрес запроса) Базовый адрес ссылок на файлы.
TIME_ZONE UTC Часовой пояс статистики в панели, если браузер не сообщил свой.
CACHE_DEFAULT_MAX_AGE 86400 max-age по умолчанию для общего кэша.
CACHE_PRIVATE_MAX_AGE 0 max-age по умолчанию для приватного кэша.
LOG_LEVEL info Подробность логов.
LOG_OUTPUT auto Куда писать логи.
SERVER_MEMORY_LIMIT 512M Потолок памяти одного процесса.
SERVER_REQUEST_TIMEOUT 30 Таймаут обработки запроса, секунды.
WINTER_KEY (генерируется) Ключ подписи сессий и временных ссылок.

Переменные панели (ADMIN_*, TRUSTED_PROXIES) подробно разобраны на странице Админ-панель, переменные ресурсов (SERVER_*) — на странице Ресурсы и производительность. Ниже — остальные.

Настроек базы нет

И они не нужны: база встроенная и единственная, она слушает только внутри контейнера. Строку подключения, хост и пароль задавать не требуется — и подключить внешнюю базу нельзя.

PUBLIC_BASE_URL

Что делает. Задаёт начало всех адресов, которые сервис выдаёт сам: publicUrl и privateUrl у файлов, url у временных ссылок, адреса в панели. Пишется со схемой и без завершающего /: https://files.example.com.

Если не задана. Адрес собирается из запроса, который пришёл в сервис: схема, хост и порт. Пока клиенты ходят к сервису напрямую, это работает. За прокси результат зависит от того, какие заголовки он передаёт, а в панели адреса строятся от домена панели — то есть ведут не туда. Панель в этом случае показывает предупреждение.

Когда задавать. Всегда, если сервис стоит за прокси или у API отдельный домен. Указывайте адрес, по которому файлы доступны снаружи — домен API, а не панели.

Уже выданные ссылки

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

TIME_ZONE

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

Что не меняет. Расписание обслуживания (оно всегда в UTC), время в логах и время в ответах API — там оно с явным смещением (+00:00).

Значение. Имя из базы часовых поясов: Europe/Moscow, Asia/Tashkent. Неизвестное имя молча заменяется на UTC.

CACHE_DEFAULT_MAX_AGE и CACHE_PRIVATE_MAX_AGE

Что делают. Значения max-age в заголовке Cache-Control, которые берутся, когда ни у папки, ни у бакета свой max-age не задан. CACHE_DEFAULT_MAX_AGE — для общего кэша (public: браузер и CDN), по умолчанию сутки. CACHE_PRIVATE_MAX_AGE — для приватного (private: только браузер), по умолчанию 0: браузер каждый раз переспрашивает, а ETag делает такой запрос дешёвым.

Когда менять. Чтобы поменять поведение по умолчанию сразу для всех бакетов. Для отдельного бакета или папки удобнее задать политику в панели — она важнее этих переменных. Как именно собирается заголовок — на странице Кэширование.

LOG_LEVEL и LOG_OUTPUT

LOG_LEVEL — debug · info · warning · error. По умолчанию info: старт и остановка частей, создание бакетов, ошибки. Для рабочего сервера обычно хватает warning. Пустое значение выключает логи приложения.

LOG_OUTPUT — auto · stdout · stderr · file. auto — это stdout, и именно его собирает docker logs и любой сборщик логов контейнеров. file пишет в файлы внутри контейнера; в Docker это обычно не нужно.

Логи PostgreSQL и супервизора s6 идут в тот же вывод контейнера независимо от этих переменных.

WINTER_KEY

Что делает. Секретный ключ, которым подписаны сессии панели и временные ссылки /t/….

Если не задан. При первом запуске ключ генерируется и сохраняется в томе, в /var/lib/s5w/.runtime_secrets, а при следующих запусках читается оттуда. Пока том тот же, ключ тот же. В логе первого запуска это видно строкой WINTER_KEY auto-generated.

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

Если сменить. Все сессии панели и все выданные временные ссылки во всех бакетах перестают действовать. Файлы, токены доступа и публичные ссылки не затрагиваются.

Том /var/lib/s5w

text
/var/lib/s5w/
  postgresql/        кластер PostgreSQL — метаданные
  buckets/           файлы, по каталогу на бакет
  staging/           незавершённые загрузки частями
  .runtime_secrets   сгенерированный WINTER_KEY

Монтируйте один том целиком. Внутри него нет частей, которые можно вынести отдельно: buckets/ и staging/ должны быть на одной файловой системе (загрузка частями завершается переименованием, а оно атомарно только внутри одной ФС), а база без файлов и файлы без базы бесполезны.

Без тома контейнер одноразовый. Данные окажутся в слое контейнера и исчезнут при его пересоздании — а пересоздаётся он при каждом обновлении образа и при изменении переменных.

Каталог хоста вместо именованного тома допустим: -v /srv/s5w:/var/lib/s5w. Каталог должен быть на локальной файловой системе: PostgreSQL на сетевых ФС вроде NFS работает ненадёжно.

Версия PostgreSQL привязана к тому. Сейчас это 18. Если образ когда-нибудь перейдёт на новую мажорную версию, кластер потребует pg_upgrade — это будет отдельно описано в заметках к выпуску.

docker compose down -v

Флаг -v удаляет тома, а с ними — базу и все файлы. Для остановки используйте docker compose down без него или docker compose stop.

Порты

Внутри контейнера порты фиксированы: 9090 — API и раздача, 9091 — панель. Чтобы снаружи был другой порт, меняйте только публикацию: -p 8080:9090. За прокси в общей docker-сети порты можно не публиковать вовсе — см. За обратным прокси.