Эта статья устроена как справочник «симптом → причина → что делать». Первым делом при любой проблеме — два источника правды:

docker logs --tail 100 flibusta-fpm       # старт, инициализация БД, ошибки PHP
docker compose logs --tail 100 swag       # (или ваш reverse proxy)

Где лежат остальные логи — в конце статьи о скриптах.

docker compose up не доходит до запуска контейнеров

Если compose ругается и ни один контейнер не создаётся, дело в самом файле — логов смотреть негде, сообщение приходит от парсера.

services.flibusta-fpm.environment.[16]: unexpected type map[string]interface {} — в environment есть строка, кончающаяся двоеточием, без кавычек. Почти всегда это префикс ключей Redis:

      - FLIBUSTA_REDIS_PREFIX=flibusta:        # ошибка
      - "FLIBUSTA_REDIS_PREFIX=flibusta:"      # правильно

Двоеточие в конце строки YAML считает признаком ключа, и элемент списка становится отображением {"FLIBUSTA_REDIS_PREFIX=flibusta": null} вместо строки. Номер в квадратных скобках — порядковый номер элемента в environment, считая с нуля и пропуская закомментированные строки. Сообщение указывает на flibusta-fpm, даже если вы правили совсем другой сервис: просто именно здесь compose споткнулся первым.

services.<имя> Additional property name is not allowed — у сервиса указан ключ name. Имя контейнера задаётся как container_name; name допустим только на верхнем уровне файла и внутри описаний networks, volumes и secrets.

Полезная привычка: docker compose config печатает файл после разбора и подстановки переменных, ничего не запуская. Если вывод есть — синтаксис в порядке, и заодно видно, во что развернулись ${...}.

Контейнер не стартует или сразу останавливается

Смотрите docker logs flibusta-fpm, там будет одна из строк:

<host> is unreachable, can not access DB, exiting — контейнер не видит Postgres по имени из FLIBUSTA_DBHOST. Проверьте, что оба контейнера в сети postgres_db_net (docker network inspect postgres_db_net), что имя хоста — это имя контейнера Postgres, и что Postgres успел стартовать (увеличьте DB_HOST_PINGS, если он медленный).

Attempt to initialize postgres DB has failed. Cant obtain PG admin password — роли flibusta ещё нет, а файл из POSTGRES_ADMIN_DBPASSWORD_FILE не найден или пуст. Проверьте секцию secrets и права на файл (uid 82).

Can't connect to the DB after initialization attempt, exiting — инициализация прошла с ошибками. Выше в логе будет вывод psql. Обычно это либо неверный пароль администратора Postgres (частая причина — перевод строки в конце файла секрета, проверьте wc -l), либо у аккаунта нет прав CREATEROLE / CREATEDB, либо роль flibusta есть, но пароль в FLIBUSTA_DBPASSWORD_FILE не тот, что был при создании.

FATAL: directory /flibusta with books is not found — не смонтирован том с архивами. Директория должна существовать, даже пустая.

Контейнер стартует, но в логе Flibusta DB connection failed — то же, что предыдущее, но уже из PHP: пароль пользователя flibusta не совпадает. Соединение с базой открывается при первом обращении к ней, а не при старте, поэтому такая запись появляется не сразу после запуска контейнера, а при первом запросе, которому действительно нужна база; в браузере это выглядит как страница «Database temporarily unavailable».

Reverse proxy отдаёт 502 / 504

502 Bad Gateway — nginx не может достучаться до flibusta-fpm:9000. Reverse proxy и библиотека должны быть в общей сети flibusta_net; имя upstream в конфиге — flibusta-fpm (или что в container_name). После пересоздания контейнера библиотеки nginx иногда держит старый адрес — docker exec swag nginx -s reload.

504 Gateway Timeout на странице книги — запрос к базе не уложился в таймаут; библиотека сама отдаёт 504 с текстом «Не удалось получить данные книги». Бывает на слабом железе при очень широком поиске; повторите проще.

Страница открывается без стилей, читалки не работают

Статика (/bootstrap/…, /css/…, JS-читалки) отдаётся reverse proxy из тома flibusta_public_files, а не через PHP. Если её нет — том не смонтирован в reverse proxy, смонтирован не туда, куда смотрит root в конфиге, или называется иначе: Docker Compose добавляет к имени тома префикс проекта (flibusta-at-home_flibusta_public_files). Проверьте docker volume ls и docker inspect у контейнера прокси.

