bolt Valebyte VPS от $4/мес — NVMe, запуск за 60 секунд.

Получить VPS arrow_forward
eco Начальный Туториал

Установка BunkerWeb WAF на VPS: защита сайтов, SSL, Docker и CrowdSec

calendar_month Oct 25, 2026 schedule 19 мин. чтения visibility 31 просмотров
Установка BunkerWeb WAF на VPS: защита сайтов, SSL, Docker и CrowdSec
info

Нужен сервер для этого гайда? Мы предлагаем выделенные серверы и VPS в 50+ странах с мгновенной настройкой.

Нужен сервер для этого гайда?

Разверните VPS или выделенный сервер за минуты.

Установка BunkerWeb WAF на VPS: защита сайтов, SSL, Docker и CrowdSec

TL;DR

BunkerWeb — это веб-файрволл с обратным прокси, который размещается перед сайтами, принимает HTTPS-трафик, применяет правила WAF и передаёт запросы приложениям. В этом руководстве мы установим BunkerWeb в Docker на Ubuntu Server 24.04 LTS, подключим сайт через reverse proxy, настроим автоматический TLS Let's Encrypt, базовую защиту от ботов и интеграцию с CrowdSec.

  • Используем Ubuntu Server 24.04 LTS, Docker Engine 28.x и Docker Compose v2.
  • BunkerWeb будет единственной публичной точкой входа на портах 80 и 443.
  • Приложение останется во внутренней Docker-сети и не будет напрямую доступно из интернета.
  • Сертификаты Let's Encrypt будут выпускаться и продлеваться автоматически.
  • CrowdSec будет анализировать логи и блокировать IP-адреса с плохой репутацией.
  • Конфигурации, секреты и данные будут вынесены в отдельные файлы и включены в резервное копирование.

3. Что мы настраиваем и зачем

Схема: 3. Что мы настраиваем и зачем
Схема: 3. Что мы настраиваем и зачем

Обычная схема публикации сайта выглядит так: интернет-клиент обращается непосредственно к веб-серверу приложения. Если приложение содержит уязвимость, неправильно обрабатывает запросы или подвергается перебору паролей, атака доходит до него без дополнительного фильтра. BunkerWeb меняет эту архитектуру: он становится обратным прокси и WAF между клиентом и приложением.

WAF, или Web Application Firewall, анализирует HTTP-запросы до передачи их на backend. Он может отбрасывать подозрительные URI, попытки SQL-инъекций, XSS, обхода каталогов, автоматизированный перебор и другие типовые атаки. Это не заменяет обновление CMS, фреймворка и операционной системы, но уменьшает поверхность атаки и добавляет отдельный защитный слой.

Итоговая схема

Интернет
    |
    | TCP 80/443
    v
[BunkerWeb WAF]
    |
    | внутренняя Docker-сеть
    v
[web-приложение: nginx, Node.js, PHP-FPM, контейнер SaaS]
    |
    v
[База данных и хранилище]

В нашем примере будет домен example.com, а приложение будет доступно внутри Docker по имени app на порту 8080. Замените этот домен и параметры на свои. DNS-записи должны указывать на публичный IPv4-адрес сервера ещё до выпуска сертификата.

Что получится после настройки

  • Порты приложения не публикуются через Docker на внешний интерфейс.
  • HTTP-запросы принимаются BunkerWeb, а HTTPS-сертификат обслуживается автоматически.
  • Для сайта включаются базовые правила ModSecurity/OWASP CRS через шаблон BunkerWeb.
  • Логи запросов сохраняются в Docker volume и доступны для анализа CrowdSec.
  • Системный firewall разрешает только SSH, HTTP и HTTPS.
  • Обновление контейнеров и резервное копирование можно выполнять независимо от приложения.

Self-hosted или облачный WAF

Облачные WAF-сервисы принимают трафик на своей стороне и проксируют его на origin-сервер. Это удобно при больших объёмах, распределённой защите от DDoS и необходимости минимизировать собственное обслуживание. Однако придётся передать DNS и часть сетевого контроля внешнему оператору, а стоимость и ограничения зависят от тарифа.

