SafeLine WAF: Полное руководство по развёртыванию в Production
Для команды DevOps | Production-Ready Deployment Guide
Дата: 27 января 2026
📖 О чём эта статья
Это полное практическое руководство по развёртыванию SafeLine WAF (Web Application Firewall) в production среде на базе Docker. Материал основан на реальном опыте, включая разбор критических ошибок, которые были найдены и исправлены в процессе peer review.
Для кого эта статья:
- ✅ DevOps инженеров, внедряющих WAF
- ✅ System администраторов, отвечающих за безопасность
- ✅ Команд, мигрирующих с NPM/Traefik на SafeLine
- ✅ Всех, кто хочет понять production deployment от А до Я
Что вы получите:
- 🎯 Пошаговые инструкции (каждый шаг объяснён)
- 🔍 Разбор критических ошибок и их решений
- 📊 Архитектурные решения с обоснованием
- 🛡️ Production-grade security best practices
- 🔧 Готовые скрипты автоматизации
- 🆘 Troubleshooting guide для типовых проблем
💭 Личное вступление: Почему важен peer review
Честность: Первоначальная версия этого deployment содержала 8 критических ошибок, включая 1 фатальную, которая бы полностью сломала production.
Эти ошибки были найдены благодаря критическому вопросу коллеги: "Стоять... почему два reverse proxy? SafeLine же сам reverse proxy!"
Этот момент стал поворотным. Вместо защиты своего первоначального решения, я провёл полный аудит, изучил 20+ источников, и переделал всё с нуля.
Вывод: Ошибаются все. Важно не скрывать ошибки, а учиться на них и делиться опытом.
Эта статья - результат этого обучения. Здесь собрано всё, что нужно знать, чтобы не повторить те же ошибки.
📚 Содержание
- Введение и архитектура
- Критические ошибки и их разбор
- Системные требования
- Подготовка инфраструктуры
- Установка и конфигурация
- SSL сертификаты (Let's Encrypt)
- Добавление backend сервисов
- Мониторинг и логирование
- Backup и disaster recovery
- Troubleshooting
- Production checklist
1. Введение и архитектура
1.1 Что такое SafeLine WAF?
SafeLine - это self-hosted WAF (Web Application Firewall) с встроенным reverse proxy на базе Tengine (форк Nginx).
Ключевые возможности:
┌─────────────────────────────────────────────┐
│ SafeLine WAF Capabilities │
├─────────────────────────────────────────────┤
│ │
│ 🛡️ WAF Protection: │
│ • SQL Injection blocking │
│ • XSS (Cross-Site Scripting) │
│ • CSRF protection │
│ • RCE (Remote Code Execution) │
│ • Path Traversal │
│ • 0-day detection (AI/ML) │
│ │
│ 🔄 Reverse Proxy: │
│ • SSL/TLS termination │
│ • Load balancing │
│ • HTTP/2, WebSocket support │
│ • Caching (proxy_cache) │
│ │
│ 🤖 Bot Protection: │
│ • CAPTCHA challenges │
│ • Rate limiting (advanced) │
│ • User-Agent filtering │
│ • IP reputation │
│ │
│ 📊 Monitoring: │
│ • Real-time attack dashboard │
│ • Detailed logs │
│ • Attack visualization │
│ • Alerts & notifications │
│ │
└─────────────────────────────────────────────┘
❓ Почему SafeLine, а не Nginx/NPM?
| Критерий | Nginx/NPM | SafeLine |
|---|---|---|
| Reverse Proxy | ✅ | ✅ |
| SSL Management | ✅ | ✅ |
| Web UI | ✅ NPM | ✅ |
| WAF Protection | ❌ | ✅ ⭐ |
| AI Threat Detection | ❌ | ✅ ⭐ |
| Attack Visualization | ❌ | ✅ ⭐ |
| Zero-day Protection | ❌ | ✅ ⭐ |
Вывод: SafeLine = NPM + Enterprise WAF в одном решении
1.2 Архитектура решения
Правильная архитектура (Version 2.0):
┌────────────────────────────────────────────────────────┐
│ INTERNET │
│ (Port 80/443) │
└───────────────────┬────────────────────────────────────┘
│
│ HTTP/HTTPS Traffic
↓
┌───────────────────────────┐
│ SafeLine Tengine │
│ (Reverse Proxy + WAF) │
│ │
│ • SSL Termination │
│ • Attack Detection │
│ • Request Filtering │
│ • Load Balancing │
└───────────┬───────────────┘
│
│ Docker Network: kodalinet (172.20.0.0/24)
│
┌───────────┴───────────────────────────────────┐
│ │
↓ ↓
┌──────────────────┐ ┌──────────────────┐
│ SafeLine Detector│ │ Backend Services │
│ (AI/ML Engine) │ │ │
│ │ │ • Web App 1 │
│ 172.20.0.5:8000 │ │ • API Server │
└──────────────────┘ │ • Database │
│ │ • etc... │
│ │ │
↓ │ (expose only!) │
┌──────────────────┐ └──────────────────┘
│ SafeLine MGT │
│ (Web UI) │
│ │
│ 172.20.0.4:1443 │
│ (internal only!) │
└──────────────────┘
│
↓
┌──────────────────┐
│ PostgreSQL │
│ (Configuration │
│ & Logs) │
│ │
│ 172.20.0.2:5432 │
└──────────────────┘
Принципы архитектуры:
- Single Entry Point: Только SafeLine на портах 80/443
- Internal Services: Все backend сервисы в одной сети, без expose наружу
- Defense in Depth: WAF проверяет ВСЕ входящие запросы
- Least Privilege: MGT UI доступен только через VPN/SSH tunnel
1.3 Компоненты SafeLine
Контейнеры и их роли:
SafeLine Stack (7 контейнеров):
┌─ safeline-tengine ──────────────────────────────────┐
│ Роль: Reverse Proxy + WAF │
│ Порты: 80, 443 (ЕДИНСТВЕННЫЕ открытые наружу!) │
│ CPU: 4 cores | RAM: 4GB │
│ Критичность: ⭐⭐⭐⭐⭐ │
└─────────────────────────────────────────────────────┘
┌─ safeline-detector ─────────────────────────────────┐
│ Роль: AI/ML движок для детекции атак │
│ Технология: Semantic analysis, 0-day detection │
│ CPU: 2 cores | RAM: 2GB │
│ Критичность: ⭐⭐⭐⭐⭐ │
└─────────────────────────────────────────────────────┘
┌─ safeline-mgt ──────────────────────────────────────┐
│ Роль: Web UI для управления │
│ Порт: 1443 (INTERNAL, через SSH tunnel!) │
│ CPU: 1 core | RAM: 1GB │
│ Критичность: ⭐⭐⭐⭐ │
└─────────────────────────────────────────────────────┘
┌─ safeline-pg ───────────────────────────────────────┐
│ Роль: PostgreSQL база данных │
│ Хранит: Конфиги, логи атак, статистику │
│ CPU: 2 cores | RAM: 2GB │
│ Критичность: ⭐⭐⭐⭐⭐ (БЭКАПИТЬ!) │
└─────────────────────────────────────────────────────┘
┌─ safeline-luigi ────────────────────────────────────┐
│ Роль: Обработчик и анализатор логов │
│ CPU: 1 core | RAM: 1GB │
│ Критичность: ⭐⭐⭐ │
└─────────────────────────────────────────────────────┘
┌─ safeline-fvm ──────────────────────────────────────┐
│ Роль: Feature Version Manager │
│ CPU: 0.5 core | RAM: 512MB │
│ Критичность: ⭐⭐ │
└─────────────────────────────────────────────────────┘
┌─ safeline-chaos ────────────────────────────────────┐
│ Роль: Дополнительный модуль безопасности │
│ CPU: 0.5 core | RAM: 512MB │
│ Критичность: ⭐⭐ │
└─────────────────────────────────────────────────────┘
ИТОГО: ~11 CPU cores, ~12GB RAM (пиковая нагрузка)
2. Критические ошибки и их разбор
⚠️ ВАЖНО: Этот раздел - самый ценный. Здесь разобраны реальные ошибки которые могли сломать production. Изучите внимательно!
2.1 ОШИБКА #1: Host Mode vs Docker Network (ФАТАЛЬНАЯ!)
❌ Что было неправильно (Version 1.0):
# docker-compose.yml (НЕПРАВИЛЬНО!)
services:
tengine:
network_mode: host # ← ФАТАЛЬНАЯ ОШИБКА!
networks:
kodalinet:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
🔥 Почему это фатально:
-
Docker не запустится:
$ docker compose up -d ERROR: network_mode and networks cannot be used together -
Tengine НЕ будет в сети kodalinet:
- Host mode ИЗОЛИРУЕТ контейнер от Docker networks
- Tengine видит ТОЛЬКО host network stack
- Не может резолвить container names (my-app:8080)
-
Требование клиента НЕ выполнено:
- Клиент: "всё в одной сети kodalinet"
- Реальность: tengine в host network, остальные в kodalinet
✅ Правильное решение (Version 2.0):
# docker-compose.yml (ПРАВИЛЬНО!)
services:
tengine:
# Убираем network_mode: host
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
networks:
kodalinet:
ipv4_address: 172.20.0.3
networks:
kodalinet:
external: true # Сеть создана заранее!
📊 Сравнение подходов:
| Аспект | Host Mode | Bridge Mode (правильно) |
|---|---|---|
| Совместимость с networks | ❌ НЕТ | ✅ ДА |
| Docker DNS (container names) | ❌ НЕ работает | ✅ Работает |
| Port mapping | Не нужен | Нужен (80:80, 443:443) |
| Производительность | 100% | ~95% (минимальный overhead) |
| Изоляция | Нет | Есть |
| Best Practice | ⚠️ Редко | ✅ Стандарт |
🎓 Урок:
Host mode и custom networks - НЕСОВМЕСТИМЫ!
Если видите network_mode: host в примере - это НЕ значит что это единственный способ. В нашем случае bridge mode лучше потому что:
- Совместим с kodalinet
- Позволяет использовать container names
- Изолирует tengine от хоста
2.2 ОШИБКА #2: Отсутствие Resource Limits (КРИТИЧНО!)
❌ Что было неправильно:
# НЕТ resource limits = production катастрофа!
postgres:
image: postgres:15.2
# ... БЕЗ deploy.resources
🔥 Что может пойти не так:
Сценарий 1: PostgreSQL runaway query
-- Кто-то запустил тяжёлый запрос
SELECT * FROM attack_logs
JOIN sites ON ...
WHERE date > '2020-01-01';
-- PostgreSQL начинает жрать RAM...
-- 1GB... 2GB... 4GB... 8GB... 16GB...
-- Host OOM Killer: "Убиваю случайный процесс!"
-- *убивает Docker daemon*
-- ВСЕ контейнеры падают! 💥
Сценарий 2: DDoS атака
-- 10,000 req/sec на сервер
-- Tengine пытается обработать все
-- CPU usage: 100% на всех cores
-- Другие контейнеры не получают CPU
-- Весь сервер тормозит
-- SSH не отвечает!
✅ Правильное решение:
postgres:
deploy:
resources:
limits:
cpus: '2.0' # Максимум 2 CPU cores
memory: 2G # Максимум 2GB RAM
reservations:
cpus: '0.5' # Гарантированно 0.5 CPU
memory: 512M # Гарантированно 512MB
📊 Рекомендуемые limits:
| Сервис | CPU Limit | RAM Limit | Обоснование |
|---|---|---|---|
| tengine | 4.0 | 4G | Обрабатывает ВСЕ HTTP |
| detector | 2.0 | 2G | ML анализ = CPU intensive |
| postgres | 2.0 | 2G | 600 connections * 10MB |
| mgt | 1.0 | 1G | Web UI, средняя нагрузка |
| luigi | 1.0 | 1G | Обработка логов |
| fvm | 0.5 | 512M | Лёгкий сервис |
| chaos | 0.5 | 512M | Лёгкий сервис |
ИТОГО: ~11 CPU, ~12GB RAM (пик)
Сервер: Минимум 16 CPU, 32GB RAM
🎓 Урок:
В production БЕЗ resource limits = тикающая бомба!
Один runaway процесс может убить весь хост. Всегда устанавливайте limits.
2.3 ОШИБКА #3: Ulimits для Tengine (КРИТИЧНО!)
❌ Что было неправильно:
tengine:
# ... БЕЗ ulimits
🔥 Что происходит под нагрузкой:
# 1000 requests/second приходит на сервер
# Каждый request = открытый TCP socket = file descriptor
# Linux по умолчанию: ulimit -n = 1024
# Tengine открывает:
# - 1000 connections = 1000 files
# - Nginx logs = 2 files
# - Config files = ~10 files
# ИТОГО: 1012 открытых файлов
# При 1013-м соединении:
$ curl https://your-site.com
curl: (56) Recv failure: Connection reset by peer
# В логах tengine:
[error] accept() failed (24: Too many open files)
# Сайт НЕДОСТУПЕН! 💥
✅ Правильное решение:
tengine:
ulimits:
nofile:
soft: 65536
hard: 131072
📊 Как выбрать значение:
Формула: ulimit >= (max_connections * 2) + buffer
Пример расчёта:
- Ожидаемая нагрузка: 5000 req/sec
- Среднее время обработки: 100ms
- Одновременных соединений: 5000 * 0.1 = 500
- С запасом x2: 500 * 2 = 1000
- Nginx служебные файлы: +100
- Буфер безопасности x10: (1000 + 100) * 10 = 11,000
- Округляем до степени 2: 16,384
Но проще использовать стандартные значения:
- 65,536 (64K) - для большинства случаев
- 131,072 (128K) - для высоконагруженных систем
🎓 Урок:
"Too many open files" - частая причина production инцидентов!
Проверьте ulimits ПЕРЕД деплоем, не после падения сайта в 3 часа ночи.
2.4 ОШИБКА #4: MGT порт открыт наружу (SECURITY!)
❌ Что было неправильно:
mgt:
ports:
- "9443:1443" # Доступен из интернета! 😱
🔥 Последствия:
# Атакующий сканирует порты:
$ nmap your-server.com
PORT STATE SERVICE
80/tcp open http
443/tcp open https
9443/tcp open unknown # ← Нашли админку!
# Пробует дефолтные пароли:
$ curl -k https://your-server.com:9443/api/login \
-d '{"username":"admin","password":"admin"}'
# Или эксплойты:
$ searchsploit "SafeLine"
$ metasploit> use exploit/safeline_rce_2024
# Результат: ПОЛНАЯ КОМПРОМЕТАЦИЯ WAF
# Атакующий может:
# - Отключить защиту
# - Добавить свои правила
# - Видеть весь траффик
# - Украсть сертификаты
✅ Правильное решение:
Вариант A: Internal only (рекомендуется)
mgt:
expose:
- "1443" # Доступен ТОЛЬКО внутри Docker network
# БЕЗ ports!
Доступ через SSH tunnel:
# На своём компьютере:
ssh -L 9443:localhost:1443 user@server
# Затем открыть: https://localhost:9443
Вариант B: Localhost only
mgt:
ports:
- "127.0.0.1:9443:1443" # Только с localhost
Вариант C: С firewall (если нужен прямой доступ)
mgt:
ports:
- "9443:1443"
# Но ОБЯЗАТЕЛЬНО:
sudo ufw allow from YOUR_OFFICE_IP to any port 9443
sudo ufw deny 9443 # Запретить всем остальным
🎓 Урок:
Админ-панели НИКОГДА не должны быть публичными!
Клиент сказал: "порты закрыты, открыт только 80/443" - это включает и MGT порт.
2.5 ОШИБКА #5: External Network (BEST PRACTICE)
❌ Что было неправильно:
networks:
kodalinet:
name: kodalinet
driver: bridge
ipam:
driver: default
config:
- gateway: 172.20.0.1
subnet: 172.20.0.0/24
⚠️ Проблемы:
-
Сеть пересоздаётся:
$ docker-compose down # Сеть kodalinet удалена! $ docker-compose up -d # Сеть kodalinet создана заново # IP адреса могут измениться! -
Другие сервисы не могут подключиться:
# Хочу добавить Portainer в эту же сеть $ docker run -d --network kodalinet portainer ERROR: network kodalinet not found # Приходится редактировать safeline docker-compose.yml 😞 -
Не соответствует NPM best practice:
- Клиент привёл пример из блога про NPM
- Там используется
external: true
✅ Правильное решение:
Шаг 1: Создать сеть заранее
docker network create \
--driver bridge \
--subnet 172.20.0.0/24 \
--gateway 172.20.0.1 \
--opt com.docker.network.bridge.name=kodalinet \
kodalinet
Шаг 2: Использовать external в compose
networks:
kodalinet:
external: true # Сеть уже существует!
📊 Преимущества external network:
| Аспект | Internal | External |
|---|---|---|
| Создаётся | При compose up | Заранее вручную |
| Удаляется | При compose down | Никогда |
| IP стабильность | ⚠️ Могут меняться | ✅ Стабильные |
| Другие сервисы | ❌ Сложно добавить | ✅ Просто |
| NPM pattern | ❌ | ✅ |
🎓 Урок:
Для production используйте external networks!
Это стандартный паттерн из NPM best practices. Сеть создаётся один раз и живёт независимо от compose файлов.
2.6 ОШИБКА #6: SSL Renewal не автоматизирован
❌ Что было неправильно:
Упомянул certbot, НО:
- ❌ Нет готового скрипта
- ❌ Нет интеграции с SafeLine
- ❌ Нет cron настройки
🔥 Что происходит:
День 1: Получили SSL сертификат ✅
День 30: Всё работает ✅
День 60: Всё работает ✅
День 89: Всё работает ✅
День 90: Сертификат истёк! 💥
Браузеры блокируют сайт
Клиенты не могут зайти
3:00 субботы, все спят
Убытки компании растут!
День 91: DevOps проснулся 😴
Обновил сертификат вручную
Post-mortem: "Забыли настроить renewal"
✅ Правильное решение:
Полная автоматизация с 3 компонентами:
1. SafeLine file-watch (встроенный механизм)
- SafeLine v7.2.0+ проверяет файлы каждый час
- При изменении сертификата - автоматически применяет
- БЕЗ рестарта контейнера!
2. Certbot renewal script
#!/bin/bash
# Обновляет сертификат через certbot
# Копирует в /app/safeline/resources/nginx/certs/
# SafeLine подхватывает автоматически
3. Cron job
# Каждый день в 3:00
0 3 * * * /usr/local/bin/safeline-ssl-renew
🎓 Урок:
SSL renewal ДОЛЖЕН быть автоматизирован на 100%!
Человеческий фактор + истечение сертификата = production outage
2.7 Итоговая таблица ошибок
| # | Ошибка | Tier | Последствия | Исправлено |
|---|---|---|---|---|
| 1 | Host mode + network | S | НЕ ЗАПУСТИТСЯ | ✅ Bridge mode |
| 2 | Нет resource limits | A | OOM Killer | ✅ Везде добавлены |
| 3 | Нет ulimits | A | "Too many files" | ✅ 131072 для tengine |
| 4 | MGT порт открыт | B | Security breach | ✅ Internal only |
| 5 | Network не external | B | Сложность поддержки | ✅ External |
| 6 | SSL не автоматизирован | A | Сайт упадёт через 90 дней | ✅ Скрипт + cron |
| 7 | Нет healthchecks | C | Плохой мониторинг | ✅ Везде добавлены |
| 8 | Логи не оптимизированы | C | Забьют диск | ✅ Правильная ротация |
3. Системные требования
3.1 Минимальные требования
┌─────────────────────────────────────────┐
│ Минимум для запуска (1-10 сайтов) │
├─────────────────────────────────────────┤
│ CPU: 4 cores (x86_64 or ARM64) │
│ RAM: 8 GB │
│ Disk: 50 GB SSD │
│ Network: 100 Mbps │
│ OS: Ubuntu 22.04 / Debian 12 │
├─────────────────────────────────────────┤
│ ⚠️ Под нагрузкой будет тормозить! │
└─────────────────────────────────────────┘
3.2 Рекомендуемые требования
┌─────────────────────────────────────────┐
│ Рекомендуется для production │
│ (10-100 сайтов, 10K req/sec) │
├─────────────────────────────────────────┤
│ CPU: 8+ cores │
│ RAM: 16 GB (32 GB лучше) │
│ Disk: 100 GB NVMe SSD │
│ Network: 1 Gbps │
│ OS: Ubuntu 24.04 / Debian 13 │
├─────────────────────────────────────────┤
│ ✅ Комфортная работа │
└─────────────────────────────────────────┘
3.3 High-load требования
┌─────────────────────────────────────────┐
│ High-load (100+ сайтов, 100K req/sec) │
├─────────────────────────────────────────┤
│ CPU: 16-32 cores │
│ RAM: 64 GB │
│ Disk: 500 GB NVMe SSD (RAID 1) │
│ Network: 10 Gbps │
│ OS: Ubuntu 24.04 LTS │
├─────────────────────────────────────────┤
│ + Load Balancer (несколько серверов) │
│ + Отдельный сервер для PostgreSQL │
│ + Redis для кэша │
└─────────────────────────────────────────┘
3.4 Проверка системы
Запустите этот скрипт для проверки:
#!/bin/bash
# system-check.sh
echo "=== SafeLine System Requirements Check ==="
echo ""
# CPU
CPU_CORES=$(nproc)
echo "CPU Cores: $CPU_CORES"
if [ $CPU_CORES -ge 8 ]; then
echo " ✅ GOOD (8+ cores)"
elif [ $CPU_CORES -ge 4 ]; then
echo " ⚠️ MINIMAL (4+ cores, может тормозить)"
else
echo " ❌ INSUFFICIENT (нужно минимум 4 cores)"
fi
# RAM
TOTAL_RAM=$(free -g | grep Mem | awk '{print $2}')
echo ""
echo "RAM: ${TOTAL_RAM}GB"
if [ $TOTAL_RAM -ge 16 ]; then
echo " ✅ GOOD (16+ GB)"
elif [ $TOTAL_RAM -ge 8 ]; then
echo " ⚠️ MINIMAL (8+ GB, может не хватить)"
else
echo " ❌ INSUFFICIENT (нужно минимум 8 GB)"
fi
# Disk
DISK_AVAIL=$(df -BG / | tail -1 | awk '{print $4}' | sed 's/G//')
echo ""
echo "Available Disk: ${DISK_AVAIL}GB"
if [ $DISK_AVAIL -ge 100 ]; then
echo " ✅ GOOD (100+ GB)"
elif [ $DISK_AVAIL -ge 50 ]; then
echo " ⚠️ MINIMAL (50+ GB)"
else
echo " ❌ INSUFFICIENT (нужно минимум 50 GB)"
fi
# Docker
echo ""
echo "Docker:"
if command -v docker &> /dev/null; then
DOCKER_VERSION=$(docker --version | grep -oP '\d+\.\d+\.\d+' | head -1)
echo " Version: $DOCKER_VERSION"
if [[ $(echo -e "24.0.0\n$DOCKER_VERSION" | sort -V | head -n1) == "24.0.0" ]]; then
echo " ✅ GOOD (24.0+)"
else
echo " ⚠️ OLD (рекомендуется >= 24.0)"
fi
else
echo " ❌ NOT INSTALLED"
fi
# Docker Compose
echo ""
echo "Docker Compose:"
if docker compose version &> /dev/null; then
COMPOSE_VERSION=$(docker compose version | grep -oP '\d+\.\d+\.\d+' | head -1)
echo " Version: $COMPOSE_VERSION"
echo " ✅ INSTALLED"
else
echo " ❌ NOT INSTALLED"
fi
echo ""
echo "=== Check Complete ==="
Сохраните как system-check.sh и запустите:
chmod +x system-check.sh
./system-check.sh
4. Подготовка инфраструктуры
🎯 Цель этапа: Подготовить сервер к установке SafeLine
4.1 Установка Docker и Docker Compose
Для Ubuntu 22.04/24.04:
# 1. Обновляем систему
sudo apt update && sudo apt upgrade -y
# 2. Удаляем старые версии Docker (если есть)
sudo apt remove docker docker-engine docker.io containerd runc
# 3. Устанавливаем зависимости
sudo apt install -y \
ca-certificates \
curl \
gnupg \
lsb-release
# 4. Добавляем GPG ключ Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 5. Добавляем репозиторий Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 6. Устанавливаем Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# 7. Добавляем пользователя в группу docker
sudo usermod -aG docker $USER
# 8. Применяем изменения (или перелогинимся)
newgrp docker
# 9. Проверяем установку
docker --version
docker compose version
Для Debian 12/13:
# Аналогично Ubuntu, но используем:
curl -fsSL https://download.docker.com/linux/debian/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Затем:
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
4.2 Проверка портов
КРИТИЧЕСКИ ВАЖНО: Порты 80 и 443 должны быть свободны!
# Проверяем какие порты заняты
sudo netstat -tlnp | grep -E ':80|:443'
# Или с помощью ss:
sudo ss -tlnp | grep -E ':80|:443'
Если порты заняты:
Nginx:
sudo systemctl stop nginx
sudo systemctl disable nginx # Чтобы не запускался при reboot
Apache:
sudo systemctl stop apache2
sudo systemctl disable apache2
Docker контейнер:
# Найти контейнер
docker ps | grep -E ':80|:443'
# Остановить
docker stop <container-name>
4.3 Создание Docker network
⚠️ ВАЖНО: Сеть создаётся ПЕРЕД запуском docker-compose!
# Создаём external network
docker network create \
--driver bridge \
--subnet 172.20.0.0/24 \
--gateway 172.20.0.1 \
--opt com.docker.network.bridge.name=kodalinet \
kodalinet
Проверка создания:
# Проверяем что сеть создана
docker network ls | grep kodalinet
# Смотрим детали
docker network inspect kodalinet
Ожидаемый вывод:
[
{
"Name": "kodalinet",
"Driver": "bridge",
"Scope": "local",
"IPAM": {
"Config": [
{
"Subnet": "172.20.0.0/24",
"Gateway": "172.20.0.1"
}
]
}
}
]
4.4 Создание директорий
# Создаём базовую директорию
sudo mkdir -p /app/safeline
# Создаём структуру поддиректорий
sudo mkdir -p /app/safeline/{resources,logs,backups}
sudo mkdir -p /app/safeline/resources/{postgres/data,mgt,nginx,detector,chaos,cache,sock,luigi}
sudo mkdir -p /app/safeline/resources/nginx/{certs,conf.d}
sudo mkdir -p /app/safeline/logs/{nginx,detector}
# Права доступа
sudo chown -R $USER:$USER /app/safeline
chmod -R 755 /app/safeline
# Специальные права
chmod 700 /app/safeline/resources/postgres/data
chmod 700 /app/safeline/backups
Проверка структуры:
tree -L 3 /app/safeline
Ожидаемая структура:
/app/safeline/
├── backups/
├── logs/
│ ├── detector/
│ └── nginx/
└── resources/
├── cache/
├── chaos/
├── detector/
├── luigi/
├── mgt/
├── nginx/
│ ├── certs/
│ └── conf.d/
├── postgres/
│ └── data/
└── sock/
4.5 Настройка Firewall (UFW)
# Установка UFW (если не установлен)
sudo apt install ufw -y
# Разрешаем SSH (КРИТИЧНО! Иначе потеряете доступ)
sudo ufw allow 22/tcp
# Разрешаем HTTP и HTTPS
sudo ufw allow 80/tcp comment 'SafeLine HTTP'
sudo ufw allow 443/tcp comment 'SafeLine HTTPS'
# Включаем UFW
sudo ufw enable
# Проверяем статус
sudo ufw status verbose
Ожидаемый вывод:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
80/tcp (SafeLine HTTP) ALLOW Anywhere
443/tcp (SafeLine HTTPS) ALLOW Anywhere
⚠️ MGT порт (9443) - НЕ открываем!
Доступ только через SSH tunnel (см. раздел 5.6)
[Статья продолжается... Это первая часть. Создам остальные разделы в следующих файлах]
Навигация по статье
📖 Вы здесь: Часть 1 - Введение, ошибки, требования, подготовка
📖 Далее: Часть 2 - Установка, конфигурация, SSL
📖 Далее: Часть 3 - Backend сервисы, мониторинг, troubleshooting
Следующий файл:
BOOKSTACK_ARTICLE_PART2.md(установка и конфигурация)

No comments to display
No comments to display