# RUNBOOK — разворачивание мирткани.рф на свежей CentOS Stream 9

Пошаговая инструкция для ИИ-агента (Claude Code). Цель: на чисто переустановленной
**CentOS Stream 9** воспроизвести стек 1-в-1 по архитектуре и поднять боевой сайт
мирткани.рф из бэкапа.

> Прочитай сначала `ARCHITECTURE.md` — там схема и все пути. Скрипты лежат в `restore/`,
> запускаются строго по номерам. Каждый 🔴 GATE — остановись и проверь, прежде чем идти дальше.

## Предусловия
- ОС: CentOS Stream 9, доступ root (`sudo -i`).
- Пакет миграции залит обратно в **`/opt/migration-backup-server/`** (как был).
- В `backups/` лежит `files-*.tar.gz`. Дамп БД `db-*.sql.gz` появится на этапе переноса данных (может прийти позже файлов).
- SSL — **wildcard через Cloudflare DNS-01**. Выпуск не зависит от IP/порта 80 (проверка идёт по DNS-записи в Cloudflare), поэтому работает даже на свежем сервере до старта nginx и при смене IP. Токен Cloudflare уже в пакете.

## Порядок (скрипты в `restore/`)
```
00-preflight → 10-repos → 20-packages → 30-files → 35-ssl → 40-configs
   → [данные] 50-database → 70-selinux → 80-firewall → 90-services → 99-verify
```
Все скрипты идемпотентны и подключают `restore/env.sh` (пути/имя БД/домен — там).

---

### Шаг 0 — Предполётная проверка ✅
```bash
cd /opt/migration-backup-server/restore
sudo bash 00-preflight.sh
```
Проверит: el9, наличие и целостность архивов, sha256, сеть, диск.
🔴 **GATE 0:** «files-tar gzip OK». Если дампа БД ещё нет — это нормально, продолжаем без него.

### Шаг 1 — Репозитории ✅
```bash
sudo bash 10-repos.sh
```
Подключит EPEL+CRB, remi (php82), nginx (офиц. el9), MariaDB 10.11.
🔴 **GATE 1:** `dnf makecache` без ошибок репозиториев.

### Шаг 2 — Установка пакетов ✅
```bash
sudo bash 20-packages.sh
```
nginx + httpd + php82-* (тот же набор расширений) + MariaDB 10.11 + certbot + firewalld.
🔴 **GATE 2:** в конце печатаются версии — nginx/httpd/php 8.2.x/MariaDB 10.11.

### Шаг 3 — Файлы сайта 🔴
```bash
sudo bash 30-files.sh
```
Распакует `files-*.tar.gz` → `/var/www/mirtkani.rf`, восстановит каталоги кэша, выставит владельца `apache:apache`.
🔴 **GATE 3:** есть `dbconn.php`, `.settings.php`, печатается `SM_VERSION 26.250.100`.

### Шаг 3.5 — SSL: wildcard через Cloudflare DNS-01 🔴 (ДО конфигов!)
```bash
sudo bash 35-ssl.sh
```
Положит Cloudflare-токен в `/root/.secrets/cloudflare.ini`, восстановит `/etc/letsencrypt`
(аккаунт + старый cert как fallback) и **выпустит wildcard** `*.xn--80apbgijsq.xn--p1ai` (+ apex)
через DNS-01. Один сертификат покрывает ВСЕ региональные поддомены. Метод renew автоматически
становится `dns-cloudflare`. Запускать ДО `40-configs`, т.к. `nginx -t` требует наличия cert.
🔴 **GATE 3.5:** в выводе виден `DNS:*.xn--80apbgijsq.xn--p1ai` (wildcard) и есть
`/etc/letsencrypt/live/xn--80apbgijsq.xn--p1ai/fullchain.pem`.

> DNS-01 не требует поднятого веб-сервера/порта 80 → cert выпускается ещё до старта nginx.
> Токен Cloudflare уже в пакете (`configs/cloudflare/cloudflare.ini`), проверен боевыми запросами.

### Шаг 4 — Конфиги стека 🔴
```bash
sudo bash 40-configs.sh
```
Разложит nginx (+ bx/, ssl/), Apache (httpd.conf + bx/ + php.conf, БЕЗ ssl.conf), php-fpm (99-bitrix.ini + www.conf), MariaDB-тюнинг. Создаст `/var/lib/php/session`.
Внутри проверяет `nginx -t` и `httpd -t`.
🔴 **GATE 4:** «nginx -t OK» и «httpd -t OK». Если httpd ругается на модуль — см. раздел «Если что-то не так».

