bolt Valebyte VPS desde $4/mes — NVMe, despliegue en 60s.

Obtener VPS arrow_forward
eco Principiante Tutorial/Cómo hacer

Instalación de BunkerWeb WAF en un VPS: protección de sitios web, SSL, Docker y CrowdSec

calendar_month Oct 25, 2026 schedule 19 min de lectura visibility 6 vistas
Установка BunkerWeb WAF на VPS: защита сайтов, SSL, Docker и CrowdSec
info

¿Necesitas un servidor para esta guía? Ofrecemos servidores dedicados y VPS en más de 50 países con configuración instantánea.

¿Necesitas un VPS para esta guía?

Explore otras opciones de servidores dedicados en

Instalación de BunkerWeb WAF en un VPS: protección de sitios, SSL, Docker y CrowdSec

TL;DR

BunkerWeb es un firewall web con proxy inverso que se coloca delante de los sitios, recibe tráfico HTTPS, aplica reglas WAF y reenvía las solicitudes a las aplicaciones. En esta guía instalaremos BunkerWeb en Docker sobre Ubuntu Server 24.04 LTS, conectaremos un sitio mediante reverse proxy, configuraremos TLS automático con Let's Encrypt, protección básica contra bots e integración con CrowdSec.

  • Usaremos Ubuntu Server 24.04 LTS, Docker Engine 28.x y Docker Compose v2.
  • BunkerWeb será el único punto de entrada público en los puertos 80 y 443.
  • La aplicación permanecerá en una red interna de Docker y no estará disponible directamente desde Internet.
  • Los certificados de Let's Encrypt se emitirán y renovarán automáticamente.
  • CrowdSec analizará los registros y bloqueará las direcciones IP con mala reputación.
  • Las configuraciones, los secretos y los datos se mantendrán en archivos separados y se incluirán en las copias de seguridad.

3. Qué configuramos y por qué

El esquema habitual de publicación de un sitio es el siguiente: un cliente de Internet se conecta directamente al servidor web de la aplicación. Si la aplicación contiene una vulnerabilidad, procesa las solicitudes de forma incorrecta o sufre un ataque de fuerza bruta contra las contraseñas, el ataque llega hasta ella sin ningún filtro adicional. BunkerWeb cambia esta arquitectura: se convierte en un proxy inverso y WAF entre el cliente y la aplicación.

Un WAF, o Web Application Firewall, analiza las solicitudes HTTP antes de reenviarlas al backend. Puede descartar URI sospechosas, intentos de inyección SQL, XSS, traversal de directorios, ataques automatizados y otros ataques habituales. Esto no sustituye la actualización del CMS, el framework y el sistema operativo, pero reduce la superficie de ataque y añade una capa de protección independiente.

Esquema final

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

En nuestro ejemplo, el dominio será example.com y la aplicación estará disponible dentro de Docker con el nombre app en el puerto 8080. Sustituya este dominio y estos parámetros por los suyos. Los registros DNS deben apuntar a la dirección IPv4 pública del servidor antes de emitir el certificado.

Qué obtendremos después de la configuración

  • Los puertos de la aplicación no se publicarán mediante Docker en la interfaz externa.
  • Las solicitudes HTTP serán recibidas por BunkerWeb y el certificado HTTPS se gestionará automáticamente.
  • El sitio tendrá activadas las reglas básicas de ModSecurity/OWASP CRS mediante la plantilla de BunkerWeb.
  • Los registros de solicitudes se guardarán en un volumen de Docker y estarán disponibles para el análisis de CrowdSec.
  • El firewall del sistema solo permitirá SSH, HTTP y HTTPS.
  • La actualización de los contenedores y las copias de seguridad podrán realizarse independientemente de la aplicación.

Self-hosted o WAF en la nube

Los servicios WAF en la nube reciben el tráfico en su propia infraestructura y lo envían mediante proxy al servidor origin. Esto resulta conveniente con grandes volúmenes, protección distribuida contra DDoS y la necesidad de minimizar el mantenimiento propio. Sin embargo, será necesario transferir el DNS y parte del control de red a un operador externo, mientras que el coste y las limitaciones dependerán del plan contratado.

