mirror of
https://gitverse.ru/kpa39l/md2vk.git
synced 2026-09-29 09:55:04 +00:00
Baseline md2vk: docs, audit log, docker 8420, openspec, deploy
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
# md2vk — Деплой
|
||||
|
||||
## Топология
|
||||
|
||||
```
|
||||
https://md2vk.nixg.ru (Caddy на vps02, basic auth)
|
||||
└─ reverse_proxy 10.8.0.2:8420 (WireGuard: vps02 .4 → bigbox .1)
|
||||
└─ docker-контейнер md2vk на bigbox, 127.0.0.1:8420
|
||||
```
|
||||
|
||||
- Порт приложения **8420** (8000 занят docker-search-api на bigbox).
|
||||
- Контейнер слушает на 127.0.0.1:8420 (снаружи bigbox не открыт).
|
||||
|
||||
## bigbox (10.8.0.2) — приложение
|
||||
|
||||
```bash
|
||||
cd /opt/md2vk
|
||||
make docker-up # docker compose up -d --build
|
||||
docker ps | grep md2vk # статус
|
||||
curl -s http://127.0.0.1:8420/api/v1/health # {"status":"ok"}
|
||||
```
|
||||
|
||||
- Данные: named volume `md2vk_data` → `/data/md2vk.db` (SQLite).
|
||||
- Секрет: `./secrets/token_encryption_key` → `/run/secrets/token_encryption_key`.
|
||||
- Логи аудита: `./logs/` монтируется в `/logs`.
|
||||
- Health: `/api/v1/health`, проверяется Docker healthcheck.
|
||||
- Восстановление после перезагрузки: `restart: unless-stopped`.
|
||||
- Если надо пересоздать БД — удалить том (только по явной команде, данные!):
|
||||
`docker compose down -v && make docker-up` (НЕ делать без подтверждения).
|
||||
|
||||
## Создание пользователя и API-ключа
|
||||
|
||||
```bash
|
||||
cd /opt/md2vk
|
||||
source venv/bin/activate
|
||||
TOKEN_ENCRYPTION_KEY_FILE=/opt/md2vk/secrets/token_encryption_key ./scripts/create_user.py \
|
||||
--name estorozhenko --api-key-out secrets/estorozhenko_api_key.txt
|
||||
# вывод: API key сохранён в secrets/estorozhenko_api_key.txt (md2vk_...)
|
||||
```
|
||||
|
||||
Источник: `scripts/create_user.py` (добавляет User с сгенерированным ключом; ключ отображается один раз).
|
||||
|
||||
## vps02 (87.242.100.206) — Caddy
|
||||
|
||||
Файл `/opt/caddy/Caddyfile` на vps02, секция:
|
||||
|
||||
```
|
||||
md2vk.nixg.ru {
|
||||
basic_auth /* {
|
||||
estorozhenko $2a$14$T5gAji7gmg1t3Ifxw0CJy.jat9vpFfOiJIE8j5bnHynEVH1q.QTPS
|
||||
}
|
||||
reverse_proxy 10.8.0.2:8420
|
||||
}
|
||||
```
|
||||
|
||||
Применить (контейнер caddy, монтирует Caddyfile):
|
||||
|
||||
```bash
|
||||
ssh vps02
|
||||
docker exec caddy caddy validate --config /etc/caddy/Caddyfile # проверить синтаксис
|
||||
docker exec caddy caddy reload --config /etc/caddy/Caddyfile # перезагрузить
|
||||
# если нужно: docker restart caddy
|
||||
```
|
||||
|
||||
- TLS: Caddy автоматически выпускает Let's Encrypt сертификат для md2vk.nixg.ru (acme в Caddyfile: `email kpa39l@yandex.ru`).
|
||||
- Сертификат на caddy_data (volume), переживает рестарты.
|
||||
|
||||
## vps02 — fail2ban (блокировка после 5 попыток)
|
||||
|
||||
Пакет ставится на vps02 (Debian/Ubuntu):
|
||||
|
||||
```bash
|
||||
ssh vps02
|
||||
sudo apt-get update && sudo apt-get install -y fail2ban
|
||||
```
|
||||
|
||||
Конфиг jail (`/etc/fail2ban/jail.local`) и фильтр (`/etc/fail2ban/filter.d/md2vk.conf`):
|
||||
|
||||
```ini
|
||||
# /etc/fail2ban/filter.d/md2vk.conf
|
||||
[Definition]
|
||||
failregex = ^.*"status":401.*
|
||||
ignoreregex =
|
||||
```
|
||||
|
||||
```ini
|
||||
# /etc/fail2ban/jail.local
|
||||
[md2vk]
|
||||
enabled = true
|
||||
port = http,https
|
||||
filter = md2vk
|
||||
logpath = /var/log/caddy/access.log
|
||||
maxretry = 5
|
||||
findtime = 600
|
||||
bantime = -1
|
||||
action = iptables-allports
|
||||
```
|
||||
|
||||
- Лог Caddy в JSON: настроить в Caddyfile `log { output file /var/log/caddy/access.log format json }` (глобальный блок).
|
||||
- Перезапуск: `sudo systemctl restart fail2ban`.
|
||||
- Проверка: `sudo fail2ban-client status md2vk`.
|
||||
- Ручной unban: `sudo fail2ban-client -c /etc/fail2ban unban <ip>`.
|
||||
|
||||
## Сквозная проверка
|
||||
|
||||
```bash
|
||||
# 1. health через Caddy (без auth → 401)
|
||||
curl -s -o /dev/null -w "%{http_code}\n" https://md2vk.nixg.ru/api/v1/health # 401
|
||||
# 2. health c auth → 200
|
||||
curl -s -u 'estorozhenko:<пароль>' https://md2vk.nixg.ru/api/v1/health # {"status":"ok"}
|
||||
# 3. публикация не требует VK-токена? нет — конвертация:
|
||||
curl -s -u 'estorozhenko:<пароль>' -H 'Authorization: Bearer <api_key>' \
|
||||
-X POST https://md2vk.nixg.ru/api/v1/convert \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"message_md":"**test** *curl*"}' # format_data
|
||||
# 4. баним проверкой: 5 раз неверный пароль → fail2ban ban IP
|
||||
for i in 1 2 3 4 5 6; do curl -s -o /dev/null -w "%{http_code}\n" -u 'estorozhenko:wrong' https://md2vk.nixg.ru/api/v1/health; done
|
||||
# → 401 ×6, затем соединение DROP (curl timeout)
|
||||
sudo fail2ban-client status md2vk # IP в banned
|
||||
sudo fail2ban-client unban <ваш-ip>
|
||||
```
|
||||
|
||||
## Восстановление после аварии
|
||||
|
||||
- Приложение: `docker compose up -d --force-recreate` на bigbox.
|
||||
- Caddy: `docker restart caddy` на vps02 (volume caddy_data хранит сертификаты).
|
||||
- БД: том `md2vk_data`; бэкап = копия `/opt/md2vk/data/md2vk.db` (вне контейнера) — включена в homelab-backup (/opt/backup).
|
||||
Reference in New Issue
Block a user