- server.js: санитизация filename в /export (header injection) - ui/api-client.js: req.setTimeout(15000) + try/catch JSON.parse - docs/devops-deploy.md: убран дубль X-Forwarded-Proto
285 lines
11 KiB
Markdown
285 lines
11 KiB
Markdown
# Деплой ipwhitelist — PRODUCTION
|
||
|
||
Репозиторий: `https://gitea.services.ngcloud.ru/Nail/ipwhitelist-app.git` (публичный)
|
||
ОС: Ubuntu 22.04 / 24.04 (для других ОС команды могут отличаться)
|
||
|
||
---
|
||
|
||
## 0. Что должно быть готово до начала
|
||
|
||
| Что | Откуда берётся |
|
||
|---|---|
|
||
| Сервер (ВМ) с Ubuntu | Выделяет DevOps |
|
||
| Домен (например `white.nubes.ru`) | DNS запись на сервер |
|
||
| Доступ к Keycloak Nubes (realm `cloud`) | Существующий Keycloak в инфраструктуре Nubes |
|
||
| Зарегистрированный OIDC-клиент в Keycloak | Создаётся в Keycloak (шаг 6) |
|
||
| `KC_CLIENT_ID` и `KC_CLIENT_SECRET` | Выдаются после регистрации клиента |
|
||
|
||
**Что будет установлено на сервер:** Node.js 20, PostgreSQL 16, nginx, certbot, PM2.
|
||
|
||
---
|
||
|
||
## 1. PostgreSQL — установка
|
||
|
||
**Где:** на этой же ВМ, рядом с приложением.
|
||
**Версия:** 16 (на Ubuntu 22.04 — 14, на 24.04 — 16).
|
||
**Безопасность:** слушает только localhost (наружу не торчит).
|
||
|
||
```bash
|
||
# 1.1 Установить PostgreSQL
|
||
sudo apt update
|
||
sudo apt install -y postgresql
|
||
|
||
# 1.2 Проверить что запустился и слушает localhost
|
||
sudo systemctl status postgresql --no-pager
|
||
ss -tlnp | grep 5432
|
||
# Должно быть: 127.0.0.1:5432 (НЕ 0.0.0.0:5432)
|
||
|
||
# 1.3 Сгенерировать пароль для БД — он понадобится в .env
|
||
DB_PASS=$(openssl rand -base64 24)
|
||
echo "Пароль БД: $DB_PASS" # сохранить — вписать в .env
|
||
|
||
# 1.4 Создать пользователя и базу данных
|
||
sudo -u postgres psql -c "CREATE USER ipwhitelist WITH PASSWORD '${DB_PASS}';"
|
||
sudo -u postgres psql -c "CREATE DATABASE ipwhitelist OWNER ipwhitelist;"
|
||
```
|
||
|
||
**Таблицы создадим позже (шаг 2.3), после клонирования кода — схема лежит в репозитории.**
|
||
|
||
---
|
||
|
||
## 2. Node.js + код приложения + таблицы БД
|
||
|
||
```bash
|
||
# 2.1 Установить Node.js 20
|
||
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
|
||
sudo apt install -y nodejs
|
||
|
||
# 2.2 Скачать код и установить зависимости
|
||
sudo git clone https://gitea.services.ngcloud.ru/Nail/ipwhitelist-app.git /opt/ipwhitelist
|
||
sudo chown -R $(whoami):$(whoami) /opt/ipwhitelist # чтобы npm install не просил sudo
|
||
cd /opt/ipwhitelist
|
||
npm install --production
|
||
|
||
# 2.3 Теперь код есть — можно создать таблицы (schema.sql в репозитории)
|
||
sudo -u postgres psql -d ipwhitelist -f /opt/ipwhitelist/sql/schema.sql
|
||
|
||
# 2.4 Проверить что таблицы создались
|
||
sudo -u postgres psql -d ipwhitelist -c "\dt"
|
||
# Результат: companies, whitelist_entries, audit_log, session
|
||
```
|
||
|
||
---
|
||
|
||
## 3. .env — настройка приложения
|
||
|
||
```bash
|
||
# 3.1 Скопировать шаблон
|
||
cd /opt/ipwhitelist
|
||
sudo cp .env.example .env
|
||
sudo chmod 600 .env # чтобы никто не прочитал пароли
|
||
```
|
||
|
||
**3.2 Открыть .env и заполнить значения:**
|
||
```bash
|
||
sudo nano /opt/ipwhitelist/.env
|
||
```
|
||
|
||
**Что и куда писать:**
|
||
|
||
| Строка в .env | Что вписать |
|
||
|---|---|
|
||
| `DB_PASS=` | Пароль, сгенерированный на шаге 1.3 |
|
||
| `DEV_MODE=false` | **ОБЯЗАТЕЛЬНО false** иначе будет mock-логин |
|
||
| `ADMIN_CLIENT_ID=WZ01112` | clientId администратора (получить у заказчика) |
|
||
| `KC_CLIENT_ID=` | ID клиента из Keycloak (шаг 6) |
|
||
| `KC_CLIENT_SECRET=` | Secret клиента из Keycloak (шаг 6) |
|
||
| `APP_URL=https://white.nubes.ru` | **Реальный домен** без слеша на конце |
|
||
| `SESSION_SECRET=` | Сгенерировать: `openssl rand -base64 32` |
|
||
| `CSRF_SECRET=` | Сгенерировать: `openssl rand -base64 32` |
|
||
|
||
**Остальные строки не трогать** — значения по умолчанию подходят.
|
||
|
||
---
|
||
|
||
## 4. nginx — HTTPS и прокси
|
||
|
||
**Зачем:** браузер не пускает на HTTPS-сайты с localhost. Нужен nginx как прослойка.
|
||
|
||
```bash
|
||
# 4.1 Установить nginx и certbot
|
||
sudo apt install -y nginx certbot python3-certbot-nginx
|
||
```
|
||
|
||
**4.2 Создать конфиг nginx.** Заменить `white.nubes.ru` на свой домен:
|
||
|
||
```bash
|
||
sudo nano /etc/nginx/sites-available/ipwhitelist
|
||
```
|
||
|
||
Вставить:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name white.nubes.ru; # ← ЗАМЕНИТЬ на свой домен
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name white.nubes.ru; # ← ЗАМЕНИТЬ на свой домен
|
||
|
||
ssl_certificate /etc/letsencrypt/live/white.nubes.ru/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/white.nubes.ru/privkey.pem;
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:3001;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
}
|
||
}
|
||
```
|
||
|
||
```bash
|
||
# 4.3 Включить сайт
|
||
sudo ln -s /etc/nginx/sites-available/ipwhitelist /etc/nginx/sites-enabled/
|
||
sudo rm -f /etc/nginx/sites-enabled/default
|
||
|
||
# 4.4 Получить SSL-сертификат (certbot сам подправит конфиг)
|
||
sudo certbot --nginx -d white.nubes.ru # ← ЗАМЕНИТЬ на свой домен
|
||
|
||
# 4.5 Проверить что nginx работает
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
```
|
||
|
||
---
|
||
|
||
## 5. PM2 — автозапуск приложения
|
||
|
||
**Зачем:** чтобы приложение само стартовало после перезагрузки сервера.
|
||
|
||
```bash
|
||
# 5.1 Установить PM2
|
||
sudo npm i -g pm2
|
||
|
||
# 5.2 Запустить приложение
|
||
cd /opt/ipwhitelist
|
||
sudo pm2 start server.js --name ipwhitelist --update-env
|
||
|
||
# 5.3 Настроить автозапуск при перезагрузке
|
||
sudo pm2 startup systemd
|
||
sudo pm2 save
|
||
|
||
# 5.4 Проверить что запустилось
|
||
sudo pm2 status
|
||
# Должен быть статус: online
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Keycloak — регистрация OIDC-клиента
|
||
|
||
**Где:** в админке Keycloak Nubes (`https://keycloak.nubes.ru/admin`, realm `cloud`).
|
||
**Зачем:** чтобы Keycloak знал наше приложение и пускал пользователей обратно после входа.
|
||
|
||
**6.1 Создать клиента:**
|
||
|
||
| Поле | Значение |
|
||
|---|---|
|
||
| Client ID | `white.nubes.ru` (или свой домен) |
|
||
| Client authentication | ON (включено) |
|
||
| Standard flow | ON (включено) |
|
||
| Valid redirect URIs | `https://white.nubes.ru/callback` |
|
||
| Web origins | `https://white.nubes.ru` |
|
||
|
||
**6.2 Забрать секрет:** после создания клиента открыть вкладка `Credentials` → `Client secret` → скопировать.
|
||
|
||
**6.3 Создать mapper'ы** (вкладка `Client scopes` → `<ClientID>-dedicated` → `Add mapper` → `By configuration` → `User Attribute`):
|
||
|
||
Создать три mapper'а:
|
||
|
||
| Имя | User Attribute | Claim name | Тип |
|
||
|---|---|---|---|
|
||
| `ClientID` | `client_id` | `ClientID` | String |
|
||
| `company_id` | `company_id` | `company_id` | String |
|
||
| `company_name` | `company_name` | `company_name` | String |
|
||
|
||
**6.4 Создать пользователей** (вкладка `Users` → `Add user`):
|
||
|
||
| Логин | Пароль | Атрибуты |
|
||
|---|---|---|
|
||
| `admin` | задать вкладка Credentials | `client_id=WZ01112`, `company_id=1`, `company_name=Nubes Admin` |
|
||
| `client` | задать | `client_id=WZ88888`, `company_id=2`, `company_name=Альфа` |
|
||
|
||
**Как задать атрибуты:** вкладка `Attributes` → добавить по одному → `Save`.
|
||
|
||
**Формат multi-company:** `client_id = "WZ11125,WZ03816"` — первое значение до запятой = активная компания. Приложение само разберёт.
|
||
|
||
---
|
||
|
||
## 7. Финальная проверка
|
||
|
||
```bash
|
||
# 7.1 Убедиться что в .env всё заполнено
|
||
grep -E "DEV_MODE|KC_CLIENT_ID|KC_CLIENT_SECRET|APP_URL|DB_PASS" /opt/ipwhitelist/.env
|
||
# Проверить: DEV_MODE=false, KC_CLIENT_ID и KC_CLIENT_SECRET не пустые
|
||
|
||
# 7.2 Перезапустить приложение
|
||
cd /opt/ipwhitelist
|
||
sudo pm2 restart ipwhitelist --update-env
|
||
|
||
# 7.3 Проверить что включился OIDC-режим
|
||
sudo pm2 logs ipwhitelist --lines 3 --nostream
|
||
# В логе должно быть: [auth] OIDC — Keycloak
|
||
# Если [auth] MOCK — значит KC_CLIENT_ID/KC_CLIENT_SECRET не заданы
|
||
```
|
||
|
||
**Открыть в браузере:**
|
||
|
||
| URL | Что должно произойти |
|
||
|---|---|
|
||
| `https://white.nubes.ru/healthz` | Покажет `OK` |
|
||
| `https://white.nubes.ru/` | Редирект на страницу логина Keycloak |
|
||
| Ввести логин/пароль пользователя из Keycloak | Редирект обратно на главную с белым списком |
|
||
| `https://white.nubes.ru/export` | Список CIDR (текст) |
|
||
| `https://white.nubes.ru/logout` | Выход из системы |
|
||
|
||
---
|
||
|
||
## 8. Обновление приложения
|
||
|
||
```bash
|
||
cd /opt/ipwhitelist
|
||
sudo git pull
|
||
sudo npm install --production
|
||
sudo pm2 restart ipwhitelist --update-env
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Переменные .env — полный список
|
||
|
||
| Переменная | Когда нужна | По умолчанию | Что писать |
|
||
|---|---|---|---|
|
||
| `DB_HOST` | всегда | — | `localhost` |
|
||
| `DB_PORT` | всегда | 5432 | — |
|
||
| `DB_NAME` | всегда | — | `ipwhitelist` |
|
||
| `DB_USER` | всегда | — | `ipwhitelist` |
|
||
| `DB_PASS` | всегда | — | пароль из шага 1.3 |
|
||
| `DB_SSLMODE` | никогда | disable | не трогать |
|
||
| `DEV_MODE` | всегда | true | **false** в production |
|
||
| `ADMIN_CLIENT_ID` | всегда | WZ01112 | clientId админа |
|
||
| `KC_CLIENT_ID` | для SSO | — | из Keycloak (шаг 6) |
|
||
| `KC_CLIENT_SECRET` | для SSO | — | из Keycloak (шаг 6) |
|
||
| `KC_BASE_URL` | для SSO | `https://keycloak.nubes.ru/realms/cloud` | не трогать |
|
||
| `APP_URL` | для SSO | — | `https://white.nubes.ru` |
|
||
| `SESSION_SECRET` | всегда | — | `openssl rand -base64 32` |
|
||
| `CSRF_SECRET` | опционально | — | `openssl rand -base64 32` |
|
||
| `PORT` | всегда | 3000 | `3001` |
|
||
| `DEFAULT_LIMIT` | опционально | 15 | не трогать |
|
||
| `API_BASE` | всегда | `http://localhost:PORT` | не трогать |
|