El BunkerWeb self-hosted es adecuado cuando se necesita un control total sobre la configuración, los registros y el lugar donde se procesan los datos. El propietario del VPS es responsable de las actualizaciones, la disponibilidad, las copias de seguridad y la protección del origin. Para uno o varios sitios en un servidor pequeño, esta opción suele ser más sencilla y transparente que montar por cuenta propia Nginx, ModSecurity, rate limiting y un servicio independiente de gestión de certificados.

Es importante comprender los límites de la solución: BunkerWeb no ofrece una protección completa contra un potente ataque DDoS volumétrico, no corrige las vulnerabilidades de la aplicación y no sustituye el control de acceso a los paneles administrativos. Para un servicio crítico se necesitan monitorización, copias de seguridad independientes y un plan de recuperación.

4. Qué configuración de VPS se necesita para esta tarea

BunkerWeb funciona como reverse proxy, por lo que sus requisitos dependen no solo del propio WAF, sino también de la cantidad de sitios, el tamaño de las solicitudes, la carga TLS, las reglas activadas y el rendimiento del backend. Para un sitio pequeño, el WAF consume pocos recursos, pero se necesita memoria RAM adicional para Docker, CrowdSec, el registro y las actualizaciones.

Escenario CPU RAM Disco Red
Sitio de prueba 1 vCPU 2 GB 25 GB SSD 100 Mbit/s
Sitio production pequeño 2 vCPU 4 GB 40–60 GB NVMe 100–500 Mbit/s
Varios sitios y CrowdSec 4 vCPU 8 GB 80–120 GB NVMe 500 Mbit/s o más

La configuración práctica mínima para production es de 2 vCPU, 4 GB de RAM y 40 GB de SSD. Si en el mismo VPS también funcionarán una base de datos, un CMS, CI/CD, un panel de control o varias aplicaciones, es mejor elegir desde el principio 4 vCPU y 8 GB de RAM. Para Docker, conviene dejar al menos 1 GB de memoria libre después de iniciar todos los contenedores.

Como opción concreta, puede contratar un VPS adecuado con 2–4 vCPU, 4–8 GB de RAM, un disco NVMe de al menos 40 GB y una IPv4 pública. Compruebe que el proveedor permita conexiones entrantes en TCP 80 y 443, proporcione una consola de recuperación y permita crear snapshots o conectar almacenamiento externo.

Cuándo se necesita un dedicated

Un servidor dedicado está justificado si a través del WAF pasa un flujo constante y elevado de solicitudes, se necesitan varias decenas de sitios, se realiza un cifrado TLS intensivo o la máquina aloja servicios backend que consumen muchos recursos. Un dedicated también resulta conveniente cuando se requieren IOPS garantizados, aislamiento de otros usuarios y equipos de red propios.

Para un sitio, un panel de administración, una API o un equipo pequeño, un dedicated suele ser excesivo. Primero mida la carga de CPU, RAM, disco y red. Si la carga media es inferior al 50 % y los picos no provocan swap ni latencia, pasar a un servidor físico no aportará un beneficio apreciable.

Elección de la ubicación

La ubicación influye en la latencia entre los visitantes y el WAF, la ruta hasta el backend y los requisitos de almacenamiento de datos. Elija una región cercana a su audiencia principal, pero tenga en cuenta la disponibilidad de IPv4, la calidad de las conexiones y las normas de tratamiento de datos personales. Si la aplicación y la base de datos se encuentran en regiones diferentes, la latencia entre ellas puede ser más notable que la latencia entre el usuario y el WAF.

5. Preparación del servidor

A continuación se supone un VPS limpio con Ubuntu Server 24.04 LTS y acceso mediante el usuario root. Todos los comandos se ejecutan en el servidor. Sustituya el ejemplo por su propia clave SSH pública y no cierre la sesión SSH actual hasta comprobar el nuevo usuario.

