Cómo montar tu propia VPN con WireGuard, wg-easy, Docker y Caddy en Ubuntu - Chuda
16019
wp-singular,post-template-default,single,single-post,postid-16019,single-format-standard,wp-theme-bridge,bridge-core-3.3.5.1,qode-optimizer-1.2.3,qode-page-transition-enabled,ajax_fade,page_not_loaded,,qode-theme-ver-30.9.1,qode-theme-bridge,disabled_footer_top,qode_header_in_grid,wpb-js-composer js-comp-ver-9.0.1,vc_responsive

Cómo montar tu propia VPN con WireGuard, wg-easy, Docker y Caddy en Ubuntu

Cómo montar tu propia VPN con WireGuard, wg-easy, Docker y Caddy en Ubuntu

Una VPN autogestionada puede ser un proyecto excelente para aprender sobre redes, cifrado, Linux y contenedores. También puede servir para conectar dispositivos a través de un túnel cifrado o utilizar un servidor remoto como punto de salida a Internet.

En esta guía desplegaremos una VPN basada en WireGuard, administrada mediante wg-easy, ejecutada con Docker Compose y publicada con HTTPS mediante Caddy. Además de la instalación, revisaremos la arquitectura, los puertos, la seguridad y las pruebas de conectividad.

Alcance y advertencia: el procedimiento está pensado como base para un laboratorio personal o un servicio pequeño. Antes de usarlo en producción, valida las versiones, las reglas de red y los requisitos del proveedor del VPS. Los nombres de variables y el proceso de configuración de wg-easy pueden cambiar entre versiones.

1. ¿Qué es cada componente?

  • WireGuard: tecnología VPN que establece túneles cifrados entre pares autorizados. Cada cliente tiene su propia identidad basada en claves.
  • wg-easy: interfaz web para configurar y administrar clientes WireGuard, generar perfiles y mostrar códigos QR.
  • Docker Engine: ejecuta los servicios en contenedores.
  • Docker Compose: declara y administra los contenedores mediante YAML.
  • Caddy: servidor web y proxy inverso que puede obtener y renovar certificados TLS automáticamente.

Una VPN no proporciona anonimato absoluto ni protege por sí sola un dispositivo comprometido. La seguridad depende también de la administración de claves, las rutas, el firewall, las actualizaciones y la configuración de los clientes.

2. Arquitectura

El despliegue separa dos flujos de red:

  1. Administración web: el navegador se conecta a https://vpn.tudominio.com por TCP 443. Caddy termina TLS y reenvía la solicitud al servicio web interno de wg-easy.
  2. Túnel VPN: los clientes WireGuard se conectan al VPS por UDP 51820. Este tráfico no pasa por Caddy.

Importante: el puerto del panel de wg-easy no se publica en la interfaz del host. Caddy y wg-easy comparten una red Docker privada, y Caddy se conecta al nombre del servicio. Así se evita exponer directamente el puerto de administración en Internet.

3. Requisitos previos

Necesitarás:

  • Un VPS con Ubuntu compatible con Docker y arquitectura soportada por la imagen.
  • Una IP pública.
  • Acceso SSH administrativo.
  • Un dominio o subdominio, por ejemplo vpn.tudominio.com.
  • Acceso a la administración DNS.
  • Permisos para configurar el firewall del sistema y el firewall del proveedor.
  • Una aplicación cliente WireGuard en los dispositivos que se conectarán.

Antes de empezar, revisa los límites de transferencia del VPS, porque el tráfico de los clientes puede salir a Internet a través de ese servidor y consumir su cuota de datos.

4. Configurar DNS

Crea en el proveedor DNS un registro A:

Campo Ejemplo


Tipo A
Nombre vpn
Valor IP pública del VPS
TTL 300 o automático

Comprueba la resolución desde tu equipo:

dig +short vpn.tudominio.com

La respuesta debe ser la IP pública correcta. Si tienes un registro AAAA, confirma que la conectividad IPv6 funciona de verdad; un registro IPv6 incorrecto puede causar fallos de acceso o de validación del certificado.

Caddy necesita que el dominio sea resoluble y que el servidor pueda recibir las conexiones necesarias para obtener el certificado público.

5. Actualizar Ubuntu y preparar SSH

