- порядок шагов исправлен (сначала код, потом таблицы) - sudo согласован - PostgreSQL: установка → код → таблицы - все <домен> заменены на white.nubes.ru как пример - таблица .env с колонкой 'Что писать'
11 KiB
Деплой 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 (или любая 15+).
Безопасность: слушает только localhost (наружу не торчит).
# 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.4), после клонирования кода — схема лежит в репозитории.
2. Node.js + код приложения + таблицы БД
# 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.4 Теперь код есть — можно создать таблицы (schema.sql в репозитории)
sudo -u postgres psql -d ipwhitelist -f /opt/ipwhitelist/sql/schema.sql
# 2.5 Проверить что таблицы создались
sudo -u postgres psql -d ipwhitelist -c "\dt"
# Результат: companies, whitelist_entries, audit_log, session
3. .env — настройка приложения
# 3.1 Скопировать шаблон
cd /opt/ipwhitelist
sudo cp .env.example .env
sudo chmod 600 .env # чтобы никто не прочитал пароли
3.2 Открыть .env и заполнить значения:
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 как прослойка.
# 4.1 Установить nginx и certbot
sudo apt install -y nginx certbot python3-certbot-nginx
4.2 Создать конфиг nginx. Заменить white.nubes.ru на свой домен:
sudo nano /etc/nginx/sites-available/ipwhitelist
Вставить:
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;
}
}
# 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 — автозапуск приложения
Зачем: чтобы приложение само стартовало после перезагрузки сервера.
# 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 → ipwhitelist-app-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. Финальная проверка
# 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. Обновление приложения
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 |
не трогать |