Creación del usuario e instalación de la clave 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

Compruebe el acceso en otra ventana de terminal:

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

Después de comprobarlo correctamente, puede prohibir el acceso de root y la autenticación mediante contraseña. Antes de hacerlo, asegúrese de que la clave funciona y de que la consola web está disponible en el panel del proveedor:

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

En el comando anterior no debe haber un espacio en el nombre del archivo. Utilice la variante correcta:

# Создаём отдельный файл настроек 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

Actualización del sistema y paquetes básicos

# Обновляем индекс репозиториев и пакеты 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 y Fail2ban

Abra SSH antes de activar UFW. Si SSH funciona en otro puerto, sustituya la regla 22/tcp. Los puertos 80 y 443 serán necesarios para que BunkerWeb gestione HTTP y 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 protegerá SSH contra ataques de fuerza bruta simples. BunkerWeb y CrowdSec se encargarán del tráfico web, por lo que no es necesario añadir sin criterio decenas de filtros y bloquear a usuarios legítimos.

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

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

6. Instalación del software — paso a paso

6. Instalación del software — paso a paso

En 2026, utilice Docker Engine desde el repositorio oficial de Docker, no el paquete obsoleto del repositorio base de Ubuntu. Es preferible fijar la versión de BunkerWeb en una etiqueta estable concreta de la serie 1.6.x en lugar de utilizar latest. Antes del despliegue en producción, compruebe la etiqueta estable actualizada en la documentación oficial del proyecto y sustituya el valor de la variable BUNKERWEB_VERSION.

Paso 1. Instalación de 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

No añada el usuario al grupo docker sin necesidad: un miembro de este grupo obtiene de facto privilegios de root. En adelante, ejecute los comandos de Docker mediante sudo o acepte conscientemente este riesgo.

Paso 2. Creación del directorio del proyecto

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

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

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

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

Paso 3. Creación del archivo de secretos

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

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

Guarde el resultado en el gestor de contraseñas. Más adelante, esta contraseña se utilizará únicamente para los servicios internos. No publique el archivo .env en Git ni introduzca secretos reales en el archivo compose.

Paso 4. Preparación de Docker Compose

Para una instalación sencilla utilizamos BunkerWeb y scheduler, y representamos la aplicación independiente mediante el contenedor app. En producción, sustituya la imagen de demostración por su propio backend. BunkerWeb debe encontrarse en la misma red de Docker que la aplicación.

# Переходим в каталог проекта
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

El contenedor de demostración whoami escucha en el puerto 80, por lo que el valor de REVERSE_PROXY_URL en el archivo compose real debe sustituirse por http://app:80. Esto es importante: el nombre del servicio y el puerto deben coincidir con la dirección real del backend.

Paso 5. Inicio de los contenedores

# Загружаем переменные и проверяем итоговую модель 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

Paso 6. Instalación de CrowdSec

CrowdSec consta de un analizador de comportamiento y un componente de toma de decisiones. Lee los registros, relaciona los eventos con escenarios y crea decisiones de bloqueo de IP. En este esquema, BunkerWeb escribe registros JSON en un volumen, mientras que CrowdSec se instala en el host. En producción, es más conveniente montar el registro en un directorio independiente disponible únicamente en modo de solo lectura para el agente de 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

Instale las colecciones para el servidor web y Linux. Los nombres de las colecciones pueden cambiar, por lo que primero realice una búsqueda:

# Обновляем индекс коллекций
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

En el siguiente paso debe indicar a CrowdSec la ruta real de los registros de BunkerWeb. Si se utiliza un volumen de Docker, determine primero su punto de montaje:

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

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

Añada la ruta del campo Mountpoint a la configuración de la fuente de CrowdSec. Los nombres concretos de los archivos de registro dependen de la versión y de la plantilla de BunkerWeb, por lo que primero debe localizarlos:

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

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

7. Configuración

Archivo de variables de entorno