Если стили есть, а pdf не открывается (пустая рамка) — не передаётся заголовок Content-Security-Policy: worker-src * blob: на ответы PHP.

Вход «по кругу»: после правильного пароля снова форма входа

Cookie сессии помечена как Secure и не отправляется браузером по HTTP. Поэтому:

  • Вход по http:// не работает. Нужен HTTPS.
  • Вход по HTTPS через reverse proxy, но библиотека думает, что это HTTP — проверьте fastcgi_param HTTP_X_FORWARDED_PROTO в конфиге прокси. Признак этой же проблемы — красное предупреждение о HTTP в разделе «Пользователи».
  • Cookie выставляется на путь из FLIBUSTA_WEBROOT. Если библиотека доступна по /flibusta, а переменная пустая (или наоборот), cookie уходит не туда. Значение должно совпадать с location в прокси, со слэшем в начале и без слэша в конце.

«Сессия формы устарела. Обновите страницу» — не совпал CSRF-токен; чаще всего форма входа была открыта очень давно или в другой вкладке был сделан вход. Просто обновите страницу.

«Session has been terminated for security reasons» — в рамках одной сессии сменился User-Agent. Так бывает при переключении «версии для ПК» в мобильном браузере или при обновлении браузера. Войдите заново.

«Неправильное имя пользователя или пароль» при верном пароле — аккаунт или адрес заблокирован после серии ошибок (более 10 ошибок для имени или более 5 с одного адреса за 15 минут). Подождите 15 минут; посмотрите «Пользователи → Активность пользователей», кто стучался. Если это fail2ban забанил ваш адрес — fail2ban-client set flibusta unbanip <адрес>.

Доверенная сеть не работает (или работает для всех)

Библиотека сравнивает с FLIBUSTA_TRUSTED_NET значение REMOTE_ADDR, которое передаёт reverse proxy.

  • В логе контейнера строка FLIBUSTA_TRUSTED_NET value '…' is not a valid IPv4 address or CIDR subnet — опечатка в значении; допустим ровно один адрес или одна подсеть, без кавычек и пробелов.
  • Пускает без пароля вообще всех — REMOTE_ADDR содержит адрес прокси (например, 172.18.0.5), который попал в доверенную подсеть. Прокси должен передавать настоящий адрес клиента; при цепочке прокси нужен real_ip_header. Проверить, какой адрес видит библиотека, проще всего в «Пользователи → Сессии» (колонка «IP входа»).
  • Не пускает из дома — та же проверка: возможно, домашняя сеть не 192.168.1.0/24, а 192.168.0.0/24, или вы заходите через VPN/туннель, и адрес другой.

«Библиотека проходит техническое обслуживание»

Страница с кодом 503 показывается, пока удерживается блокировка обновления базы — во время «Обновить базу данных» или «Сканирование ZIP». Это штатно; страница сама обновляется каждые 30 секунд. Проверить, что операция действительно идёт: раздел «Сервис» (он доступен и в этом режиме) или

docker exec flibusta-fpm ps aux | grep -E 'app_import|app_reindex|update_zip'

Блокировка — flock; если процесса нет, блокировки тоже нет. «Зависшего» режима техобслуживания не существует; если 503 держится, а процессов нет — это reverse proxy кэширует ответ, или вы смотрите на другую установку.

Если импорт был прерван (перезагрузка хоста) — просто запустите «Обновить базу данных» ещё раз.

«Session store temporarily unavailable» и 503 на всех страницах

Это не техобслуживание, а недоступный Redis. Сообщение появляется, только если задана переменная FLIBUSTA_REDIS_HOST: библиотека намеренно не откатывается молча на сессии в Postgres, потому что сессии, разъехавшиеся по двум хранилищам, выглядели бы как случайные разлогинивания.

Проверьте по порядку:

docker ps | grep redis                       # контейнер вообще запущен?
docker exec flibusta-fpm php -r 'echo extension_loaded("redis") ? "ext ok\n" : "NO EXT\n";'
docker exec flibusta-fpm sh -c 'php -r "\$r=new Redis(); var_dump(\$r->connect(getenv(\"FLIBUSTA_REDIS_HOST\"), (int)(getenv(\"FLIBUSTA_REDIS_PORT\")?:6379), 1));"'