Self-hosted BunkerWeb подходит, когда нужен полный контроль над конфигурацией, логами и местом обработки данных. Владелец VPS сам отвечает за обновления, доступность, резервное копирование и защиту origin. Для одного или нескольких сайтов на небольшом сервере такой вариант обычно проще и прозрачнее, чем самостоятельная сборка Nginx, ModSecurity, rate limiting и отдельного сервиса управления сертификатами.

Важно понимать границы решения: BunkerWeb не является полноценной защитой от мощной volumetric DDoS-атаки, не исправляет уязвимости приложения и не заменяет контроль доступа к административным панелям. Для критичного сервиса нужны мониторинг, отдельные резервные копии и план восстановления.

4. Какой VPS-конфиг нужен под эту задачу

Схема: 4. Какой VPS-конфиг нужен под эту задачу
Схема: 4. Какой VPS-конфиг нужен под эту задачу

BunkerWeb работает как reverse proxy, поэтому его требования зависят не только от самого WAF, но и от количества сайтов, размера запросов, TLS-нагрузки, включённых правил и производительности backend. Для одного небольшого сайта WAF потребляет мало ресурсов, но запас RAM нужен Docker, CrowdSec, журналированию и обновлениям.

Сценарий CPU RAM Диск Сеть
Тестовый сайт 1 vCPU 2 ГБ 25 ГБ SSD 100 Мбит/с
Небольшой production-сайт 2 vCPU 4 ГБ 40–60 ГБ NVMe 100–500 Мбит/с
Несколько сайтов и CrowdSec 4 vCPU 8 ГБ 80–120 ГБ NVMe 500 Мбит/с и выше

Минимальная практичная конфигурация для production — 2 vCPU, 4 ГБ RAM и 40 ГБ SSD. Если на том же VPS будут работать база данных, CMS, CI/CD, панель управления или несколько приложений, лучше сразу взять 4 vCPU и 8 ГБ RAM. Для Docker полезно оставить не менее 1 ГБ свободной памяти после запуска всех контейнеров.

В качестве конкретного варианта можно взять подходящий VPS с 2–4 vCPU, 4–8 ГБ RAM, NVMe-диском от 40 ГБ и публичным IPv4. Проверьте, что провайдер разрешает входящие соединения на TCP 80 и 443, предоставляет консоль восстановления и позволяет делать снимки или подключать внешнее хранилище.

Когда нужен dedicated

Выделенный сервер оправдан, если через WAF проходит большой постоянный поток запросов, нужно несколько десятков сайтов, выполняется тяжёлое TLS-шифрование или на машине размещаются ресурсоёмкие backend-сервисы. Dedicated также удобен для требований к гарантированным IOPS, изоляции от соседей и собственного сетевого оборудования.

Для одного сайта, панели администрирования, API или небольшой команды dedicated обычно избыточен. Сначала измерьте загрузку CPU, RAM, диска и сети. Если средняя загрузка ниже 50%, а пики не приводят к swap и задержкам, переход на физический сервер не даст заметной пользы.

Выбор локации

Локация влияет на задержку между посетителем и WAF, маршрут до backend и требования к хранению данных. Выбирайте регион, близкий к основной аудитории, но учитывайте доступность IPv4, качество каналов и правила обработки персональных данных. Если приложение и база находятся в разных регионах, задержка между ними может стать заметнее, чем задержка от пользователя до WAF.

5. Подготовка сервера

Схема: 5. Подготовка сервера
Схема: 5. Подготовка сервера

Ниже предполагается чистый VPS с Ubuntu Server 24.04 LTS и доступом под пользователем root. Все команды выполняются на сервере. Подставьте свой публичный SSH-ключ вместо примера и не отключайте текущую SSH-сессию до проверки нового пользователя.

Создание пользователя и установка SSH-ключа

# Создаём отдельного администратора
adduser deploy

# Добавляем его в группу sudo
usermod -aG sudo deploy

# Создаём каталог для SSH-ключей
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh

# Добавляем публичный ключ; замените значение на свой ключ
printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... admin@workstation' \
  > /home/deploy/.ssh/authorized_keys