Cree /opt/bunkerweb/.env. Aquí no hay secretos de la aplicación, pero el archivo debe seguir protegido frente a otros usuarios. En el ejemplo se utiliza la rama estable BunkerWeb 1.6.x; antes de la instalación, compruebe la versión patch actualizada.

# Записываем основные переменные проекта
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'

Para varios sitios, BunkerWeb activa el modo multisite. Según la plantilla seleccionada, los parámetros individuales se establecen mediante variables con el prefijo del nombre del sitio o a través de la UI/API. No copie la configuración de un sitio a otro sin comprobar los nombres de dominio y las direcciones upstream.

Comprobación de DNS y puertos

# Проверяем 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

Para emitir un certificado de Let's Encrypt, el dominio debe resolverse en la dirección IPv4 pública del VPS, y el puerto TCP 80 debe ser accesible desde Internet. Si se utiliza un registro AAAA, asegúrese de que IPv6 esté realmente configurado en el servidor y de que el firewall permita los puertos necesarios. De lo contrario, elimine temporalmente el registro AAAA incorrecto o configure IPv6 por completo.

Comprobación del proxy inverso

# Проверяем 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'

Si la respuesta del backend muestra encabezados de servicio, es normal en el contenedor de prueba. En producción, transmita a la aplicación el protocolo original y la dirección del cliente. BunkerWeb normalmente genera encabezados de proxy estándar, pero la aplicación debe estar configurada para confiar en ellos únicamente cuando procedan de la dirección del proxy inverso, no de un cliente arbitrario.

Configuración de los límites de solicitudes

La limitación de velocidad es especialmente útil para las páginas de inicio de sesión, las API y la recuperación de contraseñas. No establezca límites globales agresivos: podrían bloquear a usuarios detrás de NAT, redes móviles y robots de buscadores. Comience con un límite moderado y supervise los registros.

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

Los nombres de las variables y las opciones disponibles dependen de la versión de BunkerWeb. Para producción, compárelos con la documentación de la versión concreta. La interfaz web de BunkerWeb o la API son útiles para gestionar varios sitios, pero la interfaz administrativa no debe publicarse sin autenticación adicional y restricciones por IP.

Conexión de CrowdSec a los registros web

Primero asegúrese de que el formato de los registros contenga como mínimo la hora, la IP del cliente, el método HTTP, el URI y el código de respuesta. Si delante del VPS hay una CDN externa o un balanceador, CrowdSec debe analizar la dirección real del cliente desde un encabezado de confianza; de lo contrario, bloqueará la dirección del proxy.

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

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

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

Para bloquear el tráfico web, utilice el bouncer oficial de BunkerWeb u otro componente compatible admitido por su versión de BunkerWeb. El principio general es el siguiente: CrowdSec emite una clave de API y el bouncer obtiene periódicamente la lista de decisiones. No inserte esta clave en un archivo compose público ni la transmita al JavaScript del cliente.

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

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

Copie la clave en un archivo protegido de variables únicamente siguiendo las instrucciones del bouncer seleccionado. Si la clave queda expuesta, elimínela inmediatamente y cree una nueva. Compruebe el funcionamiento de la integración con una IP de prueba y no active el bloqueo permanente hasta asegurarse de que los escenarios no generan falsos positivos.

Comprobación del WAF

Pruebe el WAF con solicitudes seguras en un dominio de prueba. El objetivo es comprobar que la solicitud pasa por BunkerWeb y que las reglas se aplican realmente, no crear un payload de explotación para producción.

# Проверяем обычный запрос
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

Un código de respuesta 403 no siempre significa un error: la solicitud podría haber sido detenida por el WAF. Es importante correlacionar la hora de la solicitud, el dominio, la IP y la regla del registro. No active el modo de bloqueo de ModSecurity en un sitio recién publicado sin analizar previamente el modo de detección y realizar pruebas en páginas reales.

8. Copias de seguridad y mantenimiento