Частые причины: Redis и библиотека не в общей сети Docker; имя хоста в FLIBUSTA_REDIS_HOST не совпадает с именем контейнера; задан requirepass, а пароль библиотеке не передан.

Первая причина ловит чаще всего, и незаметно: если у сервиса библиотеки сети перечислены явно (flibusta_net, postgres_db_net), а у сервиса Redis секции networks нет вовсе, Redis попадает в сеть default, которую compose создаёт сам, — библиотеки там нет, и имя flibusta-redis просто не разрешается. Сети по умолчанию наследуют не все сервисы, а только те, у которых список не задан, так что добавьте Redis в flibusta_net явно. Точная причина будет в docker logs flibusta-fpm — там же строка о том, что Redis недоступен.

Отдельный случай — NOAUTH Authentication required. в логе рядом с session write failed, причём страницы при этом открываются (код 200, а не 503). Это значит, что Redis запущен с requirepass, соединение установилось, а библиотека пароль не отправила: подключение само по себе аутентификации не требует, и промах вылезает только на первой настоящей команде. Причина всегда в конфигурации библиотеки, а не Redis — проверьте, что у сервиса flibusta-fpm есть и переменная FLIBUSTA_REDIS_PASSWORD_FILE, и сам секрет в его секции secrets (объявить секрет только у сервиса Redis недостаточно), и что файл читается пользователем php-fpm:

docker exec flibusta-fpm env | grep -i redis
docker exec -u www-data flibusta-fpm sh -c 'wc -c < /run/secrets/FLIBUSTA_REDIS_PWD'

Начиная с версии, где это поведение исправлено, нечитаемый или пустой файл пароля даёт честную 503 и строку cannot read FLIBUSTA_REDIS_PASSWORD_FILE вместо потока NOAUTH.

Быстрый обходной путь, если Redis чинить некогда: уберите FLIBUSTA_REDIS_HOST и пересоздайте контейнер — библиотека вернётся к сессиям в Postgres. Читателям придётся войти заново. Подробнее — в статье о кэше.

Показываются старые данные книги после импорта

Кэш описаний книг (только в конфигурации с Redis) привязан к «поколению библиотеки», которое увеличивают импорт дампа и сканирование ZIP. Если каталог обновился, а на странице книги старая аннотация или старое название, значит счётчик не увеличился — как правило, потому что импорт завершился с ошибкой до последнего шага. Сбросить кэш вручную:

docker exec -u www-data flibusta-fpm php /tools/cache_bump.php

Команда безопасна, её можно выполнять когда угодно: она лишь помечает все закэшированные описания как устаревшие. Без Redis она ничего не делает.

Если же расходится не описание книги, а то, в каком архиве она лежит («книга не найдена» после добавления архивов), — это индекс архивов, см. следующий раздел.

Книга не открывается

«Книга не найдена» / файл недоступен при том, что книга есть в каталоге. Каталог строится по базе, а файлы — по индексу архивов. Варианты:

  • Не выполнено «Сканирование ZIP» после добавления архивов. Выполните.

  • Архив есть, но не проиндексирован: имя не по схеме (нужен дефис, .zip, подстрока fb2 для fb2-архивов) или нет прав на чтение для uid 82. Смотрите /cache/log/update_zip_list.log, таблицу book_zip и файл /cache/zip_index.php — именно из него библиотека берёт соответствие «книга → архив». Сканирование перестраивает и таблицу, и файл; если они разошлись (например, файл удалили руками), достаточно перезапустить контейнер или выполнить docker exec -u www-data flibusta-fpm php /tools/build_zip_index.php --force.

  • Диапазоны архивов не покрывают этот id (Got a gap в том же логе) — книги из разрыва отсутствуют физически; либо докачайте архив, либо включите скачивание на лету.

  • Архив повреждён: в логе контейнера book_open_source: cannot open archive …. Проверьте unzip -t <файл> и перекачайте.

  • Режим «на лету» включён, но в логе fetchMissingBook: failed to download … (HTTP <код>) — Флибуста недоступна с сервера, сменился домен или книга удалена. Проверьте доступность:

    docker exec flibusta-fpm curl -sI "$FLIBUSTA_URL" | head -1
    

