NotariumДокументация
Версия документации: latest
RU

Продакшн

Эта страница — о выводе инстанса в прод: как правильно поставить его за reverse proxy, что означает инвариант «один инстанс» и как делать бэкап. Notarium разворачивается одним контейнером — прод-конфигурация сводится к трём вещам ниже.

Reverse proxy и forwarded-заголовки

Перед приложением ставят reverse proxy (nginx, Caddy, Traefik) — он терминирует TLS и проксирует на порт Notarium. Ключевое требование: прокси обязан пробрасывать заголовки о внешнем адресе.

Самая частая ошибка деплоя

Reverse proxy должен слать X-Forwarded-Host (или не переписывать Host) и X-Forwarded-Proto: https. Иначе cookie-аутентифицированные мутации из интерфейса отклоняются как cross-origin — получается симптом «вижу, но не могу сохранить». Проброс X-Forwarded-Proto также нужен, чтобы сессионная cookie получила флаг Secure.

Почему так: Origin-проверка на мутациях сверяет источник запроса с адресом, который видит браузер, — а этот адрес приходит в forwarded-заголовке. Вызовы агентов по Bearer-PAT от проверки освобождены (у них нет cookie — нет и CSRF-поверхности). Прокси при этом обязан перезаписывать forwarded-заголовки своими значениями, а не пропускать клиентские насквозь.

Если вы включаете OAuth-авторизацию агентов, задайте за прокси PUBLIC_BASE_URL (например, https://notes.example.com) — стабильный внешний адрес для OAuth-метаданных. Без него адрес выводится из forwarded-заголовков. См. Конфигурация.

Доверие к IP клиента

Отдельная от адреса ось — настоящий IP клиента. По нему считаются два лимита: попытки входа и допуск новых OAuth-клиентов. За прокси все запросы приходят с одного адреса, поэтому без явной настройки эти лимиты считались бы «на прокси», то есть на всех сразу.

Ручка — TRUST_PROXY: список IP/CIDR непосредственных прокси через запятую.

# .env — подставьте адрес своего прокси-контейнера или хоста
TRUST_PROXY=172.18.0.0/16

Безопасный дефолт — переменная не задана: тогда X-Forwarded-For вообще не влияет на лимиты, и подделать чужой IP заголовком невозможно. Задавайте её, только когда точно знаете адрес своего прокси, и держите список узким.

Не пишите сюда «всех»

Булевы значения, счётчики хопов, именованные диапазоны и всеадресные диапазоны (/0) отклоняются при старте. Доверие всем адресам означало бы, что любой клиент сам себе назначает IP заголовком и обходит лимит входа.

На проброс X-Forwarded-Host и X-Forwarded-Proto эта настройка не влияет — это независимые оси, и контракт из предыдущего раздела остаётся прежним.

Инвариант «один инстанс»

Notarium рассчитан на один процесс. Два состояния аутентификации живут в памяти процесса:

  • rate-limit логина — счётчики попыток;
  • реестр SSE-сокетов — через него отзыв доступа мгновенно рвёт живые соединения.

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

Несколько инстансов за балансировщиком

Оба состояния живут в памяти процесса, поэтому за балансировщиком с несколькими инстансами без общего хранилища эти механизмы не работают. Вынос служебной БД в Postgres даёт общее состояние, но одного этого для горизонтального масштабирования недостаточно. Держите один инстанс.

Резервное копирование

Каноничный бэкап — встроенная команда образа, а не копирование файлов снаружи: notarium backup собирает проверенный ZIP и отдаёт его потоком, пока сервис продолжает работать.

docker compose exec -T notarium backup > notarium-$(date -u +%Y%m%dT%H%M%SZ).zip
docker compose exec -T notarium backup verify < notarium-20260731.zip

Проверка — обязательная часть регулярной джобы, а не разовый жест: она ничего не меняет и ловит порчу до того, как архив вам понадобится. Для самой джобы простого перенаправления мало — возьмите безопасную публикацию (временный файл → сброс на диск → атомарная жёсткая ссылка) из runbook'а: Бэкап и восстановление. Там же — восстановление в чистый том и границы применимости.

Не копируйте живой meta.db

cp /data/meta.db или копирование тома на ходу — не бэкап: служебная БД работает в режиме WAL, закоммиченные строки могут лежать в meta.db-wal, а файлы, скопированные по отдельности, не являются срезом на один момент времени.

Что именно попадает в бэкап и почему:

ЧтоРоль
/data/spacesВаши Markdown-файлы — источник истины.
/data/meta.dbСлужебная БД (история, пользователи, доступы) — невосстановимая из файлов.
/data/jobsАртефакты и загрузки задач импорта/экспорта.
/data/engineПроизводные индексы движка. В архив не входят: пересобираются из файлов.

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