Qué es necesario guardar

  • Configuraciones: compose.yml, .env, ajustes de BunkerWeb, CrowdSec y firewall.
  • Datos de los sitios: archivos cargados, documentos de usuarios, archivos multimedia y claves privadas.
  • Bases de datos: volcado lógico de PostgreSQL, MariaDB u otro SGBD utilizado.
  • Certificados y ajustes TLS: solo si no pueden recuperarse automáticamente.
  • Registros: normalmente basta con conservarlos durante un tiempo limitado, si no se necesitan para auditorías.

La imagen de Docker se vuelve a descargar desde el registry, por lo que normalmente no es necesario archivarla. La copia de seguridad debe almacenarse fuera del VPS: en un servidor independiente, en un almacenamiento de objetos compatible con S3 o en otra ubicación física. El snapshot del disco es práctico, pero no sustituye los volcados lógicos de la base de datos ni una copia independiente.

Ejemplo de copia de seguridad de las configuraciones mediante Restic

A continuación se utiliza un almacenamiento compatible con S3. Los valores de acceso se pasan mediante variables de entorno y no se escriben en el script. Instale Restic desde el repositorio de Ubuntu o utilice el paquete oficial de una versión adecuada.

# Устанавливаем 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'

Cree un script que primero archive la configuración y después la envíe al almacenamiento. Para la base de datos, añada un comando de volcado independiente: copiar los archivos de una base de datos en funcionamiento casi siempre es incorrecto.

# Создаём каталог временных архивов
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

Programe la ejecución mediante root-cron:

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

Añada la línea:

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

Compruebe periódicamente la restauración. Una copia de seguridad que nunca se ha probado no puede considerarse fiable.

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

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

Actualizaciones

Antes de actualizar, guarde la configuración y lea las release notes de BunkerWeb. Para un solo sitio, es aceptable una maintenance window breve: descargar la nueva imagen, volver a crear el contenedor y comprobar HTTPS. Para varios sitios en production, es mejor utilizar una instancia de prueba independiente, healthcheck y un cambio gradual.

# Проверяем текущие образы
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"

No actualice Ubuntu, Docker, BunkerWeb, CrowdSec y la aplicación simultáneamente sin necesidad. Si surge un problema después de la actualización, será más fácil determinar el origen. Elimine las imágenes antiguas de Docker solo después de comprobar que no será necesario hacer rollback.

9. Solución de problemas y FAQ

¿Por qué no se abre el sitio y curl devuelve connection refused?

Primero compruebe si los contenedores están en ejecución con el comando sudo docker compose ps y si el host escucha en los puertos mediante sudo ss -lntp. Después compruebe UFW, las reglas del grupo de red del proveedor y el DNS. Si el contenedor se reinicia, ejecute sudo docker compose logs --tail=200 bunkerweb. Una causa frecuente es que otro Nginx o Caddy esté utilizando el puerto 80/443. Detenga el servicio antiguo o colóquelo detrás de BunkerWeb.

¿Por qué Let's Encrypt no emite el certificado?

Las causas más frecuentes son que el dominio apunte a la IP incorrecta, que el puerto TCP 80 esté cerrado, que exista un registro AAAA incorrecto o que esté habilitado un proxy externo con un modo TLS inadecuado. Compruebe dig A example.com, dig AAAA example.com y la accesibilidad de HTTP desde el exterior. Consulte los registros de BunkerWeb y asegúrese de que el email esté configurado correctamente. No solicite el certificado muchas veces seguidas: Let's Encrypt tiene límites de frecuencia.

¿Por qué BunkerWeb devuelve 502 Bad Gateway?

El código 502 significa que el reverse proxy no recibió una respuesta correcta del upstream. Compruebe el nombre del servicio Docker, el puerto interno y la red común de los contenedores. El comando docker compose exec bunkerweb wget -qO- http://app:80 debería recibir una respuesta del backend. Si la aplicación escucha solo en 127.0.0.1 dentro de su propio contenedor, no estará disponible a través de la red de Docker. Configúrela para escuchar en 0.0.0.0.

¿Qué configuración mínima de VPS es adecuada?