# Исправляем владельца и права
chown deploy:deploy /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys

Проверьте вход в отдельном окне терминала:

# Выполняется на локальном компьютере
ssh deploy@SERVER_IP

После успешной проверки можно запретить вход root и авторизацию по паролю. Перед этим убедитесь, что ключ работает, а в панели провайдера доступна web-консоль:

# Открываем конфигурацию SSH
sudoedit /etc/ssh/sshd_config.d/ hardening.conf

В команде выше не должно быть пробела в имени файла. Используйте корректный вариант:

# Создаём отдельный файл настроек SSH
sudo tee /etc/ssh/sshd_config.d/hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
AllowUsers deploy
EOF

# Проверяем синтаксис перед перезапуском
sudo sshd -t

# Применяем настройки SSH
sudo systemctl reload ssh

Обновление системы и базовые пакеты

# Обновляем индекс репозиториев и пакеты Ubuntu
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt full-upgrade -y

# Устанавливаем утилиты для администрирования и репозиториев
sudo apt install -y \
  ca-certificates curl gnupg jq git unzip vim htop tmux \
  ufw fail2ban unattended-upgrades apt-transport-https

# Перезагружаем сервер, если обновлялось ядро
sudo reboot

Firewall и Fail2ban

Откройте SSH до включения UFW. Если SSH работает на другом порту, замените правило 22/tcp. Порты 80 и 443 будут нужны BunkerWeb для HTTP и HTTPS.

# Разрешаем SSH, HTTP и HTTPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Включаем политику запрета входящих соединений
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Включаем firewall
sudo ufw --force enable

# Проверяем активные правила
sudo ufw status verbose

Fail2ban защитит SSH от простого перебора. BunkerWeb и CrowdSec будут отвечать за веб-трафик, поэтому не нужно бездумно добавлять десятки фильтров и блокировать легитимных пользователей.

# Включаем стандартную защиту SSH
sudo systemctl enable --now fail2ban

# Проверяем состояние jail
sudo fail2ban-client status
sudo fail2ban-client status sshd

6. Установка ПО — пошагово

В 2026 году используйте Docker Engine из официального репозитория Docker, а не устаревший пакет из базового репозитория Ubuntu. Версию BunkerWeb лучше фиксировать на конкретном стабильном теге серии 1.6.x, а не использовать latest. Перед production-развёртыванием проверьте актуальный стабильный тег в официальной документации проекта и замените значение переменной BUNKERWEB_VERSION.

Шаг 1. Установка Docker Engine

# Удаляем конфликтующие пакеты старых Docker-реализаций
sudo apt remove -y docker.io docker-doc docker-compose podman-docker containerd runc || true

# Создаём каталог ключей APT
sudo install -m 0755 -d /etc/apt/keyrings

# Загружаем официальный ключ Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Разрешаем APT читать ключ
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Добавляем официальный репозиторий Docker для Ubuntu 24.04
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu noble stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Устанавливаем Docker Engine и Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# Запускаем Docker после загрузки системы
sudo systemctl enable --now docker

# Проверяем версии
docker --version
docker compose version

Не добавляйте пользователя в группу docker без необходимости: участник этой группы фактически получает права root. В дальнейшем команды Docker выполняйте через sudo или осознанно примите этот риск.

Шаг 2. Создание каталога проекта

# Создаём каталог конфигурации BunkerWeb
sudo install -d -m 750 -o deploy -g deploy /opt/bunkerweb

# Переключаемся на администратора проекта
sudo -iu deploy

# Переходим в рабочий каталог
cd /opt/bunkerweb

# Создаём каталоги для данных и логов
mkdir -p data logs backups

Шаг 3. Создание файла секретов

# Создаём файл переменных окружения с закрытыми правами
touch /opt/bunkerweb/.env
chmod 600 /opt/bunkerweb/.env

# Генерируем случайный пароль для административной базы
openssl rand -base64 32

Сохраните результат в менеджере паролей. Позже этот пароль будет использоваться только для внутренних сервисов. Не публикуйте файл .env в Git и не вставляйте реальные секреты в compose-файл.

Шаг 4. Подготовка Docker Compose

