# Деплой 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-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` ```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` → `-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` | не трогать |