# 09 · Эксплуатация

## Ежедневное

| Что | Как |
|---|---|
| Жив ли сервис | `GET /api/health` (без входа, отдаёт версию и время) |
| Что происходило | панель → «Действия», либо `php backend/bin/fornex audit --limit=30` |
| Состояние зоны домена | `php backend/bin/fornex zone:show example.com` |
| Что видят получатели | `php backend/bin/fornex verify example.com` |

Мониторингу достаточно `/api/health`: ответ `{"ok":true,"status":"ok","version":"…","php":"8.5.x"}`
означает, что PHP отвечает, настройки прочитаны и приложение собралось.

## Журнал

`LOG_PATH` (по умолчанию `var/log/app.log`), ротация: 5 МБ на файл, хранится 5 файлов. В строке
есть `request_id`; он же попадает в запись журнала действий, поэтому «что видел человек» и «что
записано в базе» можно сопоставить.

Уровни: `debug`, `info` (по умолчанию), `warning`, `error`. `debug` на боевой установке не
включайте надолго — он пишет подробности запросов.

## Бэкап

| Что | Зачем |
|---|---|
| `fornex.env` | единственная копия ключа API и хэша пароля |
| `var/fornex.sqlite` | журнал, выпущенные токены, индекс снимков |
| `var/snapshots/` | снимки зон, по каталогу на домен |

Сама зона в бэкап не входит — она живёт в Fornex. Согласованную копию базы даёт:

```bash
sqlite3 var/fornex.sqlite "VACUUM INTO '/backup/fornex-$(date +%F).sqlite'"
```

Снимки полезно хранить дольше, чем журнал: именно из них восстанавливают зону, когда что-то
пошло не так.

## Обновление

```bash
cd /srv/fornex-control
git pull --ff-only
sudo -u www-data php tools/lint.php
sudo -u www-data php tests/plan_test.php
systemctl reload php8.5-fpm
```

Миграции применяются на первом запросе после обновления и только добавляют (`CREATE TABLE IF NOT
EXISTS`), поэтому старая база продолжает работать во время перезагрузки.

После обновления интерфейса поднимите `APP_VERSION`: ссылки на `app.js` и CSS содержат `?v=`,
именно это заставляет браузер взять новый файл, а не закешированный.

## Откат

1. `git checkout <предыдущий тег>` (или `git reset --hard <тег>` в рабочей копии, если своих
   правок нет).
2. `systemctl reload php8.5-fpm`.
3. Если схема базы ушла вперёд — вернуть копию из бэкапа; миграции этой версии только добавляют,
   поэтому обычно достаточно оставить базу как есть.
4. Зону при необходимости вернуть из снимка вручную: автоматического восстановления нет
   намеренно — это решение человека.

## Смена пароля и ключа

```bash
# пароль
php -r "echo password_hash('новый-пароль', PASSWORD_DEFAULT), PHP_EOL;"
# в fornex.env заменить ADMIN_PASSWORD_HASH, затем
systemctl reload php8.5-fpm
```

Ключ API меняется в кабинете Fornex: выпустить новый, вписать в `FORNEX_API_KEY`, перезагрузить
PHP-FPM, отозвать старый. Пока ключ не заменён, панель продолжает работать со старым.

## Переезд на другой сервер

1. Скопировать дерево, `fornex.env`, `var/` целиком.
2. Проверить права: приложение читает пользователь PHP, `var/` ему доступен на запись.
3. `php backend/bin/fornex help` — настройки и база на месте.
4. Переключить DNS/прокси, проверить `/api/health` и вход.
5. Убедиться, что старый экземпляр выключен: два экземпляра с одним ключом работают, но журнал и
   попытки входа окажутся разделены.

## Что делать, если панель недоступна

Зона от этого не страдает: она в Fornex. Пока панель лежит, записи правятся в кабинете, а после
подъёма `verify` покажет расхождение с ожидаемым. Поэтому панель не хранит «истину» у себя —
любая её копия зоны была бы вторым источником правды.

## Пределы, о которых стоит помнить

- Зона пересобирается минутами; проверка сразу после записи может показать старый ответ.
- `SOA` и `NS` не редактируются: это держит зону, и «быстрая правка» здесь дороже, чем кажется.
- Создание зоны через API на части аккаунтов запрещено (403) — это свойство аккаунта Fornex.