Для простой установки мы используем BunkerWeb и scheduler, а отдельное приложение представляем контейнером app. В production вместо демонстрационного образа поставьте свой backend. BunkerWeb должен находиться в той же Docker-сети, что и приложение.

# Переходим в каталог проекта
cd /opt/bunkerweb

# Создаём compose-файл
cat > compose.yml <<'EOF'
services:
  bunkerweb:
    image: bunkerity/bunkerweb:${BUNKERWEB_VERSION}
    restart: unless-stopped
    ports:
      - "80:8080"
      - "443:8443"
    environment:
      SERVER_NAME: "${SERVER_NAME}"
      MULTISITE: "yes"
      HTTP_PORT: "8080"
      HTTPS_PORT: "8443"
      DISABLE_DEFAULT_SERVER: "yes"
      AUTO_LETS_ENCRYPT: "yes"
      EMAIL_LETS_ENCRYPT: "${LETSENCRYPT_EMAIL}"
      USE_REVERSE_PROXY: "yes"
      REVERSE_PROXY_URL: "http://app:8080"
      USE_MODSECURITY: "yes"
      USE_ANTIBOT: "yes"
      ANTIBOT_METHOD: "cookie"
      LOG_FORMAT: "json"
    volumes:
      - bunkerweb_data:/data
      - bunkerweb_logs:/var/log/bunkerweb
    networks:
      - edge
    depends_on:
      - app

  app:
    image: traefik/whoami:v1.10
    restart: unless-stopped
    expose:
      - "80"
    networks:
      - edge

networks:
  edge:

volumes:
  bunkerweb_data:
  bunkerweb_logs:
EOF

Демонстрационный контейнер whoami слушает порт 80, поэтому значение REVERSE_PROXY_URL в реальном compose-файле нужно заменить на http://app:80. Это важно: имя сервиса и порт должны совпадать с фактическим адресом backend.

Шаг 5. Запуск контейнеров

# Загружаем переменные и проверяем итоговую модель Compose
cd /opt/bunkerweb
sudo docker compose --env-file .env config

# Скачиваем образы
sudo docker compose --env-file .env pull

# Запускаем BunkerWeb и backend
sudo docker compose --env-file .env up -d

# Проверяем состояние контейнеров
sudo docker compose ps

# Просматриваем последние сообщения BunkerWeb
sudo docker compose logs --tail=100 bunkerweb

Шаг 6. Установка CrowdSec

CrowdSec состоит из анализатора поведения и компонента принятия решения. Он читает логи, сопоставляет события с сценариями и создаёт решения о блокировке IP. В этой схеме BunkerWeb пишет JSON-логи в volume, а CrowdSec устанавливается на хосте. Для production удобнее монтировать лог в отдельный каталог, доступный только для чтения агенту CrowdSec.

# Добавляем официальный репозиторий CrowdSec
curl -fsSL https://packagecloud.io/crowdsec/crowdsec/gpgkey \
  | sudo gpg --dearmor -o /usr/share/keyrings/crowdsec.gpg

echo "deb [signed-by=/usr/share/keyrings/crowdsec.gpg] \
https://packagecloud.io/crowdsec/crowdsec/ubuntu/ noble main" \
  | sudo tee /etc/apt/sources.list.d/crowdsec.list > /dev/null

# Устанавливаем CrowdSec
sudo apt update
sudo apt install -y crowdsec

# Включаем сервис
sudo systemctl enable --now crowdsec

# Проверяем состояние
sudo systemctl status crowdsec --no-pager
sudo cscli version

Установите коллекции для веб-сервера и Linux. Названия коллекций могут меняться, поэтому сначала выполните поиск:

# Обновляем индекс коллекций
sudo cscli hub update

# Ищем доступные коллекции nginx и базовую Linux-коллекцию
sudo cscli collections list | grep -E 'nginx|linux'

# Устанавливаем подходящие коллекции
sudo cscli collections install crowdsecurity/linux
sudo cscli collections install crowdsecurity/nginx

# Перезапускаем анализатор
sudo systemctl restart crowdsec

На следующем этапе нужно указать CrowdSec реальный путь к логам BunkerWeb. Если используется Docker volume, сначала определите его точку монтирования:

