chore(home): mirror from kalinamall (9883e6a) with papatramp URLs

This commit is contained in:
2026-07-14 20:43:52 +10:00
commit ed4e78f6c3
312 changed files with 42790 additions and 0 deletions
+465
View File
@@ -0,0 +1,465 @@
# Ubuntu 24.04 — установка SAC (native, без Docker)
Пошаговое руководство: **PostgreSQL + Python venv + systemd + nginx**.
Рекомендуемый путь для production.
---
## 0. Исходные данные
| Параметр | Пример |
|----------|--------|
| FQDN | `sac.kalinamall.ru` |
| IP | `10.0.0.50` |
| Каталог | `/opt/security-alert-center` |
| Пользователь сервиса | `sac` |
| API только на localhost | `127.0.0.1:8000` |
| Снаружи | nginx → 443 → API |
---
## 1. Базовая настройка ОС
```bash
sudo apt update
sudo apt upgrade -y
sudo timedatectl set-timezone Europe/Moscow
```
### Firewall (ufw)
```bash
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
```
---
## 2. Пакеты
```bash
sudo apt install -y \
git \
postgresql \
postgresql-contrib \
nginx \
python3.12 \
python3.12-venv \
python3-pip \
jq \
certbot \
python3-certbot-nginx
```
Проверка:
```bash
python3.12 --version
psql --version
nginx -v
```
---
## 3. Клонирование репозитория
```bash
sudo mkdir -p /opt
sudo git clone https://git.papatramp.ru/PapaTramp/security-alert-center.git /opt/security-alert-center
```
---
## 4. PostgreSQL
Создать пользователя и БД (пароль сохраните для `.env`):
```bash
sudo -u postgres psql <<'SQL'
CREATE USER sac WITH PASSWORD 'ЗАМЕНИТЕ_НА_ДЛИННЫЙ_ПАРОЛЬ';
CREATE DATABASE sac OWNER sac;
GRANT ALL PRIVILEGES ON DATABASE sac TO sac;
SQL
```
PostgreSQL по умолчанию слушает `127.0.0.1` — для SAC этого достаточно.
Проверка:
```bash
psql "postgresql://sac@127.0.0.1/sac" -c 'SELECT 1'
```
Каталог бэкапов:
```bash
sudo mkdir -p /var/backups/sac
sudo chown postgres:postgres /var/backups/sac
```
---
## 5. Пользователь `sac` и Python venv
```bash
sudo useradd --system --home /opt/security-alert-center --shell /usr/sbin/nologin sac || true
sudo chown -R sac:sac /opt/security-alert-center
cd /opt/security-alert-center/backend
sudo -u sac python3.12 -m venv .venv
sudo -u sac .venv/bin/pip install --upgrade pip
sudo -u sac .venv/bin/pip install -r requirements.txt
```
---
## 6. Конфигурация
Файл лежит **в каталоге приложения** (владелец `sac`) — так проще, чем права на `/etc/...`.
```bash
sudo mkdir -p /opt/security-alert-center/config
sudo cp /opt/security-alert-center/deploy/env.native.example \
/opt/security-alert-center/config/sac-api.env
sudo nano /opt/security-alert-center/config/sac-api.env
sudo chown sac:sac /opt/security-alert-center/config/sac-api.env
sudo chmod 600 /opt/security-alert-center/config/sac-api.env
```
Если уже создавали `/etc/security-alert-center/sac-api.env` — перенесите:
```bash
sudo mkdir -p /opt/security-alert-center/config
sudo cp /etc/security-alert-center/sac-api.env /opt/security-alert-center/config/sac-api.env
sudo chown sac:sac /opt/security-alert-center/config/sac-api.env
sudo chmod 600 /opt/security-alert-center/config/sac-api.env
```
Обязательно задать:
- `DATABASE_URL`с паролем PostgreSQL из шага 4 (если в пароле есть `#`, `@`, `%` — возьмите значение в **кавычки**: `DATABASE_URL="postgresql+psycopg2://..."`)
- `JWT_SECRET``openssl rand -hex 32`
- `SAC_PUBLIC_URL``https://sac.kalinamall.ru`
- `SAC_BOOTSTRAP_API_KEY``python3.12 -c "import secrets; print('sac_'+secrets.token_urlsafe(32))"`
- `SAC_ADMIN_PASSWORD` — пароль входа в веб-UI (отдельно от API key агентов)
- `EVENT_SCHEMA_PATH=/opt/security-alert-center/schemas/event-schema-v1.json`
- (опц.) Telegram из SAC: `TELEGRAM_ENABLED=true`, `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`, `TELEGRAM_MIN_SEVERITY=high`
---
## 7. Миграции БД
Проверка, что `sac` читает конфиг (должно быть без `Permission denied`):
```bash
ls -la /opt/security-alert-center/config/sac-api.env
# должно быть: -rw------- sac sac
sudo -u sac test -r /opt/security-alert-center/config/sac-api.env && echo OK
```
Миграции:
```bash
cd /opt/security-alert-center/backend
sudo -u sac bash -c 'set -a; source /opt/security-alert-center/config/sac-api.env; set +a; .venv/bin/alembic upgrade head'
```
---
## 8. systemd
Приложение загружает `config/sac-api.env` **само** (не через `EnvironmentFile` systemd) — так же, как при `alembic` с `source`.
```bash
cd /opt/security-alert-center && sudo git pull
sudo cp /opt/security-alert-center/deploy/systemd/sac-api.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable sac-api
sudo systemctl start sac-api
sudo systemctl status sac-api --no-pager
```
Логи:
```bash
journalctl -u sac-api -f
```
---
## 9. nginx и TLS
Для KalinaMall: **корпоративный wildcard VeriSign** (или DigiCert), не Let's Encrypt.
Хост `sac.kalinamall.ru` должен попадать под `*.kalinamall.ru`.
**Подробно:** форматы, scp с Windows/Linux, `.pfx` → PEM, права — **[ssl-certificate.md](ssl-certificate.md)**.
### 9.1. Кратко: куда положить файлы
nginx ожидает **два PEM-файла**:
| Файл на сервере | Содержимое |
|-----------------|------------|
| `/etc/ssl/sac/fullchain.pem` | Wildcard-сертификат + промежуточные CA |
| `/etc/ssl/sac/privkey.pem` | Закрытый ключ |
```bash
# каталог: группа ssl-cert, чтобы www-data мог зайти в каталог (chmod 750)
sudo mkdir -p /etc/ssl/sac
sudo chown root:ssl-cert /etc/ssl/sac
sudo chmod 750 /etc/ssl/sac
# nginx читает ключ через группу ssl-cert (на чистой Ubuntu в группе часто только postgres)
sudo groupadd -f ssl-cert
sudo usermod -aG ssl-cert www-data
```
Скопировать с рабочего ПК (пример):
```bash
# с вашего компьютера:
scp fullchain.pem privkey.pem papatramp@<IP_SAC>:/tmp/
# на сервере:
sudo mv /tmp/fullchain.pem /tmp/privkey.pem /etc/ssl/sac/
sudo chmod 644 /etc/ssl/sac/fullchain.pem
sudo chmod 640 /etc/ssl/sac/privkey.pem
sudo chown root:root /etc/ssl/sac/fullchain.pem
sudo chown root:ssl-cert /etc/ssl/sac/privkey.pem
# каталог снова root:ssl-cert (если меняли владельца при mv)
sudo chown root:ssl-cert /etc/ssl/sac
sudo chmod 750 /etc/ssl/sac
# worker nginx должен подхватить группу www-data
sudo systemctl restart nginx
sudo -u www-data test -x /etc/ssl/sac && echo dir OK || echo dir FAIL
sudo -u www-data test -r /etc/ssl/sac/fullchain.pem && echo fullchain OK || echo fullchain FAIL
sudo -u www-data test -r /etc/ssl/sac/privkey.pem && echo key OK || echo key FAIL
```
Если `test -r privkey.pem` молчит: каталог был `root:root` при `750`у `www-data` нет права `x` на `/etc/ssl/sac/`; либо `www-data` не в `ssl-cert`. См. [ssl-certificate.md §3](ssl-certificate.md#3-каталог-и-права-на-сервере).
Если PFX с другого Linux — `scp` на SAC: [ssl-certificate.md §4.3](ssl-certificate.md#43-забрать-файл-с-другого-linux-сервера-scp).
Распаковка PFX на Ubuntu 24.04: **`openssl pkcs12 -legacy`** — [§4.4](ssl-certificate.md#44-распаковка-pfx--p12-на-сервере-ubuntu-2404).
### 9.2. Конфиг nginx (HTTPS)
```bash
cd /opt/security-alert-center
sudo git pull
sudo cp deploy/nginx/sac.conf.tls.example /etc/nginx/sites-available/sac
sudo nano /etc/nginx/sites-available/sac
# Проверьте пути ssl_certificate и ssl_certificate_key → /etc/ssl/sac/...
sudo ln -sf /etc/nginx/sites-available/sac /etc/nginx/sites-enabled/sac
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
```
Шаблон `sac.conf.tls.example` содержит **default_server** с `return 444` (:80) и `ssl_reject_handshake` (:443) для любого Host, кроме `sac.kalinamall.ru`. Это защищает от ситуации, когда на IP SAC (например `192.168.160.145`) по ошибке DNS попадает `ext.kalinamall.ru` и открывается форма входа SAC.
Проверка после reload:
```bash
curl -sS -o /dev/null -w '%{http_code}\n' --resolve sac.kalinamall.ru:443:127.0.0.1 https://sac.kalinamall.ru/health
# ожидается 200
curl -sS -o /dev/null -w '%{http_code}\n' --resolve ext.kalinamall.ru:443:127.0.0.1 https://ext.kalinamall.ru/ 2>/dev/null || echo "connection closed (444/reject OK)"
```
Проверка:
```bash
curl -sS https://sac.kalinamall.ru/health | jq .
```
В `config/sac-api.env` должно быть: `SAC_PUBLIC_URL=https://sac.kalinamall.ru`
### 9.3. Агенты (ssh-monitor, RDP) и доверие к CA
- Агенты ходят на `https://sac.kalinamall.ru/api/v1/events`.
- Если используется **внутренний корневой CA**, а не публичный VeriSign/DigiCert в системном store — на Linux/Windows может понадобиться установка корневого сертификата в доверенные (или корпоративный прокси с подменой TLS).
- Для публичного коммерческого wildcard от известного УЦ обычно **дополнительных действий на агентах не нужно**.
### 9.4. Альтернатива: только HTTP (отладка)
Шаблон `deploy/nginx/sac.conf.example` — порт 80 без TLS. Не для production.
### 9.5. Альтернатива: Let's Encrypt
Если понадобится публичный бесплатный сертификат только на этот хост:
```bash
sudo cp deploy/nginx/sac.conf.example /etc/nginx/sites-available/sac
# ... nginx -t, reload, затем:
sudo certbot --nginx -d sac.kalinamall.ru
```
---
## 10. Сборка веб-UI (фаза 1C)
```bash
sudo apt install -y nodejs npm
cd /opt/security-alert-center
sudo -u sac git pull
cd frontend
sudo -u sac npm ci
sudo -u sac npm run build
ls -la dist/index.html
sudo systemctl restart sac-api
```
В `config/sac-api.env` задайте `SAC_ADMIN_PASSWORD`, затем откройте `https://sac.kalinamall.ru/` (логин `SAC_ADMIN_USERNAME`, по умолчанию `admin`).
После обновления с multi-user (миграция `009_sac_users`): выполните `alembic upgrade head` в каталоге `backend/`. При первом старте API создаст пользователя **admin** из `SAC_ADMIN_*`, если таблица `sac_users` пуста.
Добавить сотрудника с ролью **monitor** (просмотр без «Настройки»):
```bash
cd /opt/security-alert-center/backend
sudo -u sac python scripts/sac_manage_user.py create ivanov 'StrongPass123' --role monitor
```
Роли: **admin** — полный доступ; **monitor** — события, хосты, проблемы, отчёты (без `/settings` и `/users`).
---
## 11. Проверка
Локально на сервере:
```bash
curl -sS http://127.0.0.1:8000/health | jq .
```
Через nginx (после TLS):
```bash
curl -sS https://sac.kalinamall.ru/health | jq .
```
Тест ingest (подставьте `SAC_BOOTSTRAP_API_KEY`):
```bash
API_KEY="ваш_ключ_из_sac-api.env"
curl -sS -X POST http://127.0.0.1:8000/api/v1/events \
-H "Authorization: Bearer ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"schema_version": "1.0",
"event_id": "00000000-0000-4000-8000-000000000002",
"occurred_at": "2026-05-26T12:00:00+03:00",
"source": {"product": "ssh-monitor", "product_version": "test"},
"host": {"hostname": "test-host", "os_family": "linux"},
"category": "agent",
"type": "agent.test",
"severity": "info",
"title": "Test",
"summary": "Native install check"
}'
```
Ожидается HTTP **202** и `"status": "accepted"`.
---
## 12. Резервное копирование
```bash
sudo tee /etc/cron.d/sac-backup <<'EOF'
0 3 * * * postgres pg_dump -Fc -U sac sac > /var/backups/sac/sac_$(date +\%Y\%m\%d).dump
EOF
```
Для `pg_dump` без пароля в cron настройте `~postgres/.pgpass` (см. документацию PostgreSQL).
---
## 13. Обновление SAC (деплой)
### Рекомендуется: скрипт `/opt/sac-deploy.sh`
После первой установки один раз:
```bash
sudo cp /opt/security-alert-center/deploy/sac-deploy.sh /opt/sac-deploy.sh
sudo chmod 755 /opt/sac-deploy.sh
```
Каждое обновление с git:
```bash
sudo /opt/sac-deploy.sh
```
Скрипт: `chown sac:sac``git pull` (от **sac**) → `pip``alembic``npm run build``systemctl restart sac-api` → проверка `/health`.
### Вручную (если без скрипта)
```bash
sudo chown -R sac:sac /opt/security-alert-center
sudo -u sac git -C /opt/security-alert-center pull
cd /opt/security-alert-center/frontend && sudo -u sac npm ci && sudo -u sac npm run build
sudo -u sac /opt/security-alert-center/backend/.venv/bin/pip install -r /opt/security-alert-center/backend/requirements.txt
sudo -u sac bash -c 'set -a; source /opt/security-alert-center/config/sac-api.env; set +a; cd /opt/security-alert-center/backend && .venv/bin/alembic upgrade head'
sudo systemctl restart sac-api
```
### Git: только от пользователя `sac`
Не выполняйте `sudo git pull` в `/opt/security-alert-center``.git` станет root и появится:
`error: cannot open '.git/FETCH_HEAD': Permission denied`
Исправление: `sudo chown -R sac:sac /opt/security-alert-center`.
---
## 14. Чеклист
- [ ] Ubuntu 24.04, timezone
- [ ] ufw: 22, 80, 443
- [ ] PostgreSQL: БД `sac`, пользователь `sac`
- [ ] venv, зависимости установлены
- [ ] `/opt/security-alert-center/config/sac-api.env`, владелец `sac:sac`, chmod 600
- [ ] `alembic upgrade head` без ошибок
- [ ] `sac-api` active (systemd)
- [ ] nginx + TLS
- [ ] `/health` ok, ingest 202
- [ ] `frontend/dist` собран, UI открывается, вход admin OK
- [ ] cron backup
---
## 15. Устранение неполадок
| Симптом | Действие |
|---------|----------|
| `sac-api.env: Permission denied` | Конфиг в `/opt/security-alert-center/config/`, `chown sac:sac`, `chmod 600`. Не используйте `/etc/...` с каталогом `root:root` |
| `password authentication failed` в **sac-api**, но alembic OK | Старый unit с `EnvironmentFile=``git pull`, обновить `sac-api.service`, `daemon-reload`, `restart`. Либо пароль в `DATABASE_URL` ≠ PostgreSQL |
| `password authentication failed` везде | Пароль в `DATABASE_URL` в кавычках; `ALTER USER sac WITH PASSWORD`; тот же пароль в URL |
| `database: error` / SQLAlchemy connect | `systemctl status postgresql`; проверить `DATABASE_URL` после успешного `source` |
| 401 ingest | ключ в `Authorization: Bearer`; проверить `SAC_BOOTSTRAP_API_KEY` |
| 502 от nginx | API не слушает: `ss -lntp \| grep 8000`, `systemctl restart sac-api` |
| Schema errors 422 | путь `EVENT_SCHEMA_PATH`, наличие файла schema |
| `FETCH_HEAD: Permission denied` | `sudo chown -R sac:sac /opt/security-alert-center`; далее `sudo -u sac git pull` |
| UI 404 / пустая главная | `cd frontend && sudo -u sac npm run build`; `restart sac-api` |
| 503 на `/auth/login` | задать `SAC_ADMIN_PASSWORD` в `config/sac-api.env` |
| `test -r privkey.pem` без вывода | каталог `/etc/ssl/sac``root:ssl-cert`, `www-data` в группе `ssl-cert` — [ssl-certificate.md](ssl-certificate.md) §3 |
| PFX `RC2-40-CBC unsupported` | `openssl pkcs12 -legacy` — [ssl-certificate.md](ssl-certificate.md) §4.4 |
---
## См. также
- [install-ubuntu-24.04.md](install-ubuntu-24.04.md) — указатель
- [install-ubuntu-24.04-docker.md](install-ubuntu-24.04-docker.md) — альтернатива (не prod)
- [deployment.md](deployment.md)