Conéctate al servidor:

ssh usuario@TU_IP_PUBLICA

Actualiza el índice de paquetes e instala las actualizaciones disponibles:

sudo apt update
sudo apt upgrade -y

En un entorno productivo, revisa los cambios y mantén un procedimiento de recuperación. Antes de habilitar el firewall, confirma que la regla SSH permite tu forma de administración para evitar bloquearte.

6. Instalar Docker

Para un entorno mantenible, sigue la guía oficial de Docker Engine para Ubuntu:

Después, verifica la instalación:

docker --version
docker compose version
sudo systemctl enable --now docker

No añadas usuarios al grupo docker sin entender sus implicaciones: ese grupo normalmente concede privilegios equivalentes a root sobre el host. Administra quién puede ejecutar comandos Docker.

7. Crear el proyecto

Crea una carpeta para los archivos de configuración:

mkdir -p ~/wireguard
cd ~/wireguard

Dentro guardaremos compose.yml y Caddyfile. Docker utilizará volúmenes persistentes para conservar la configuración de WireGuard y los datos de Caddy.

8. Crear el archivo compose.yml

La siguiente composición sigue el patrón documentado por wg-easy para integrar Caddy mediante una red Docker compartida. La imagen de wg-easy usa la etiqueta mayor 15; antes de producción, fija una versión de parche o digest validado y prueba la actualización en un entorno controlado.

Crea el archivo:

nano compose.yml

Contenido:

services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:15
    container_name: wg-easy
    restart: unless-stopped
    environment:
      # wg-easy v15 sirve el panel en el puerto interno 80
      - PORT=80
    volumes:
      - etc_wireguard:/etc/wireguard
      - /lib/modules:/lib/modules:ro
    ports:
      # Solo el túnel VPN se publica en el host
      - "51820:51820/udp"
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv6.conf.all.disable_ipv6=0
      - net.ipv6.conf.all.forwarding=1
      - net.ipv6.conf.default.forwarding=1
    networks:
      - proxy

  caddy:
    image: caddy:2.10.0-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80/tcp"
      - "443:443/tcp"
      # UDP 443 habilita HTTP/3; es opcional
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - proxy

networks:
  proxy:
    name: wireguard-proxy

volumes:
  etc_wireguard:
  caddy_data:
  caddy_config:

¿Por qué no se publica el puerto 51821?

En esta configuración, wg-easy escucha en el puerto interno 80 y Caddy lo alcanza a través de la red Docker wireguard-proxy. No se declara una publicación de puerto para la interfaz web en el host. Por eso no es necesario exponer el puerto TCP 51821.

Permisos del contenedor

NET_ADMIN permite operaciones administrativas de red. SYS_MODULE y el montaje de /lib/modules aparecen en el patrón de instalación de wg-easy, pero amplían las capacidades del contenedor. Revisa los requisitos de la versión, el kernel y el proveedor; no elimines ni añadas capacidades a ciegas. En un entorno de mayor exigencia, evalúa alternativas que reduzcan privilegios y valida la compatibilidad con el host.

Sobre IPv6

El ejemplo contempla parámetros de forwarding IPv6, pero eso no significa que la conectividad IPv6 quede configurada automáticamente de extremo a extremo. Si no vas a utilizar IPv6, revisa si necesitas esos parámetros y no configures rutas IPv6 completas en los clientes hasta validar direccionamiento, NAT/rutas y firewall.

9. Configurar Caddy

Crea el archivo:

nano Caddyfile

Contenido:

vpn.tudominio.com {
    reverse_proxy wg-easy:80
}

Reemplaza vpn.tudominio.com por tu dominio real.

Caddy y wg-easy comparten la red Docker wireguard-proxy, por lo que Caddy puede resolver wg-easy como nombre del servicio. Caddy gestionará automáticamente el certificado TLS público cuando el DNS, los puertos externos y los permisos de almacenamiento estén correctamente configurados.

No agregues tls internal para este caso si necesitas un certificado público confiable por navegadores sin instalar una autoridad certificadora privada. La opción tls internal sirve certificados emitidos por la CA local de Caddy y tiene un propósito diferente.

Documentación:

– wg-easy: integración con Caddy