# Показываем имя volume с логами
sudo docker volume ls | grep bunkerweb

# Получаем путь volume на хосте
sudo docker volume inspect bunkerweb_bunkerweb_logs

Путь из поля Mountpoint добавьте в конфигурацию источника CrowdSec. Конкретные имена лог-файлов зависят от версии и шаблона BunkerWeb, поэтому сначала найдите их:

# Показываем файлы логов внутри контейнера
sudo docker compose exec bunkerweb sh -c 'find /var/log/bunkerweb -maxdepth 2 -type f -print'

# Проверяем наличие событий
sudo docker compose logs --since=10m bunkerweb

7. Конфигурация

Файл переменных окружения

Создайте /opt/bunkerweb/.env. Здесь нет секретов приложения, но файл всё равно должен быть закрыт от других пользователей. Для примера используется стабильная ветка BunkerWeb 1.6.x; перед установкой проверьте актуальный patch-релиз.

# Записываем основные переменные проекта
cat > /opt/bunkerweb/.env <<'EOF'
BUNKERWEB_VERSION=1.6
SERVER_NAME=example.com
[email protected]
EOF

# Запрещаем чтение файла другим пользователям
chmod 600 /opt/bunkerweb/.env

# Проверяем, что переменные подставляются
sudo docker compose --env-file .env config | sed -n '1,120p'

Для нескольких сайтов в BunkerWeb включается multisite-режим. В зависимости от выбранного шаблона отдельные параметры задаются через переменные с префиксом имени сайта или через UI/API. Не копируйте конфигурацию одного сайта на другой без проверки доменных имён и upstream-адресов.

Проверка DNS и портов

# Проверяем DNS-запись с локального компьютера
dig +short A example.com

# Проверяем, что сервер слушает HTTP и HTTPS
sudo ss -lntp | grep -E ':80|:443'

# Проверяем HTTP-ответ по IP или домену
curl -I http://example.com

# Проверяем HTTPS и цепочку сертификата
curl -Iv https://example.com

Для выпуска Let's Encrypt домен должен разрешаться в публичный IPv4-адрес VPS, а TCP 80 должен быть доступен из интернета. Если используется AAAA-запись, убедитесь, что IPv6 действительно настроен на сервере и firewall разрешает нужные порты. Иначе временно удалите неверную AAAA-запись или настройте IPv6 полностью.

Проверка reverse proxy

# Проверяем backend из контейнера BunkerWeb
sudo docker compose exec bunkerweb sh -c \
  'wget -qO- http://app:80 || true'

# Проверяем сетевые подключения контейнеров
sudo docker network inspect bunkerweb_edge

# Смотрим последние ошибки проксирования
sudo docker compose logs --since=15m bunkerweb | \
  grep -Ei 'error|upstream|certificate|failed'

Если в ответе backend видны служебные заголовки, это нормально для тестового контейнера. В production передавайте приложению исходный протокол и адрес клиента. BunkerWeb обычно формирует стандартные прокси-заголовки, но приложение должно быть настроено доверять им только от адреса reverse proxy, а не от произвольного клиента.

Настройка ограничений запросов

Rate limiting особенно полезен для страниц входа, API и восстановления пароля. Не задавайте агрессивные глобальные ограничения: они могут заблокировать NAT-пользователей, мобильные сети и поисковых роботов. Начните с умеренного лимита и наблюдайте логи.

# Просматриваем доступные переменные BunkerWeb в установленном образе
sudo docker run --rm bunkerity/bunkerweb:${BUNKERWEB_VERSION} \
  sh -c 'env | sort | grep -Ei "limit|rate|modsecurity|antibot"'

Названия переменных и доступные настройки зависят от версии BunkerWeb. Для production сверяйте их с документацией конкретного релиза. Веб-интерфейс BunkerWeb или API удобны для управления несколькими сайтами, но административный интерфейс нельзя публиковать без дополнительной аутентификации и ограничения по IP.

Подключение CrowdSec к веб-логам

