---
title: "Продакшн"
description: "Reverse proxy и forwarded-заголовки, доверие к IP клиента, инвариант «один инстанс», регулярный бэкап встроенной командой."
---

# Продакшн

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

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

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

> [!warning] Самая частая ошибка деплоя
> 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-заголовков. См. [Конфигурация](/docs/self-hosting/configuration/).

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

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

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

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

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

> [!warning] Не пишите сюда «всех»
> Булевы значения, счётчики хопов, именованные диапазоны и всеадресные диапазоны (`/0`) отклоняются при старте. Доверие всем адресам означало бы, что любой клиент сам себе назначает IP заголовком и обходит лимит входа.

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

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

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

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

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

> [!note] Несколько инстансов за балансировщиком
> Оба состояния живут в памяти процесса, поэтому за балансировщиком с несколькими инстансами без общего хранилища эти механизмы не работают. [Вынос служебной БД в Postgres](/docs/self-hosting/database/) даёт общее состояние, но одного этого для горизонтального масштабирования недостаточно. Держите один инстанс.

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

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

```bash
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'а: [Бэкап и восстановление](/docs/self-hosting/backup/). Там же — восстановление в чистый том и границы применимости.

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

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

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

Если служебная БД вынесена в Postgres или заметки лежат вне корня данных, встроенная команда завершается ошибкой вместо частичного архива — бэкапьте базу и смонтированные каталоги штатными средствами провайдера. Что именно хранит служебная БД — на странице [База данных](/docs/self-hosting/database/).