– Caddy: HTTPS automático

10. Configurar el firewall

Si utilizas UFW:

sudo apt install ufw -y

# Mantén acceso SSH antes de activar el firewall
sudo ufw allow 22/tcp

# Caddy: validación HTTP y HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# WireGuard
sudo ufw allow 51820/udp

sudo ufw status verbose

Una vez confirmadas las reglas, habilita UFW si aún no está activo:

sudo ufw enable

Si tu proveedor tiene firewall de red, permite también los puertos requeridos allí. La configuración del host y la del proveedor son controles distintos.

Resumen de puertos


Puerto Protocolo Exposición Uso


22 TCP Restringir cuando SSH sea posible

80 TCP Público Caddy, validación y redirección

443 TCP Público Panel HTTPS

443 UDP Opcional HTTP/3 de Caddy

51820 UDP Público Túnel WireGuard

80 interno TCP Solo red Docker Panel wg-easy detrás de Caddy

51821 TCP No publicado en No se usa como el host puerto público en esta composición


11. Validar e iniciar los contenedores

Desde ~/wireguard:

docker compose -f compose.yml config
docker compose -f compose.yml up -d
docker compose -f compose.yml ps

Consulta los registros:

docker compose -f compose.yml logs -f caddy

Si Caddy no obtiene un certificado, revisa:

  • Que el registro DNS apunte al VPS.
  • Que los puertos 80 y 443 sean accesibles desde Internet.
  • Que no haya otro servicio ocupando esos puertos.
  • Que los volúmenes /data y /config de Caddy sean persistentes y escribibles.
  • Que el nombre del dominio en Caddyfile sea correcto.

Después abre https://vpn.tudominio.com. En una instalación inicial de wg-easy v15, sigue el asistente de configuración del panel para completar la configuración inicial y crear el acceso administrativo. Los pasos exactos dependen de la versión; consulta la documentación de wg-easy.

No dejes el panel sin configurar ni compartas el acceso administrativo. Activa las medidas de autenticación disponibles en la versión instalada y, cuando sea posible, añade MFA y restricciones de acceso.

12. Crear un cliente

Desde el panel:

  1. Completa la configuración inicial.
  2. Crea un cliente con un nombre reconocible, por ejemplo mac-personal.
  3. Descarga su archivo .conf o utiliza el QR desde un dispositivo móvil.
  4. Importa el perfil en la aplicación WireGuard oficial.
  5. Activa el túnel y verifica la conectividad.

Cada dispositivo debe tener su propio perfil. Los archivos de configuración pueden contener claves privadas: trátalos como secretos, no los envíes por canales inseguros y no los subas a repositorios.

Si un dispositivo se pierde o una clave queda expuesta, deshabilita el cliente desde el panel y genera un perfil nuevo cuando corresponda.

13. VPN completa o túnel dividido

AllowedIPs determina qué destinos se enrutan por el túnel desde la perspectiva del cliente.

  • Túnel completo IPv4: 0.0.0.0/0 dirige las rutas IPv4 predeterminadas por la VPN.
  • Túnel completo IPv6: ::/0 dirige las rutas IPv6 predeterminadas por la VPN, pero solo debe usarse si IPv6 funciona de extremo a extremo.
  • Túnel dividido: se incluyen únicamente las redes que deben pasar por la VPN, por ejemplo una subred privada.

Una VPN de túnel completo puede hacer que el tráfico de Internet salga usando la IP pública del VPS. Para que funcione, el servidor debe tener forwarding, rutas, reglas de NAT y firewall correctos.

14. Validar la conectividad

Desde el cliente con la VPN activa, prueba:

ping -c 3 1.1.1.1
ping -c 3 google.com

La primera prueba ayuda a revisar la conectividad IP; la segunda también depende del DNS.

En el servidor, consulta el estado de WireGuard usando el procedimiento soportado por la versión instalada. También puedes revisar los registros:

docker compose -f compose.yml logs --tail=100 wg-easy
docker compose -f compose.yml logs --tail=100 caddy

Un ping fallido no demuestra por sí solo que el túnel esté roto: algunos destinos bloquean ICMP. Complementa las pruebas con estado del túnel, rutas, DNS, firewall y tráfico real de una aplicación.