Сначала убедитесь, что формат логов содержит как минимум время, IP клиента, HTTP-метод, URI и код ответа. Если перед VPS стоит внешний CDN или балансировщик, CrowdSec должен анализировать реальный адрес клиента из доверенного заголовка, иначе он будет блокировать адрес прокси.

# Проверяем решения CrowdSec
sudo cscli decisions list

# Проверяем метрики сбора и сценариев
sudo cscli metrics

# Смотрим журналы сервиса
sudo journalctl -u crowdsec -n 100 --no-pager

Для блокировки на уровне веб-трафика используйте официальный BunkerWeb bouncer или другой совместимый компонент, поддерживаемый вашей версией BunkerWeb. Общий принцип такой: CrowdSec выдаёт API-ключ, а bouncer периодически получает список решений. Не вставляйте этот ключ в публичный compose-файл и не передавайте его в клиентский JavaScript.

# Создаём API-ключ для отдельного bouncer
sudo cscli bouncers add bunkerweb-bouncer

# Показываем активные bouncers без раскрытия ключа
sudo cscli bouncers list

Скопируйте ключ в защищённый файл переменных только на основании инструкции выбранного bouncer. Если ключ раскрыт, немедленно удалите его и создайте новый. Проверяйте работу интеграции на тестовом IP и не включайте постоянную блокировку до того, как убедитесь, что сценарии не дают ложных срабатываний.

Проверка WAF

Тестируйте WAF безопасными запросами на тестовом домене. Цель — проверить, что запрос проходит через BunkerWeb и правила действительно применяются, а не подобрать эксплуатационный payload для production.

# Проверяем обычный запрос
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com/

# Проверяем служебные заголовки и редиректы
curl -sSI https://example.com/

# Проверяем, что явно подозрительная строка фиксируется в логах
curl -k -i 'https://example.com/?q=%3Cscript%3Etest%3C%2Fscript%3E'

# Смотрим решения и журналы после теста
sudo cscli decisions list
sudo docker compose logs --since=5m bunkerweb

Код ответа 403 не всегда означает ошибку: запрос мог быть остановлен WAF. Важно сопоставить время запроса, домен, IP и правило в журнале. Не переводите ModSecurity в режим блокировки на только что опубликованном сайте без предварительного анализа режима обнаружения и тестов на реальных страницах.

8. Бэкапы и обслуживание

Схема: 8. Бэкапы и обслуживание
Схема: 8. Бэкапы и обслуживание

Что необходимо сохранять

  • Конфигурации: compose.yml, .env, настройки BunkerWeb, CrowdSec и firewall.
  • Данные сайтов: загруженные файлы, пользовательские документы, медиа и приватные ключи.
  • Базы данных: логический дамп PostgreSQL, MariaDB или другой используемой СУБД.
  • Сертификаты и настройки TLS: только если они не могут быть восстановлены автоматически.
  • Логи: обычно достаточно хранить их ограниченное время, если они не нужны для аудита.

Docker image повторно скачивается из registry, поэтому его обычно не нужно архивировать. Резервная копия должна храниться вне VPS: на отдельном сервере, в S3-совместимом объектном хранилище или в другой физической локации. Snapshot диска удобен, но не заменяет логические дампы базы данных и независимую копию.

Пример бэкапа конфигураций через Restic

Ниже используется S3-совместимое хранилище. Значения доступа передаются через переменные окружения и не записываются в скрипт. Установите Restic из репозитория Ubuntu либо используйте официальный пакет подходящей версии.

# Устанавливаем Restic
sudo apt install -y restic

# Создаём закрытый файл переменных бэкапа
sudo install -m 600 /dev/null /etc/restic-bunkerweb.env

# Пример содержимого; замените значения на свои
sudo tee /etc/restic-bunkerweb.env > /dev/null <<'EOF'
export AWS_ACCESS_KEY_ID='CHANGE_ME'
export AWS_SECRET_ACCESS_KEY='CHANGE_ME'
export RESTIC_REPOSITORY='s3:https://s3.example.net/bunkerweb-backups'
export RESTIC_PASSWORD='CHANGE_ME_LONG_RANDOM_PASSWORD'
EOF

