Продакшн
Эта страница — о выводе инстанса в прод: как правильно поставить его за 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.dbcp /data/meta.db или копирование тома на ходу — не бэкап: служебная БД работает в режиме WAL, закоммиченные строки могут лежать в meta.db-wal, а файлы, скопированные по отдельности, не являются срезом на один момент времени.
Что именно попадает в бэкап и почему:
| Что | Роль |
|---|---|
/data/spaces | Ваши Markdown-файлы — источник истины. |
/data/meta.db | Служебная БД (история, пользователи, доступы) — невосстановимая из файлов. |
/data/jobs | Артефакты и загрузки задач импорта/экспорта. |
/data/engine | Производные индексы движка. В архив не входят: пересобираются из файлов. |
Если служебная БД вынесена в Postgres или заметки лежат вне корня данных, встроенная команда завершается ошибкой вместо частичного архива — бэкапьте базу и смонтированные каталоги штатными средствами провайдера. Что именно хранит служебная БД — на странице База данных.