Checklist de solución de problemas

  • El nombre DNS resuelve a la IP pública correcta.
  • UDP 51820 está permitido en UFW y en el firewall del proveedor.
  • TCP 80 y 443 llegan a Caddy.
  • El contenedor wg-easy está activo.
  • El cliente utiliza el endpoint y las claves correctas.
  • El forwarding IPv4 está activo si se requiere enrutamiento.
  • NAT/rutas y reglas de firewall permiten el tráfico esperado.
  • El DNS configurado en el cliente responde.
  • IPv6 está configurado de forma coherente o no se enruta por eltúnel.
  • No hay conflictos entre el rango VPN y las redes locales del cliente.

15. Operación diaria y actualizaciones

Comandos habituales:

cd ~/wireguard

# Estado
docker compose -f compose.yml ps

# Registros
docker compose -f compose.yml logs -f

# Reiniciar
docker compose -f compose.yml restart

# Detener
docker compose -f compose.yml down

Antes de actualizar, respalda la configuración persistente y lee las notas de versión. Luego descarga la imagen y recrea los servicios durante una ventana controlada:

docker compose -f compose.yml pull
docker compose -f compose.yml up -d
docker compose -f compose.yml ps

La etiqueta :15 limita la imagen a la serie mayor 15, pero no fija una versión de parche inmutable. Para despliegues críticos, utiliza una etiqueta concreta o digest validado, registra la versión instalada y prueba la actualización antes de aplicarla.

No elimines los volúmenes al detener el servicio. Un comando como docker compose down -v puede borrar volúmenes y provocar pérdida de configuración.

16. Seguridad y buenas prácticas

Acceso administrativo

  • Usa una contraseña fuerte y las medidas de autenticación disponibles, incluida MFA cuando la versión lo permita.
  • Restringe SSH a direcciones conocidas o utiliza un acceso administrativo privado si es viable.
  • No publiques el puerto interno del panel.
  • Revisa periódicamente las cuentas y los clientes que siguen autorizados.
  • No compartas archivos .conf, claves privadas, secretos ni códigos QR de clientes.

Sistema y contenedores

  • Instala actualizaciones de seguridad de Ubuntu.
  • Fija y valida versiones de imágenes.
  • Revisa capacidades de contenedor como NET_ADMIN y SYS_MODULE.
  • Limita quién puede administrar Docker.
  • Conserva registros útiles sin almacenar secretos innecesarios.

Respaldos y recuperación

  • Respalda los datos persistentes de wg-easy y Caddy.
  • Cifra los respaldos y restringe su acceso.
  • Mantén copias fuera del VPS.
  • Documenta cómo restaurar y prueba la recuperación.
  • Define cuánto tiempo conservar las copias y cómo eliminarlas de forma segura.

Monitorización

Supervisa CPU, memoria, espacio en disco, estado de contenedores, errores de Caddy, conectividad del túnel y consumo de transferencia. Para un servicio empresarial, incorpora alertas y un procedimiento de respuesta ante incidentes.

17. Costos y escalabilidad

El costo depende del VPS, el ancho de banda, la transferencia de datos, los respaldos y el nivel de disponibilidad requerido. Revisa la política de tráfico del proveedor: una VPN puede consumir mucha transferencia si varios clientes envían todo su tráfico de Internet a través del servidor.

Una única instancia suele ser suficiente para un laboratorio, pero constituye un punto único de falla. Para un uso empresarial, evalúa disponibilidad, recuperación ante desastres, administración de claves, segmentación, controles de acceso y requisitos de cumplimiento.

18. Conclusión

WireGuard, wg-easy, Docker Compose y Caddy permiten construir una VPN autogestionada con un túnel cifrado, una interfaz de administración y HTTPS para proteger el acceso al panel.

La parte más importante no es solamente conseguir que el contenedor arranque: también hay que comprobar las rutas, el DNS, el firewall, el almacenamiento persistente y la protección de las claves. La seguridad debe mantenerse durante todo el ciclo de vida, incluidas las actualizaciones y la revocación de clientes.

Si trabajas con Linux, redes, DevOps o seguridad en la nube, esta práctica es una buena oportunidad para reforzar conocimientos de conectividad, contenedores y operación segura.