# Инициализируем repository один раз
sudo bash -c 'source /etc/restic-bunkerweb.env && restic init'

Создайте скрипт, который сначала архивирует конфигурацию, а затем отправляет её в хранилище. Для базы данных добавьте отдельную команду дампа: копирование файлов работающей базы почти всегда некорректно.

# Создаём каталог временных архивов
sudo install -d -m 700 /var/backups/bunkerweb

# Создаём скрипт резервного копирования
sudo tee /usr/local/sbin/backup-bunkerweb > /dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

source /etc/restic-bunkerweb.env

STAMP="$(date -u +%Y-%m-%dT%H-%M-%SZ)"
WORK="/var/backups/bunkerweb/${STAMP}"
mkdir -p "$WORK"

# Копируем конфигурацию и список контейнеров
install -m 600 /opt/bunkerweb/.env "$WORK/.env"
cp -a /opt/bunkerweb/compose.yml "$WORK/compose.yml"
docker compose -f /opt/bunkerweb/compose.yml ps > "$WORK/containers.txt"

# Архивируем конфигурацию в удалённый repository
restic backup "$WORK" --tag bunkerweb-config

# Удаляем локальные временные файлы
rm -rf "$WORK"

# Оставляем разумную историю
restic forget --tag bunkerweb-config \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
EOF

# Делаем скрипт исполняемым
sudo chmod 750 /usr/local/sbin/backup-bunkerweb

Запланируйте запуск через root-cron:

# Открываем cron для root
sudo crontab -e

Добавьте строку:

# Ежедневный бэкап в 03:15 по времени сервера
15 3   * /usr/local/sbin/backup-bunkerweb >> /var/log/backup-bunkerweb.log 2>&1

Периодически проверяйте восстановление. Бэкап, который ни разу не тестировали, нельзя считать гарантированно пригодным.

# Показываем резервные точки
sudo bash -c 'source /etc/restic-bunkerweb.env && restic snapshots'

# Проверяем целостность repository
sudo bash -c 'source /etc/restic-bunkerweb.env && restic check'

Обновления

Перед обновлением сохраните конфигурацию и прочитайте release notes BunkerWeb. Для одного сайта допустимо короткое maintenance window: скачать новый образ, пересоздать контейнер и проверить HTTPS. Для нескольких production-сайтов лучше использовать отдельный тестовый экземпляр, healthcheck и поэтапное переключение.

# Проверяем текущие образы
cd /opt/bunkerweb
sudo docker compose images

# Загружаем обновления после проверки версии
sudo docker compose pull

# Перезапускаем сервисы с новой версией
sudo docker compose up -d

# Проверяем состояние и логи
sudo docker compose ps
sudo docker compose logs --tail=100 bunkerweb

# Проверяем внешний HTTPS
curl -fsS https://example.com/ > /dev/null
echo "HTTPS OK"

Не обновляйте одновременно Ubuntu, Docker, BunkerWeb, CrowdSec и приложение без необходимости. Если после обновления возникла проблема, так проще определить источник. Старые Docker-образы удаляйте только после проверки, что откат не понадобится.

9. Troubleshooting и FAQ

Почему сайт не открывается, а curl возвращает connection refused?

Сначала проверьте, запущены ли контейнеры командой sudo docker compose ps, и слушает ли хост порты через sudo ss -lntp. Затем проверьте UFW, правила сетевой группы провайдера и DNS. Если контейнер перезапускается, выполните sudo docker compose logs --tail=200 bunkerweb. Частая причина — занятый порт 80/443 другим Nginx или Caddy. Остановите старый сервис либо перенесите его за BunkerWeb.

Почему Let's Encrypt не выпускает сертификат?

Наиболее частые причины — домен указывает не на тот IP, закрыт TCP 80, присутствует неправильная AAAA-запись или включён внешний прокси с неподходящим режимом TLS. Проверьте dig A example.com, dig AAAA example.com и доступность HTTP извне. Посмотрите логи BunkerWeb и убедитесь, что email задан корректно. Не запрашивайте сертификат много раз подряд: у Let's Encrypt есть ограничения частоты.

Почему BunkerWeb возвращает 502 Bad Gateway?