Книга большая и предлагается только скачать. fb2 крупнее MAX_FB2_SIZE_2_DISPLAY (по умолчанию 100 МБ) в браузере не рендерится — намеренно.

Скачивание в epub/kfx/azw8 отдаёт ошибку. В логе контейнера будет fb2.php fbc failed for book … с выводом конвертера — как правило, это битый fb2 (невалидный XML). Скачайте fb2 как есть и конвертируйте локально, или сообщите об ошибке в проект.

Нет обложек

  • Не запускалась «Скачать обложки» — обложки берутся из архивов lib.b.attached.zip (книги) и lib.a.attached.zip (авторы) в /cache.
  • Обложка отсутствовала при прошлом обращении, и библиотека это запомнила: в /cache/covers/<id>.none ставится отметка, чтобы не искать снова. Отметка автоматически теряет силу, когда архив обложек обновится («Скачать обложки»), и удаляется кнопкой «Очистить кэш».
  • В логе extract_cover: cannot write miss marker … is /cache/covers/ writable? — права на /cache/covers, см. следующий раздел.
  • Для fb2 без обложки в архиве библиотека пытается вытащить обложку из самого файла; если её там нет — будет заглушка, это нормально.

Ошибки прав доступа: «Permission denied», операции молча не работают

Всё в /cache и /sql должно принадлежать uid 82. Обычные причины нарушения: файлы созданы docker exec без -u www-data, директории скопированы с другого хоста rsync без сохранения владельца, том NAS с принудительным владельцем. Лечение:

docker restart flibusta-fpm      # entrypoint делает chown -R www-data /cache /sql

или на хосте chown -R 82:82 /opt/flibusta/cache /opt/flibusta/sql. Для /flibusta достаточно права чтения; проверка изнутри контейнера:

docker exec -u www-data flibusta-fpm sh -c 'ls /flibusta | head; touch /cache/tmp/probe && echo cache OK'

Импорт дампа падает

Смотрите /cache/log/dbupdate.log. Частые причины:

  • Нет места в /sql: дампы распаковываются на месте, нужно несколько гигабайт сверх размера .gz.
  • Нет места в Postgres (том базы).
  • Сообщение gzip: /sql/*.gz: No such file or directory в начале — не ошибка: дампы уже были распакованы прошлым импортом.
  • Импорт прерван — запустите ещё раз, он идемпотентен.

Если дампы скачались не полностью («Скачать базу» прервалась), удалите битый .gz из /sql и файл с тем же именем из /cache/etag/, иначе библиотека решит, что версия актуальна, и не перекачает.

«Скачать последние обновления» ничего не скачивает

  • Перед скачиванием сравнивается ETag с сохранённым в /cache/etag/; local version of … remains current в выводе означает «уже есть». Чтобы принудительно перекачать файл, удалите его ETag-файл.
  • Флибуста недоступна с сервера — см. проверку curl выше. В России доступ к домену может быть заблокирован; варианты — другое зеркало в FLIBUSTA_URL или прокси через переменные https_proxy в environment.
  • Скрипт не смог взять блокировку (failed to obtain admin op lock) — идёт другая операция, подождите.

Загрузка файла в «Добавить» или torrent-файла не проходит

Лимит PHP — 500 МБ (upload_max_filesize) при post_max_size 508 МБ. Если ошибка «слишком велик» при файле меньше — упирается reverse proxy: client_max_body_size в nginx, лимит запроса у Cloudflare (100 МБ на бесплатном тарифе) и т.п.

Часы и время

Время операций в «Сервисе», лог попыток входа и cron живут в разных часовых поясах, если TZ контейнера не совпадает с хостом. Симптомы: fail2ban не банит (записи «из будущего»), отметки времени на странице «Сервис» отличаются от ожидаемых на несколько часов. Задайте TZ в environment равным часовому поясу хоста.

Если ничего не помогло

Соберите docker logs flibusta-fpm, лог reverse proxy, вывод последней операции из «Сервиса», версию образа (docker inspect flibusta-fpm | grep -i image) и опишите проблему в issues проекта на GitHub. Пароли и адреса из логов перед публикацией уберите.