### Шаг 5 — База данных 🔴 (НА ЭТАПЕ ПЕРЕНОСА ДАННЫХ)
Выполняется, когда `db-*.sql.gz` уже в `backups/` (дамп снимается на источнике в момент переезда, чтобы данные были свежими).
```bash
sudo bash 50-database.sh
```
Поднимет MariaDB, создаст `db_mt_new` + пользователя (реквизиты читаются из `dbconn.php`, пароль не печатается), импортирует дамп.
🔴 **GATE 5:** «таблиц в db_mt_new: N» (N — сотни). 

> Дамп на источнике снимается так (пароль не печатать):
> ```bash
> DBP=$(sudo grep -oP "DBPassword\s*=\s*[\"']\K[^\"']+" /var/www/mirtkani.rf/bitrix/php_interface/dbconn.php)
> mysqldump --single-transaction --quick --routines --triggers --default-character-set=utf8 \
>   -u <DBLogin> -p"$DBP" db_mt_new | gzip > db-db_mt_new-$(date +%Y%m%d_%H%M%S).sql.gz
> unset DBP
> ```

### Шаг 7 — SELinux 🔴 (специфика el9!)
```bash
sudo bash 70-selinux.sh
```
Булевы + метки портов 8888/8887/9082 + контекст docroot + restorecon.
🔴 **GATE 7:** скрипт без ошибок. (Без этого шага сайт отдаст 502/503.)

### Шаг 8 — Firewall ✅
```bash
sudo bash 80-firewall.sh
```
Восстановит зону public (80/443/21/ssh + drop 45.227.253.15).

### Шаг 9 — Сервисы + cron + кэш 🔴
```bash
sudo bash 90-services.sh
```
Запустит mariadb/php-fpm/httpd/nginx, поставит cron (SSL renew + обновление товаров), очистит кэш Битрикса.
🔴 **GATE 9:** все 4 сервиса `active`.

### Шаг 10 — Приёмка ✅
```bash
sudo bash 99-verify.sh
```
Порты, версии, HTTP 200 + `X-Powered-By: PHP/8.2`, smoke по страницам, число таблиц БД.
Дальше — пройти `CHECKLIST.md` (ручной e-commerce поток).

---

## Если что-то не так
- **502/503 от nginx, в логе nginx «connect() failed (13: Permission denied)»** → SELinux. Перепроверь шаг 7; временно `setenforce 0`, добейся работы, потом верни enforcing с правильными правилами (`audit2allow`).
- **httpd не стартует, «Invalid command 'SSLEngine'»** → где-то остался ssl.conf с mod_ssl. Удали `/etc/httpd/conf.d/ssl.conf` (TLS на nginx).
- **httpd «Cannot load modules/...»** → не переноси el7-`conf.modules.d`; используй стоковый el9. Нужны модули: proxy, proxy_fcgi, remoteip, rewrite, setenvif, dir, mime (в базовом httpd они уже включены).
- **mysqld не стартует после z9_bitrix.cnf** → закомментируй устаревшую директиву в `/etc/my.cnf.d/z9_bitrix.cnf`, `systemctl restart mariadb`, смотри `journalctl -u mariadb`.
- **Сайт «белый экран» / ошибка БД** → проверь, что 50-database.sh отработал и пользователь из dbconn.php создан; проверь `/var/log/php/exceptions.log` и `b_event_log`.
- **debug=true на проде** → в `/var/www/mirtkani.rf/bitrix/.settings.php` выключить `'debug' => false` (после успешного запуска).
- **SSL: wildcard не выпустился** → проверь токен: `curl -sS https://api.cloudflare.com/client/v4/zones?name=xn--80apbgijsq.xn--p1ai -H "Authorization: Bearer $(grep -oP 'api_token = \K.*' /root/.secrets/cloudflare.ini)"` должен вернуть `"success":true`. Затем перевыпусти командой из конца `35-ssl.sh`. Пока не выпустился — nginx работает на восстановленном (старом) сертификате.
- **certbot renew не идёт** → в `/etc/letsencrypt/renewal/xn--80apbgijsq.xn--p1ai.conf` должно быть `authenticator = dns-cloudflare` и `dns_cloudflare_credentials = /root/.secrets/cloudflare.ini`. Проверка: `certbot renew --dry-run`.

## Опционально (best practices)
- **swap** (на источнике не было): `fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile && echo '/swapfile none swap sw 0 0' >> /etc/fstab`.
- **innodb_buffer_pool_size** в `z9_bitrix.cnf` подогнать под RAM нового сервера (~50–60%).
- После запуска — сменить пароли (взлом в анамнезе): Bitrix-админы, БД, SSH/FTP.