Para un sitio pequeño, el mínimo técnico es 1 vCPU, 2 GB de RAM y 25 GB de SSD, pero para production es mejor utilizar 2 vCPU y 4 GB de RAM. Esta reserva es necesaria para Docker, BunkerWeb, CrowdSec, las actualizaciones y los picos breves. Si en el servidor funciona una base de datos o varias aplicaciones, elija al menos 4 vCPU y 8 GB de RAM. El disco debe ser SSD y la red debe disponer de una IPv4 pública y de los puertos 80/443 accesibles.

¿Qué elegir: VPS o dedicated para esta tarea?

El VPS es adecuado para la mayoría de los proyectos con uno o varios sitios: BunkerWeb y CrowdSec consumen una cantidad moderada de recursos, y el escalado se realiza aumentando el plan o añadiendo instancias. Elija dedicated cuando exista una carga elevada constante, un gran número de dominios, requisitos de IOPS dedicadas o una estricta separación. Tome la decisión basándose en las métricas reales de CPU, RAM, disco y red, no solo en el número previsto de visitantes.

¿Cómo saber si CrowdSec realmente está bloqueando ataques?

Compruebe sudo cscli metrics, la lista de decisiones mediante sudo cscli decisions list y los registros con journalctl -u crowdsec. Si las métricas están vacías, el agente no lee el registro necesario o el formato no coincide con el parser. Si se crean decisiones, pero las solicitudes siguen pasando, el bouncer no está configurado o no está conectado a BunkerWeb. Empiece bloqueando temporalmente su propia IP de prueba y elimínela inmediatamente después de la comprobación.

¿Por qué las IP reales de los usuarios aparecen como la dirección del proxy?

Si delante del VPS hay un CDN o un balanceador, BunkerWeb recibe la conexión TCP desde él. Es necesario configurar las redes proxy de confianza y el encabezado correcto, por ejemplo CF-Connecting-IP o X-Forwarded-For, solo para las direcciones conocidas del proxy. No se debe confiar incondicionalmente en estos encabezados de cualquier cliente: un atacante podría falsificar la IP. Después de la configuración, compruebe el access log y asegúrese de que la dirección del cliente se determine correctamente.

Después de activar WAF, las solicitudes legítimas reciben 403. ¿Qué hacer?

Busque la regla concreta y el URI en el registro de BunkerWeb y, a continuación, reproduzca la solicitud en el entorno de prueba. No desactive todo el WAF: añada una excepción específica para la regla, el parámetro o la ruta concretos. Las causas frecuentes son las solicitudes JSON de la API, la carga de archivos, las cookies no estándar y los formularios administrativos. Antes de modificar la excepción, compruebe que la aplicación no envíe realmente un payload peligroso y que los límites de tamaño de la solicitud estén configurados según lo esperado.

10. Conclusiones y próximos pasos

Como resultado, BunkerWeb recibe el tráfico HTTP/HTTPS externo, gestiona TLS automáticamente, filtra las solicitudes mediante WAF y las redirige al backend a través de la red interna de Docker. El firewall de Ubuntu, Fail2ban y CrowdSec añaden protección al host y una respuesta automática ante actividades sospechosas.

A continuación, conviene configurar la supervisión de la disponibilidad y de la vigencia de los certificados, comprobar la restauración desde la copia de seguridad de Restic y trasladar la base de datos o las aplicaciones pesadas a recursos independientes. A medida que aumente la carga, mida la latencia p95, la cantidad de respuestas 4xx/5xx, el uso de CPU y el volumen de registros, y después pase a varios nodos WAF, al balanceo y a un servidor de respaldo independiente.

¿Te fue útil esta guía?

Tus comentarios nos ayudan a mejorar nuestras guías.

Compartir esta publicación:

Envía esta guía a alguien a quien pueda resultarle útil.

Telegram VKVK WhatsApp Facebook LinkedIn XX

instalación de BunkerWeb WAF en VPS: protección de sitios web, SSL, Docker y CrowdSec
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.