Шаблоны конфигурации в репозитории написаны под SWAG, но библиотеке всё равно, кто стоит перед ней. Важно только, чтобы фронтенд умел две вещи: отдавать статику из тома и говорить с php-fpm по FastCGI. Эта статья — о том, как это сделать с тремя другими популярными reverse proxy.
Что нужно библиотеке от фронтенда
-
Статика из тома. Контейнер библиотеки при старте выкладывает содержимое
application/public(JS-читалки, CSS, картинки, шрифты) в именованный томflibusta_public_files. Веб-сервер монтирует этот том и отдаёт файлы сам; PHP-файлы в томе намеренно пустые — они там только для того, чтобыtry_filesнаходил путь. -
FastCGI к
flibusta-fpm:9000для всего, что оканчивается на.phpи для всего, что не найдено как файл (переписывается наindex.php).SCRIPT_FILENAMEдолжен указывать на путь внутри контейнера библиотеки:/application/public/<имя>.php. -
Параметры FastCGI, от которых зависит поведение приложения:
Параметр Зачем REMOTE_ADDRадрес клиента: FLIBUSTA_TRUSTED_NET, лог попыток входа, блокировки, fail2banHTTP_X_FORWARDED_PROTO(илиHTTPS)определение HTTPS для административных разделов HTTP_HOST,REQUEST_URIпостроение ссылок, адрес OPDS в «Справке» HTTP_USER_AGENTпривязка сессии к браузеру HTTP_AUTHORIZATION,PHP_AUTH_USERHTTP Basic для OPDS и прямых ссылок на файлы -
Заголовок
Content-Security-Policy: worker-src * blob:на ответах PHP — без него pdf.js не сможет запустить web worker и pdf-книги не откроются в браузере. -
Лимит размера тела запроса не меньше 500 МБ, если планируете загружать книги через «Добавить» (
client_max_body_sizeв nginx и аналоги). -
HTTPS — административные разделы без него не работают.
Всё это есть в шаблонах flibusta.subdomain.conf и flibusta.subfolder.conf
в docs_and_configs/external_services_config/; их стоит держать перед
глазами как эталон.
Универсальный путь: nginx-сайдкар
Если ваш reverse proxy не умеет FastCGI (Traefik) или умеет, но неудобно
(Nginx Proxy Manager), самое надёжное — поставить рядом с библиотекой
маленький контейнер nginx:alpine, который делает всё из списка выше, и
проксировать на него обычным HTTP. В репозитории есть готовый конфиг для
такого сервера — phpdocker/nginx/nginx.conf (тот самый, что используется в
устаревшей all-in-one конфигурации). Его нужно чуть доработать, потому что
теперь перед ним стоит ещё один прокси:
server {
listen 80;
client_max_body_size 508M;
# адрес клиента и схема приходят от внешнего прокси
set_real_ip_from 172.16.0.0/12; # подсети Docker, где живёт внешний прокси
real_ip_header X-Forwarded-For;
real_ip_recursive on;
root /application/public;
index index.php;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
add_header 'Content-Security-Policy' 'worker-src * blob:';
include fastcgi_params;
fastcgi_pass flibusta-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param HTTP_HOST $http_host;
fastcgi_param HTTP_X_REAL_IP $remote_addr;
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto; # не $scheme!
fastcgi_param HTTP_USER_AGENT $http_user_agent;
fastcgi_param PHP_AUTH_USER $remote_user;
fastcgi_param HTTP_AUTHORIZATION $http_authorization;
}
}
Два отличия от оригинала: блок real_ip, чтобы $remote_addr стал адресом
настоящего клиента, а не внешнего прокси, и HTTP_X_FORWARDED_PROTO из
заголовка, а не из $scheme (иначе библиотека решит, что соединение по
HTTP, и закроет административные разделы). Подсеть в set_real_ip_from
должна включать адрес внешнего прокси в Docker-сети.
Сервис в docker-compose библиотеки:
flibusta-web:
image: nginx:alpine
container_name: flibusta-web
restart: unless-stopped
volumes:
- flibusta_public_files:/application/public:ro
- ./nginx-sidecar.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- flibusta_net # к flibusta-fpm
- proxy_net # к внешнему reverse proxy
Наружу порт не публикуется; внешний прокси ходит на flibusta-web:80 по
общей сети. Для subfolder-схемы (/flibusta) подмените location / и
fastcgi_split_path_info по образцу flibusta.subfolder.conf.
Дальше — как подключить flibusta-web (или напрямую flibusta-fpm, где это
возможно) к каждому из прокси.
Nginx Proxy Manager
NPM — это nginx с веб-панелью, так что FastCGI он умеет, но панель заточена
под proxy_pass. Каждый «Proxy Host» генерирует свой location /, и
попытка объявить ещё один location / во вкладке Advanced закончится
ошибкой конфигурации. Практичных варианта два.
С сайдкаром (рекомендуется). Создайте Proxy Host: домен
flibusta.example.org, схема http, Forward Host flibusta-web, порт 80,
включите SSL с Let’s Encrypt и Force SSL. NPM сам передаст X-Forwarded-For
и X-Forwarded-Proto. Контейнер NPM должен быть в той же Docker-сети, что и
flibusta-web (proxy_net в примере выше). Во вкладке Advanced добавьте
только лимит на загрузку:
client_max_body_size 508M;
Без сайдкара, subfolder-схема. Смонтируйте том статики в контейнер NPM
(flibusta_public_files:/srv/flibusta:ro), подключите NPM к flibusta_net,
создайте Proxy Host для основного домена (Forward Host — что угодно живое,
он будет обслуживать /), и во вкладке Advanced вставьте содержимое
flibusta.subfolder.conf — блок location ^~ /flibusta { … } с другим
префиксом не конфликтует с location /. В библиотеке задайте
FLIBUSTA_WEBROOT=/flibusta. Пути к логам в шаблоне (/config/log/nginx/…)
замените на /data/logs/… или уберите.
Caddy
Caddy умеет FastCGI «из коробки» и сам получает сертификаты, поэтому сайдкар не нужен. Caddyfile для subdomain-схемы:
flibusta.example.org {
root * /srv/flibusta # том flibusta_public_files
encode gzip
request_body {
max_size 512MB
}
header Content-Security-Policy "worker-src * blob:"
php_fastcgi flibusta-fpm:9000 {
# SCRIPT_FILENAME должен указывать на путь внутри контейнера библиотеки
root /application/public
}
file_server
}
php_fastcgi сам делает try_files с откатом на index.php, передаёт
REMOTE_ADDR с адресом клиента, ставит HTTPS=on при TLS и прокидывает
заголовки запроса как HTTP_*, включая HTTP_AUTHORIZATION для OPDS.
Поддиректива root внутри php_fastcgi переопределяет корень только для
SCRIPT_FILENAME — именно то, что нужно, когда файлы у Caddy лежат в одном
месте, а у php-fpm в другом.
Docker-compose для Caddy: том flibusta_public_files:/srv/flibusta:ro, сеть
flibusta_net, порты 80 и 443, том для сертификатов (caddy_data).
Subfolder-схему в Caddy сделать можно (handle_path /flibusta/* плюс
php_fastcgi с теми же параметрами), но try_files для вложенного пути
требует аккуратности; если есть выбор — берите subdomain.
Конфигурация выше составлена по документации Caddy, а не снята с рабочей установки; после запуска проверьте три вещи: открывается ли pdf-книга (CSP), показывается ли в разделе «Пользователи» предупреждение о HTTP (HTTPS определяется корректно) и правильный ли адрес в «Активности пользователей» после входа (REMOTE_ADDR).
Traefik
Traefik не говорит по FastCGI вообще, поэтому сайдкар обязателен. Traefik
подключается к нему через labels на сервисе flibusta-web:
flibusta-web:
image: nginx:alpine
# ... тома и конфиг как в разделе про сайдкар
networks:
- flibusta_net
- traefik_net
labels:
- traefik.enable=true
- traefik.docker.network=traefik_net
- traefik.http.routers.flibusta.rule=Host(`flibusta.example.org`)
- traefik.http.routers.flibusta.entrypoints=websecure
- traefik.http.routers.flibusta.tls.certresolver=letsencrypt
- traefik.http.services.flibusta.loadbalancer.server.port=80
Traefik по умолчанию добавляет X-Forwarded-For и X-Forwarded-Proto, а
set_real_ip_from в сайдкаре должен включать подсеть traefik_net. Если
Traefik сам стоит за ещё одним прокси (Cloudflare), не забудьте
forwardedHeaders.trustedIPs на entrypoint, иначе в X-Forwarded-For будет
адрес Cloudflare.
Лимит на размер тела запроса Traefik не накладывает (есть middleware
buffering, но по умолчанию он выключен), так что 500 МБ упрутся только в
client_max_body_size сайдкара.
Как проверить, что всё подключено правильно
Один проход по чек-листу закрывает почти все типичные ошибки интеграции:
- Главная страница открывается, есть стили и картинки — статика из тома работает.
- Открывается pdf-книга — CSP на месте.
- В «Пользователи → Сессии» ваш IP — реальный, а не
172.xконтейнера —REMOTE_ADDRпередаётся. - В «Пользователях» нет красного предупреждения об HTTP — схема определена верно.
- Читалка подключается к
/opdsс паролем —HTTP_AUTHORIZATIONдоходит. - Загрузка книги на 100+ МБ в «Добавить» проходит — лимиты тела запроса подняты.
Если что-то из этого не так — сверьтесь с таблицей параметров в начале статьи и с шаблоном для SWAG.