Код 502 означает, что reverse proxy не получил корректный ответ от upstream. Проверьте имя Docker-сервиса, внутренний порт и общую сеть контейнеров. Команда docker compose exec bunkerweb wget -qO- http://app:80 должна получить ответ backend. Если приложение слушает только 127.0.0.1 внутри собственного контейнера, оно не будет доступно по Docker-сети. Настройте его на прослушивание 0.0.0.0.

Какой VPS-конфиг минимально подойдёт?

Для одного небольшого сайта технический минимум — 1 vCPU, 2 ГБ RAM и 25 ГБ SSD, но для production лучше использовать 2 vCPU и 4 ГБ RAM. Такой запас нужен для Docker, BunkerWeb, CrowdSec, обновлений и кратковременных пиков. Если на сервере работает база данных или несколько приложений, выбирайте от 4 vCPU и 8 ГБ RAM. Диск должен быть SSD, а сеть — с публичным IPv4 и доступными портами 80/443.

Что выбрать — VPS или dedicated для этой задачи?

VPS подходит большинству проектов с одним или несколькими сайтами: BunkerWeb и CrowdSec потребляют умеренное количество ресурсов, а масштабирование выполняется увеличением тарифа или добавлением экземпляров. Dedicated стоит выбирать при постоянной высокой нагрузке, большом количестве доменов, требованиях к выделенным IOPS или строгой изоляции. Решение принимайте по фактическим метрикам CPU, RAM, диска и сети, а не только по предполагаемому числу посетителей.

Как понять, что CrowdSec действительно блокирует атаки?

Проверьте sudo cscli metrics, список решений через sudo cscli decisions list и журналы journalctl -u crowdsec. Если метрики пустые, агент не читает нужный лог или формат не соответствует parser. Если решения создаются, но запросы проходят, не настроен bouncer или он не подключён к BunkerWeb. Начинайте с тестовой блокировки собственного временного IP и сразу удаляйте её после проверки.

Почему реальные IP пользователей отображаются как адрес прокси?

Если перед VPS есть CDN или балансировщик, BunkerWeb получает TCP-соединение от него. Нужно настроить доверенные proxy-сети и корректный заголовок, например CF-Connecting-IP или X-Forwarded-For, только для известных адресов прокси. Нельзя безусловно доверять этим заголовкам от любого клиента: злоумышленник сможет подменить IP. После настройки проверьте access log и убедитесь, что адрес клиента определяется правильно.

После включения WAF легитимные запросы получают 403. Что делать?

Найдите конкретное правило и URI в журнале BunkerWeb, затем воспроизведите запрос на тестовом окружении. Не отключайте весь WAF: добавьте точечное исключение для конкретного правила, параметра или маршрута. Частые причины — JSON-запросы API, загрузка файлов, нестандартные cookie и административные формы. Перед изменением исключения проверьте, что приложение не отправляет действительно опасный payload и что лимиты размера запроса настроены ожидаемым образом.

10. Выводы и следующие шаги

Схема: 10. Выводы и следующие шаги
Схема: 10. Выводы и следующие шаги

В результате BunkerWeb принимает внешний HTTP/HTTPS-трафик, автоматически обслуживает TLS, фильтрует запросы WAF и проксирует их к приложению во внутренней Docker-сети. Ubuntu firewall, Fail2ban и CrowdSec добавляют защиту хоста и автоматическую реакцию на подозрительную активность.

Дальше стоит настроить мониторинг доступности и сроков сертификатов, проверить восстановление из Restic-бэкапа и вынести базу данных либо тяжёлые приложения на отдельные ресурсы. При росте нагрузки измеряйте p95-задержку, количество 4xx/5xx, загрузку CPU и объём логов, а затем переходите к нескольким WAF-узлам, балансировке и отдельному резервному серверу.

Был ли этот гайд полезен?

Ваш отзыв помогает нам улучшать гайды.

Поделиться записью:

Отправьте гайд тому, кому он может пригодиться.

Telegram VKVK WhatsApp Facebook LinkedIn XX

установка bunkerweb waf на vps: защита сайтов, ssl, docker и crowdsec
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.