Любой человек, всерьёз увлекающийся чтением, рано или поздно сталкивается с одной и той же проблемой. Книг становится много, форматы у них разные, на одном устройстве лежит epub, на другом mobi, на третьем pdf, и каждый раз приходится мучительно вспоминать, где именно осталась недочитанная глава. Облачные читалки решают вопрос лишь отчасти - они закрытые, привязывают к одному магазину, имеют свои ограничения по форматам и не дают полного контроля над собственной коллекцией. Хочется чего-то простого и собственного, что работает по принципу "положил книгу - и она доступна везде". Calibre именно такое решение и предлагает.
Сам по себе Calibre широко известен как настольная программа для управления электронными книгами на Linux, Windows и macOS. Эта часть проекта позволяет хранить локальную библиотеку, конвертировать между форматами, редактировать метаданные, синхронизироваться с устройствами вроде Kindle. Но у Calibre есть и серверная сторона, о которой знают далеко не все. Серверный компонент превращает обычный Linux-узел в персональную книжную полку, доступную с любого устройства через браузер.
С таким сервером открываются интересные возможности. Можно читать книги из любой точки мира, не таская с собой устройство с локальной копией. Можно быстро передавать книги на смартфон или планшет без проводов и кабелей. Можно делиться чтением с друзьями и родственниками, выдавая им логины и пароли. Можно читать прямо в браузере без установки дополнительного софта. Ниже разобран полный путь развёртывания такого сервера на Ubuntu 22.04 - от подготовки брандмауэра до подключения TLS-сертификата от Let's Encrypt.
Подготовительные требования и базовое окружение для развёртывания личной книжной полки
Чтобы пройти этот путь без сюрпризов, понадобится сервер на Ubuntu 22.04 - желательно свежий, без хвостов от предыдущих экспериментов. Доступ должен быть из-под обычного пользователя с правами sudo. Постоянная работа из-под root считается дурным тоном с давних времён, и для сетевых сервисов это особенно критично.
В системе должен быть включён и работать брандмауэр UFW (Uncomplicated Firewall) - стандартное средство фильтрации сетевого трафика на Ubuntu. Также нужно полное доменное имя (FQDN), направленное A-записью на IP сервера. Без домена не получится выпустить TLS-сертификат, а без шифрования передача учётных данных будет небезопасна. В этом руководстве используется условный домен calibre.example.com - его нужно заменить на свой реальный.
Обновляем пакеты до последних версий перед началом:
$ sudo apt update && sudo apt upgrade
Эта команда сначала обновляет индекс репозиториев, а затем устанавливает все доступные обновления. Привычка делать update перед серьёзными работами экономит часы будущих разбирательств с устаревшими версиями.
Открытие портов HTTP и HTTPS в брандмауэре UFW для веб-доступа к серверу
Любая публикация веб-сервиса начинается с открытия нужных портов. Calibre будет крутиться внутри сервера на порту 8080, но снаружи трафик пойдёт через стандартные 80 и 443, которые проксирует Nginx. Эти два порта и нужно открыть.
Проверяем текущее состояние брандмауэра:
$ sudo ufw status
Ожидаемый вывод:
Status: active
To
Action
From
--
------
----
OpenSSH
ALLOW
Anywhere
OpenSSH (v6)
ALLOW
Anywhere (v6)
Видно, что разрешён только SSH - это базовая настройка любого правильно сконфигурированного сервера. Если вместо active в выводе inactive, нужно сначала включить UFW через sudo ufw enable, не забыв предварительно разрешить SSH, иначе можно потерять удалённый доступ.
Открываем порты для веб-трафика:
$ sudo ufw allow http
$ sudo ufw allow https
Использование имён http и https вместо номеров портов 80 и 443 - синтаксический сахар UFW. Брандмауэр сам подставит нужные номера из своей встроенной таблицы соответствий. Это удобнее и понятнее в логах.
Проверяем результат:
$ sudo ufw status
Ожидаемый вывод:
Status: active
To
Action
From
--
------
----
OpenSSH
ALLOW
Anywhere
80/tcp
ALLOW
Anywhere
443/tcp
ALLOW
Anywhere
OpenSSH (v6)
ALLOW
Anywhere (v6)
80/tcp (v6)
ALLOW
Anywhere (v6)
443/tcp (v6)
ALLOW
Anywhere (v6)
В списке появились новые правила для HTTP и HTTPS трафика, причём как для IPv4, так и для IPv6. Брандмауэр готов пропускать веб-запросы.
Установка Calibre через официальный скрипт инсталлятора с подтягиванием свежей версии
Calibre присутствует в стандартном репозитории Ubuntu 22.04, но обычно там лежит относительно старая версия. Проект развивается активно, и каждая новая редакция приносит исправления багов и поддержку свежих форматов. Поэтому правильнее ставить через официальный скрипт инсталлятора с сайта проекта - так гарантированно получаешь самую актуальную сборку.
Сначала ставим зависимости, которые нужны для работы графических компонентов Calibre:
$ sudo apt install libopengl0 libxkbcommon-x11-0 libegl1 libfontconfig libgl1-mesa-glx
Странное наблюдение - зачем серверной версии графические библиотеки? Дело в том, что Calibre изначально создавался как настольное приложение, и его инсталлятор тянет за собой полный набор зависимостей вне зависимости от того, нужен GUI или нет. Без этих пакетов скрипт установки будет ругаться, хотя сам сервер потом работает в чисто консольном режиме. Это не самый изящный момент архитектуры, но мириться с ним приходится.
Скачиваем скрипт инсталлятора:
$ wget https://download.calibre-ebook.com/linux-installer.sh
Делаем его исполняемым:
$ chmod +x ./linux-installer.sh
Запускаем установку:
$ sudo ./linux-installer.sh
В процессе появятся предупреждения про отсутствие графического окружения - это нормально, инсталлятор всегда ругается на серверах. Сообщения можно спокойно игнорировать. Скрипт скачает последнюю версию Calibre, разместит файлы в /opt/calibre и создаст все нужные ссылки на бинарники.
Создание первой библиотеки и добавление пробной книги через утилиту calibredb
После установки нужно создать саму библиотеку - каталог, в котором будут жить книги вместе с метаданными и эскизами обложек. Для пробы возьмём книгу "Приключения Шерлока Холмса" Артура Конан Дойля из Project Gutenberg - бесплатной электронной библиотеки общественного достояния:
$ wget http://www.gutenberg.org/ebooks/1661.kindle.noimages -O adventuresofsherlockholmes.mobi
Файл сохраняется с понятным именем adventuresofsherlockholmes.mobi. На сайте проекта Гутенберг ссылки имеют технические имена вроде 1661.kindle.noimages, поэтому имеет смысл переименовывать при скачивании через флаг -O. Версия в формате Kindle (mobi) предпочтительнее по двум причинам - она нативно поддерживается читалками от Amazon и обычно имеет более качественную типографику, чем epub-варианты.
Создаём каталог для библиотеки:
$ mkdir calibre-library
Добавляем книгу в библиотеку через утилиту calibredb:
$ calibredb add adventuresofsherlockholmes.mobi --with-library calibre-library/
Параметр --with-library указывает путь к каталогу библиотеки. Без него calibredb попытается работать с библиотекой по умолчанию, которая ещё не существует. После выполнения команда выведет:
Added book ids: 1
Идентификатор 1 означает, что это первая книга в новой библиотеке. Дальше идентификаторы будут расти.
Если книг сразу несколько, можно добавлять их все одной командой через wildcard:
$ calibredb add *.mobi --with-library calibre-library/
Утилита переберёт все mobi-файлы в текущем каталоге и добавит их в библиотеку, проставив автоматически вытянутые из метаданных названия и авторов. Это удобнее, чем добавлять по одной, особенно если в коллекции десятки или сотни книг.
Запуск сервера Calibre и проверка веб-интерфейса в браузере
Книги готовы, пора запустить сервер:
$ calibre-server calibre-library
Команда calibre-server принимает путь к библиотеке как аргумент. После старта выводится подобное сообщение:
calibre server listening on 0.0.0.0:8080
OPDS feeds advertised via BonJour at: your_server_ip port: 8080
Адрес 0.0.0.0:8080 означает, что сервер слушает все сетевые интерфейсы на восьмом тысяче восьмидесятом порту. OPDS - это специальный протокол для каталогов электронных книг, который понимают многие читалки и приложения для управления библиотеками. BonJour - механизм автоматического обнаружения сервисов в локальной сети, удобно для быстрого подключения с домашних устройств.
Чтобы посмотреть на сервер из браузера, нужно временно открыть порт 8080:
$ sudo ufw allow 8080
Открываем браузер и переходим на http://<yourserverIP>:8080/. Появится приветственная страница Calibre с тёмной или светлой темой в зависимости от системных настроек. Кликаем на ссылку calibre-library и видим добавленную ранее книгу с обложкой и метаданными. Можно прямо в браузере перелистывать страницы, выбирать формат для скачивания, читать в браузере онлайн.
Останавливаем сервер через Ctrl + C в терминале.
Если стандартный порт 8080 чем-то не устраивает (занят другим сервисом, конфликтует с корпоративными политиками), можно запустить Calibre на любом другом:
$ calibre-server calibre-library --port 7654
Не забыть открыть выбранный порт в брандмауэре, иначе соединение не пройдёт.
Создание systemd юнита для автоматического запуска и устойчивой работы сервера
Запуск из терминала через calibre-server удобен для тестов, но в боевой эксплуатации не годится. Стоит закрыть SSH-сессию или перезагрузиться - и сервер пропадёт. Решение классическое - оформить запуск через systemd, чтобы служба поднималась автоматически при загрузке и перезапускалась при сбоях.
Создаём юнит-файл:
$ sudo nano /etc/systemd/system/calibre-server.service
Содержимое:
[Unit]
Description=Calibre Server
After=network.target
[Service]
Type=simple
User=<username>
Group=<username>
ExecStart=/opt/calibre/calibre-server /home/<username>/calibre-library --enable-local-write
[Install]
WantedBy=multi-user.target
Параметр --enable-local-write даёт серверу права на запись в библиотеку. Это важная тонкость - без этого флага нельзя добавлять новые книги через calibredb, пока сервер запущен. С флагом всё работает корректно одновременно.
Заменяем <username> на имя своего системного пользователя по всему файлу. Например, если пользователь зовётся reader, везде должно стоять reader. Сохраняем файл через Ctrl + W (или Ctrl + X в зависимости от версии nano) и подтверждаем Y.
Перечитываем конфигурацию systemd:
$ sudo systemctl daemon-reload
Эта команда обязательна после любых изменений в юнит-файлах. Без неё systemd работает по старому кешированному набору, и новые правки игнорируются.
Включаем автозапуск и стартуем службу:
$ sudo systemctl enable calibre-server
$ sudo systemctl start calibre-server
Первая команда прописывает запуск при загрузке системы, вторая поднимает сервис прямо сейчас.
Проверяем статус:
$ sudo systemctl status calibre-server
Ожидаемый вывод:
? calibre-server.service - Calibre Server
Loaded: loaded (/etc/systemd/system/calibre-server.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2022-07-25 07:23:42 UTC; 15s ago
Main PID: 1877 (BonJour)
Tasks: 13 (limit: 2241)
Memory: 53.3M
CPU: 762ms
CGroup: /system.slice/calibre-server.service
??1877 /opt/calibre/bin/calibre-server /home/<username>/calibre-library --enable-local-write
Jul 25 07:23:42 calibre systemd[1]: Started Calibre Server.
Jul 25 07:23:42 calibre calibre-server[1877]: QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-<username>'
Jul 25 07:23:42 calibre calibre-server[1877]: calibre server listening on 0.0.0.0:8080
Jul 25 07:23:43 calibre calibre-server[1877]: OPDS feeds advertised via BonJour at: 69.28.84.201 port: 8080
Строка active (running) означает, что всё работает. Предупреждение про XDG_RUNTIME_DIR можно игнорировать - это последствие отсутствия графической сессии и на функциональность не влияет.
Защита библиотеки через включение базовой аутентификации с собственной учётной записью
По умолчанию доступ к Calibre открыт всем, кто знает адрес сервера. Для домашней сети это может быть приемлемо, но публиковать такую конфигурацию в интернет - всё равно что вешать ключи от квартиры на дверь. Надо включать защиту по логину и паролю.
Останавливаем сервер для внесения изменений:
$ sudo systemctl stop calibre-server
Calibre хранит учётные записи в SQLite-базе. Запускаем встроенный скрипт управления пользователями:
$ sudo calibre-server --manage-users
Появится меню с четырьмя опциями. Нажимаем 1 для добавления нового пользователя:
1) Add a new user
2) Edit an existing user
3) Remove a user
4) Cancel
What do you want to do? [1-4]: (Press 1)
Enter the username: howtoforge
Enter the new password for howtoforge:
Re-enter the new password for howtoforge, to verify:
User howtoforge added successfully!
Вводим имя пользователя (в примере оставлено howtoforge как условное имя) и пароль. Calibre проверит совпадение пароля при повторном вводе и сообщит об успешном добавлении.
Дальше нужно сказать сервису, что он должен требовать аутентификацию. Открываем юнит-файл:
$ sudo nano /etc/systemd/system/calibre-server.service
Добавляем флаг --enable-auth в конец строки ExecStart:
...
ExecStart=/opt/calibre/calibre-server "/home/<username>/calibre-library" --userdb "/home/<username>/.config/calibre/server-users.sqlite" --enable-local-write --enable-auth
...
В этой строке появилось два новых параметра. Первый - --userdb с путём к базе пользователей, которую Calibre создал на предыдущем шаге. Второй - сам --enable-auth, включающий проверку учётных данных. Без обоих параметров аутентификация работать не будет - один указывает где хранятся пароли, другой включает их использование.
Сохраняем файл, перечитываем systemd и запускаем сервис:
$ sudo systemctl daemon-reload
$ sudo systemctl start calibre-server
Открываем библиотеку в браузере - теперь вместо немедленного отображения каталога появится диалог авторизации. Вводим логин и пароль, попадаем внутрь. Всё, защита установлена.
Автоматическое добавление новых книг через cron-задачу с отслеживанием отдельной директории
Ручное добавление книг через calibredb работает, но при больших объёмах и регулярных пополнениях коллекции становится утомительным. Удобнее настроить автоматизацию - создать отдельный каталог-приёмник, куда просто кидаются новые книги, а скрипт по расписанию забирает их в библиотеку. Это самый быстрый способ держать коллекцию свежей: загрузил файл - и через несколько минут он уже в библиотеке.
Создаём каталог отслеживания:
$ mkdir ~/calibre-watch
$ cd ~/calibre-watch
Скачаем туда для примера "Войну и мир" Льва Толстого с того же Project Gutenberg:
$ wget https://www.gutenberg.org/ebooks/2600.kindle.images -O warandpeace.mobi
На этот раз берётся версия с картинками - на Project Gutenberg для разных книг доступны разные варианты. Calibre корректно обрабатывает обе вариации, так что выбор зависит от личных предпочтений.
Открываем редактор cron:
$ crontab -e
При первом запуске crontab спросит, какой редактор использовать:
no crontab for <username> - using an empty one
Select an editor.
To change later, run 'select-editor'.
1. /bin/nano
<---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
Нажимаем 1 для выбора nano - он самый простой и понятный. Открывается редактор с пустым crontab. Добавляем строку в конец файла:
*/5 * * * * calibredb add /home/<username>/calibre-watch/ -r --with-library http://localhost:8080#calibre-library --username mycalibreuser --password StrongPassword! && rm -r /home/<username>/calibre-watch/*
Эта длинная строка делает следующее. Конструкция */5 * * * * означает запуск каждые 5 минут (можно поменять на любой удобный интервал, например 0 * * * * для часового запуска). Команда calibredb add с параметром -r рекурсивно добавляет все файлы из указанного каталога. Параметр --with-library с URL означает работу через сетевой интерфейс сервера, а не напрямую с файлами библиотеки - это важно, поскольку сервер уже запущен и держит блокировки. Параметры --username и --password передают учётные данные для аутентификации. Конструкция через && после успешного добавления удаляет исходные файлы из watch-каталога, чтобы они не добавлялись повторно при следующем запуске.
Заменяем <username> на своё имя пользователя, mycalibreuser и StrongPassword! на свои реальные учётные данные Calibre. Сохраняем файл.
Через пять минут любой загруженный в /home/<username>/calibre-watch файл автоматически появится в библиотеке. Это удобно для интеграций - можно настроить downloader из RSS-ленты, поставить ScP-скрипт на смартфоне, прикрутить веб-форму загрузки.
Установка свежей версии Nginx через официальный репозиторий разработчиков
В стандартном репозитории Ubuntu 22.04 живёт относительно старая версия Nginx. Для современной конфигурации с TLS 1.3 и HTTP/2 хочется иметь свежую сборку. Подключаем официальный репозиторий nginx.org.
Импортируем подписной ключ Nginx:
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Команда выглядит замысловато, но логика прозрачная. Сначала curl скачивает ключ, потом gpg --dearmor преобразует его в бинарный формат, потом sudo tee сохраняет в стандартное место для ключей репозиториев. Перенаправление в /dev/null нужно, чтобы tee не дублировала вывод на экран.
Добавляем репозиторий стабильной ветки:
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
Параметр signed-by привязывает репозиторий к ранее установленному ключу - это часть современной модели безопасности apt. Конструкция lsb_release -cs подставляет кодовое имя текущего релиза Ubuntu (jammy для 22.04), что позволяет одной и той же команде работать на разных версиях системы.
Обновляем индекс и ставим Nginx:
$ sudo apt update
$ sudo apt install nginx
Проверяем результат:
$ nginx -v
nginx version: nginx/1.22.0
Версия 1.22 - последний стабильный релиз на момент написания оригинала. Все современные возможности TLS и HTTP/2 поддерживаются.
Получение TLS-сертификата от Let's Encrypt и настройка автоматического продления
Без шифрования передавать пароли по сети - значит делать подарок любому, кто способен прослушать трафик. Решение - сертификат от Let's Encrypt, бесплатной службы сертификации. Ставим Certbot через snap, поскольку snap-версия обновляется чаще и стабильнее.
Ubuntu 22.04 поставляется со Snapd по умолчанию. Обновляем основные компоненты:
$ sudo snap install core
Ставим сам Certbot:
$ sudo snap install --classic certbot
Параметр --classic разрешает snap-пакету выходить за пределы своего изолированного окружения. Для Certbot это нужно, поскольку он работает с системными файлами в /etc/letsencrypt и веб-сервером.
Создаём симлинк, чтобы команда certbot была доступна из обычного PATH:
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Получаем сертификат:
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. -d calibre.example.com
Разберём флаги. Параметр certonly получает только сертификат без автоматической настройки веб-сервера. --standalone запускает временный встроенный веб-сервер для прохождения проверки. --agree-tos автоматически принимает условия использования. --no-eff-email отказывается от рассылки EFF. --staple-ocsp включает OCSP stapling для ускорения проверки сертификата. --preferred-challenges http выбирает HTTP-метод проверки. Параметр -m задаёт email для уведомлений, -d указывает домен.
Поскольку используется standalone-режим, на момент получения сертификата 80-й порт должен быть свободен. На текущем этапе Nginx ещё не запущен, поэтому проблем не будет.
Генерируем параметры Diffie-Hellman:
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Параметр -dsaparam ускоряет генерацию для DH-параметров, а размер 4096 бит обеспечивает надёжную криптостойкость. Без флага -dsaparam команда работала бы значительно дольше - иногда десятки минут.
Открываем конфигурацию автообновления сертификата:
$ sudo nano /etc/letsencrypt/renewal/calibre.example.com.conf
Добавляем в конец файла хуки до и после обновления:
pre_hook = systemctl stop nginx
post_hook = systemctl start nginx
Сертификаты Let's Encrypt действуют 90 дней, и обновление происходит через тот же standalone-режим, который требует свободного 80-го порта. Хук pre_hook остановит Nginx перед обновлением, post_hook запустит его обратно. Без этих хуков обновление будет проваливаться, и через три месяца сертификат просто перестанет действовать.
Проверяем работу обновления через сухой запуск:
$ sudo certbot renew --dry-run
Если ошибок нет, всё в порядке. Сертификат будет автоматически продлеваться задолго до истечения срока.
Создание конфигурации виртуального хоста Nginx с проксированием Calibre и поддержкой современных протоколов TLS
Открываем главный конфиг Nginx:
$ sudo nano /etc/nginx/nginx.conf
Перед строкой include /etc/nginx/conf.d/*.conf; добавляем:
server_names_hash_bucket_size
64;
Этот параметр увеличивает размер хеш-таблицы для хранения имён виртуальных хостов. Без него Nginx может ругнуться при загрузке конфига с длинным доменным именем. Сохраняем файл.
Создаём конфиг для нашего сайта:
$ sudo nano /etc/nginx/conf.d/calibre.conf
Содержимое:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
http2_push_preload on; # Enable HTTP/2 Server Push
# Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
# prevent replay attacks.
#
# @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
ssl_early_data on;
server_name calibre.example.com;
client_max_body_size 50M;
access_log
/var/log/nginx/calibre.access.log;
error_log
/var/log/nginx/calibre.error.log;
ssl_certificate
/etc/letsencrypt/live/calibre.example.com/fullchain.pem;
ssl_certificate_key
/etc/letsencrypt/live/calibre.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/calibre.example.com/chain.pem;
ssl_session_timeout
5m;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# enforce HTTPS
server {
listen 80;
listen [::]:80;
server_name
calibre.example.com;
return 301
https://$host$request_uri;
}
Эта конфигурация заслуживает разбора по частям. Первый блок server отвечает за основной HTTPS-трафик. Параметр listen 443 ssl http2 включает SSL и HTTP/2 - современный протокол, который заметно быстрее HTTP/1.1 за счёт мультиплексирования.
Параметр http2_push_preload on активирует server push - механизм, при котором сервер сам отправляет клиенту ресурсы, которые тот скоро запросит. Опция ssl_early_data on включает поддержку 0-RTT TLS 1.3 - это сокращает задержку при повторных подключениях, что особенно ощутимо на мобильных устройствах с нестабильной сетью.
Параметр client_max_body_size 50M разрешает загрузку файлов до 50 мегабайт - этого достаточно для большинства электронных книг, но при необходимости можно увеличить (например, для скан-копий учебников или альбомов с иллюстрациями).
Блок ssl_* параметров - это набор настроек криптографии. Указаны пути к сертификату и ключу, включены OCSP stapling и кеширование сессий, отключены небезопасные TLS 1.0 и 1.1. Список ssl_ciphers содержит только сильные шифры с прямой секретностью. Параметр ssl_ecdh_curve перечисляет современные эллиптические кривые для ключевого обмена в порядке предпочтения.
Блок location / реализует основное проксирование. Все запросы передаются на 127.0.0.1:8080 - это адрес внутреннего Calibre. Заголовки X-Real-IP и X-Forwarded-For передают исходный IP клиента в Calibre - без них в логах сервиса все запросы выглядели бы как идущие с localhost. Заголовок X-Forwarded-Proto сообщает Calibre, что исходный запрос пришёл по HTTPS, что важно для правильной генерации внутренних ссылок.
Второй блок server слушает 80-й порт и делает безусловный редирект на HTTPS через return 301. Любая попытка зайти по обычному HTTP автоматически перенаправляется на защищённую версию.
Сохраняем файл и проверяем синтаксис:
$ sudo nginx -t
Если ошибок нет, перезапускаем Nginx:
$ sudo systemctl restart nginx
Открываем https://calibre.example.com в браузере - после прохождения базовой авторизации Calibre появляется библиотека со всеми книгами, включая добавленные через cron.
Распространённые подводные камни и практические наблюдения из реальной эксплуатации
В копилку наблюдений из практики стоит добавить несколько моментов, на которых обжигаются те, кто впервые поднимает Calibre Server в боевом окружении.
Первая частая проблема - производительность при больших библиотеках. Calibre великолепно справляется с тысячами книг, но когда коллекция переваливает за десятки тысяч, начинаются заметные задержки при поиске и фильтрации. Лекарство - регулярно запускать calibredb check_library и при необходимости перестраивать индексы через интерфейс. Также имеет смысл хранить базу на SSD-диске, поскольку случайные обращения при поиске метаданных создают много iops.
Вторая популярная грабля связана с правами на каталог watch. Если cron работает от одного пользователя, а файлы в watch-каталог падают от другого (например, через scp с учёткой с другого имени), скрипт может не суметь их удалить, и при следующем запуске они добавятся ещё раз. Получаются дубликаты в библиотеке. Лекарство - либо строго выдерживать единого пользователя для всех источников, либо добавить в crontab логику проверки и обработки ошибок.
Третий момент касается конвертации форматов. Calibre умеет конвертировать книги из одного формата в другой через ebook-convert, и это можно встроить в автоматизацию. Например, при добавлении epub автоматически генерировать mobi для пользователей Kindle. Получается универсальная библиотека, которая отдаёт книгу в нужном формате под конкретное устройство без ручной возни.
Четвёртая тонкость - резервное копирование. Бэкапить нужно сразу две вещи - сам каталог библиотеки (там лежат файлы книг плюс metadata.db с индексом) и каталог .config/calibre с учётными записями пользователей. Без второго при восстановлении придётся пересоздавать всех пользователей, что неудобно при большом числе родственников и друзей с доступом.
Пятый момент - доступ через OPDS. Многие читалки и приложения для электронных книг (Moon+ Reader, KOReader, Foliate, FBReader) умеют подключаться к серверам по протоколу OPDS, что даёт удобный интерфейс прямо на устройстве, без необходимости лезть в браузер. URL для OPDS обычно имеет вид https://calibre.example.com/opds, и его можно сразу прописать в настройках читалки.
Где такая инсталляция пригодится в реальной жизни? Сценариев масса. Личная библиотека для семьи, доступная с любых устройств без облачных сервисов. Корпоративная коллекция технических книг и руководств для команды разработчиков. Библиотека учебных материалов в школе или университете. Архив профессиональной литературы для медиков, юристов, инженеров. Полки специализированной литературы для клубов по интересам - от любителей фантастики до собирателей кулинарных рецептов.
Освоение Calibre Server даёт инженеру не просто навык настройки одного приложения, а целый набор практик работы с веб-сервисами. Связка systemd-юнита, обратного прокси Nginx, TLS-сертификата от Let's Encrypt и cron-автоматизации - это базовый набор для развёртывания практически любого самохостимого проекта. Тот, кто разобрался с Calibre, без труда поднимет Bookstack, Wallabag, Kavita, Komga и другие подобные платформы - принципы у них одинаковые, отличия только в специфике конкретного приложения. Этот сценарий стоит реализовать хотя бы один раз, чтобы перестать зависеть от облачных сервисов в той области, где приватность важнее всего - в собственной коллекции книг и материалов для чтения.