Estás harto de pagar 12,99 €/mes a NordVPN después del año promocional. Quieres un túnel cifrado que no compartas con nadie, alojado en una jurisdicción GDPR y cuya configuración controles línea por línea. Buenas noticias: se monta en 20 minutos en un VPS Contabo a 5,50 €/mes (junio 2026), y esta guía te da todos los comandos. Sin marketing, sin abstracciones - solo el script de calidad producción.
¿Cómo auto-alojar una VPN WireGuard en un VPS?
Auto-alojar una VPN WireGuard lleva unos 20 minutos: contratar un Contabo Cloud VPS 10 (5,50 €/mes, Ubuntu 24.04), ejecutar apt install wireguard, generar las claves del servidor, escribir un wg0.conf de 10 líneas con subnet 10.66.66.0/24 en el puerto 51820, activar el reenvío IP y añadir NAT con iptables. Coste: unos 66 €/año frente a ~540 € por NordVPN en 5 años.
Por qué auto-alojar en lugar de un servicio comercial
Un servicio VPN comercial te vende una promesa: sin logs, IP compartida con miles de usuarios, jurisdicción "no-logs friendly" (Panamá, BVI, Suiza). Sobre el papel es sólido. En la práctica:
- IP compartida = reputación compartida. Cuando 4 000 usuarios de NordVPN salen por la misma IP, heredas sus listas negras. Stripe te pedirá un 3DS adicional. Cloudflare te servirá retos sin fin. Alojas tu propio VPN = tu propia IP limpia.
- No-logs inverificable en tiempo real. Una auditoría PwC valida una política en un instante T. Entre auditorías, las órdenes judiciales (subpoenas estadounidenses, órdenes europeas) pueden forzar logging temporal. En tu VPS, decides tú. Purgas cuando quieres.
- Precios que se duplican al renovar. NordVPN 2 años: 71,76 €. Renovación anual: 156 €/año. En 5 años: ~600 €. Un Contabo Cloud VPS 10 en 5 años: ~330 €. Y puedes alojar otros servicios encima.
El tradeoff honesto: no desbloquearás Netflix US con un VPS dedicado (Netflix bloquea los ASN datacenter). Para streaming, documentamos una solución híbrida en la guía de bypass DPI.
Elegir el VPS Contabo adecuado
Contabo tiene tres gamas relevantes para una VPN personal (precios junio 2026, plan 12 meses, sin IVA):
| Oferta | Precio/mes | vCPU | RAM | Almacenamiento | Ideal para |
|---|---|---|---|---|---|
| Cloud VPS 10 | 5,50 € | 4 | 8 GB | 75 GB NVMe | VPN solo 1-3 dispositivos |
| Cloud VPS 20 | 7,50 € | 6 | 12 GB | 100 GB NVMe | VPN familia 5-10 dispositivos |
| Cloud VPS 30 | 14 € | 8 | 24 GB | 200 GB NVMe | Multi-túnel + otros servicios |
Nuestra elección por defecto: Cloud VPS 10 a 5,50 €/mes. Para el 90 % de usos individuales, sobra. El enlace de 200 Mbps+ es de sobra para un túnel personal (ejecuta iperf3 tú mismo para cifras exactas en tu conexión).
Datacenter recomendado: Nuremberg (DE) para latencias <30 ms desde Europa continental. Si estás en EE.UU./Canadá, elige US Central (St. Louis).
Setup paso a paso
Paso 1 - Provisionar el VPS
En contabo.com, elige Cloud VPS 10, Ubuntu 24.04 LTS, contraseña root (crearemos un usuario normal después), datacenter Nuremberg. Pago con tarjeta o PayPal. Activación: email en ~5 minutos con la IP pública y la contraseña root.
Paso 2 - Endurecer el servidor
Primera conexión SSH:
ssh root@TU_IP_PUBLICA
# La contraseña está en el email de Contabo
Crea un usuario no root, añade tu clave SSH, desactiva el login root:
adduser ericg
usermod -aG sudo ericg
mkdir -p /home/ericg/.ssh
# Pega tu clave pública (~/.ssh/id_ed25519.pub en local)
nano /home/ericg/.ssh/authorized_keys
chmod 700 /home/ericg/.ssh
chmod 600 /home/ericg/.ssh/authorized_keys
chown -R ericg:ericg /home/ericg/.ssh
# Desactivar login root + password
sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh
Sal del shell root y reconecta con ssh ericg@TU_IP. Si funciona, seguimos.
Instala firewall y fail2ban:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ufw fail2ban
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 51820/udp
sudo ufw --force enable
sudo systemctl enable --now fail2ban
Paso 3 - Instalar y configurar WireGuard
sudo apt install -y wireguard qrencode
# Generación de claves del servidor
cd /etc/wireguard
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key
SERVER_PRIV=$(sudo cat server_private.key)
Identifica tu interfaz pública (a menudo ens3 o eth0):
ip route | grep default
# default via X.X.X.X dev ens3 ...
Crea /etc/wireguard/wg0.conf:
sudo nano /etc/wireguard/wg0.conf
Contenido (reemplaza ens3 por tu interfaz si es distinta):
[Interface]
PrivateKey = PEGA_SERVER_PRIV_AQUI
Address = 10.66.66.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
Activa el forwarding IP:
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Arranca WireGuard:
sudo systemctl enable --now wg-quick@wg0
sudo wg show
# Debes ver "interface: wg0" y "listening port: 51820"
Paso 4 - Generar un cliente
Para cada dispositivo:
cd /etc/wireguard
sudo wg genkey | sudo tee macbook_private.key | sudo wg pubkey | sudo tee macbook_public.key
CLIENT_PRIV=$(sudo cat macbook_private.key)
CLIENT_PUB=$(sudo cat macbook_public.key)
SERVER_PUB=$(sudo cat server_public.key)
Crea /tmp/macbook.conf (en el servidor, para generar el QR - luego lo borras):
[Interface]
PrivateKey = PEGA_CLIENT_PRIV
Address = 10.66.66.2/24
DNS = 1.1.1.1, 9.9.9.9
[Peer]
PublicKey = PEGA_SERVER_PUB
Endpoint = TU_IP_PUBLICA:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Añade este peer al servidor:
sudo wg set wg0 peer PEGA_CLIENT_PUB allowed-ips 10.66.66.2/32
# Y persistir:
sudo nano /etc/wireguard/wg0.conf
# Añadir abajo:
# [Peer]
# PublicKey = PEGA_CLIENT_PUB
# AllowedIPs = 10.66.66.2/32
Para iOS/Android: genera el QR
qrencode -t ansiutf8 < /tmp/macbook.conf
Escanea con la app oficial WireGuard. Activa. Listo.
Paso 5 - Verificar que no hay fugas
En tu cliente conectado al túnel:
- Ve a ipleak.net - la IP debe ser la del VPS Contabo, no la tuya.
- Ve a browserleaks.com/webrtc - sin IP local expuesta.
- Ve a dnsleaktest.com - DNS resuelto vía 1.1.1.1 (Cloudflare).
Si aparece una fuga WebRTC: activa el kill switch en WireGuard móvil ("On-Demand"), o bloquea WebRTC en Firefox (about:config → media.peerconnection.enabled → false).
Endurecimiento adicional
Algunos hardenings recomendados en producción:
- Auditoría Lynis:
sudo apt install lynis && sudo lynis audit system. Puntuación objetivo: 80+/100. - SSH en puerto custom: modifica
/etc/ssh/sshd_configpuerto 2222, actualiza UFW. - Desactivar IPv6 si no se usa:
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1(persistir en sysctl.conf). - Logs mínimos: por defecto journald conserva 4 semanas. Reducir a 7 días vía
/etc/systemd/journald.confsi el modelo de amenaza es estricto. - Backups Contabo: activar los snapshots automáticos en el panel Contabo (1 €/mes, no para los logs sino para restaurar rápidamente tras un error).
Setup automatizado vía un playbook Ansible
Si planeas provisionar más de un VPS - o simplemente quieres poder reconstruir tu túnel en 3 minutos tras un incidente - automatizar vía Ansible evita teclear los comandos de arriba una y otra vez. Aquí está el playbook que usamos en producción. Idempotente (puedes relanzarlo sin romper nada), probado en Ubuntu 24.04 LTS Contabo Nuremberg en mayo 2026.
Prerrequisitos locales
# En tu portátil
pip install --user ansible
mkdir -p ~/vpn-ansible && cd ~/vpn-ansible
Crea inventory.yml (sustituye la IP por la recibida en el email de Contabo):
all:
hosts:
vpn1:
ansible_host: TU_IP_PUBLICA
ansible_user: root
ansible_python_interpreter: /usr/bin/python3
El playbook playbook.yml
---
- name: Bootstrap VPNSmith WireGuard en Contabo
hosts: vpn1
become: yes
vars:
admin_user: ericg
admin_ssh_key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
wg_subnet: "10.66.66.0/24"
wg_port: 51820
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Upgrade all packages
apt:
upgrade: dist
autoremove: yes
- name: Install hardening + WireGuard packages
apt:
name:
- ufw
- fail2ban
- wireguard
- qrencode
- unattended-upgrades
state: present
- name: Create admin user
user:
name: "{{ admin_user }}"
groups: sudo
shell: /bin/bash
password: "!"
- name: Authorize admin SSH key
authorized_key:
user: "{{ admin_user }}"
key: "{{ admin_ssh_key }}"
state: present
- name: Disable SSH root login + passwords
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regex }}"
line: "{{ item.line }}"
loop:
- { regex: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regex: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
notify: restart ssh
- name: Configure UFW default policies
ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
loop:
- { direction: incoming, policy: deny }
- { direction: outgoing, policy: allow }
- name: Allow SSH + WireGuard through UFW
ufw:
rule: allow
port: "{{ item.port }}"
proto: "{{ item.proto }}"
loop:
- { port: 22, proto: tcp }
- { port: "{{ wg_port }}", proto: udp }
- name: Enable UFW
ufw:
state: enabled
policy: deny
- name: Enable IP forwarding
sysctl:
name: net.ipv4.ip_forward
value: "1"
state: present
reload: yes
- name: Detect public interface
shell: ip -o -4 route show to default | awk '{print $5}'
register: pub_iface
changed_when: false
- name: Generate server WireGuard keys
shell: |
umask 077
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
args:
creates: /etc/wireguard/server_private.key
- name: Read server keys
slurp:
src: "/etc/wireguard/{{ item }}"
register: wg_keys
loop:
- server_private.key
- server_public.key
- name: Render wg0.conf
copy:
dest: /etc/wireguard/wg0.conf
mode: '0600'
content: |
[Interface]
PrivateKey = {{ wg_keys.results[0].content | b64decode | trim }}
Address = 10.66.66.1/24
ListenPort = {{ wg_port }}
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o {{ pub_iface.stdout }} -j MASQUERADE
- name: Enable + start wg-quick@wg0
systemd:
name: wg-quick@wg0
enabled: yes
state: started
- name: Enable + start fail2ban
systemd:
name: fail2ban
enabled: yes
state: started
handlers:
- name: restart ssh
systemd:
name: ssh
state: restarted
Ejecución
ansible-playbook -i inventory.yml playbook.yml
Cuenta ~3 minutos la primera vez (esencialmente el upgrade apt). El túnel está arriba. Tu usuario ericg puede SSH con su clave Ed25519. Puedes relanzar el playbook tantas veces como quieras sin romper nada - no reescribirá las claves WireGuard (idempotencia garantizada por el creates:).
Para añadir un cliente (gestionado en una segunda fase del playbook, lo documentamos en la guía de plantillas WireGuard): generas las claves del cliente, renderizas el client.conf en Jinja2, push de la config vía QR encode.
Consejo práctico: versiona el playbook en un repo Git privado (jamás público - las claves de Ansible Vault no son un secreto frente a GitHub público si la passphrase se filtra). Nosotros usamos un Gitea auto-alojado en el mismo VPS para la circularidad perfecta.
Monitorización de uptime gratis con UptimeRobot
Si quieres saber cuándo se cae tu túnel sin refrescar manualmente, UptimeRobot cubre el 95 % de la necesidad gratis. Plan free: 50 monitors, check cada 5 minutos, alertas por email + Telegram + webhook Discord.
Monitorizamos 3 endpoints distintos para distinguir el tipo de fallo:
Monitor 1 - Salud del servidor (ping HTTPS de la IP)
Tipo UptimeRobot "HTTP(s)", URL https://TU_IP_PUBLICA/healthz. Para responder a este check, instala un Caddy ligero en el puerto 443:
sudo apt install -y caddy
sudo tee /etc/caddy/Caddyfile > /dev/null <<EOF
:443 {
respond /healthz "OK" 200
tls internal
}
EOF
sudo systemctl restart caddy
sudo ufw allow 443/tcp
Si este monitor pasa a DOWN → el VPS en sí está inaccesible (corte de red Contabo, o tu VPS se ha caído).
Monitor 2 - Salud del túnel (desde Cloudflare Workers)
Crea un Cloudflare Worker gratuito (free tier 100 000 req/día) que haga un fetch a https://ifconfig.me con un user-agent custom. Para que el check tenga sentido el Worker debería atravesar el túnel WireGuard, lo que no es directamente posible con Workers - se resuelve con un monitor "Keyword" de UptimeRobot que interrogue un endpoint que alojas tú y verifique que la respuesta contiene la IP del VPS Contabo (no una IP residencial).
URL monitorizada: https://TU_IP_PUBLICA/whoami (Caddy redirige a ifconfig.me).
Keyword: la IPv4 de tu VPS.
Si el routing fallase (hijack DNS, NAT roto), la IP devuelta sería distinta y el monitor saltaría.
Monitor 3 - Salud DNS vía 1.1.1.1
URL: https://1.1.1.1/cdn-cgi/trace, keyword "warp=off". Este check verifica que puedes resolver Cloudflare desde el VPS - es decir, que la ruta saliente del VPS no está rota.
Configuración de alertas
En UptimeRobot, configura:
- Email primario: te llega en menos de 30 seg tras la detección
- Bot Telegram (gratis): push al móvil incluso fuera del email
- Threshold: "alert after 2 failed checks" para evitar falsos positivos de red
En la práctica, este setup te alerta sobre todo de eventos reales - un mantenimiento planificado de Contabo, o un crash de servicio (por ejemplo Caddy fallando en una renovación de certificado). Con el umbral de «2 checks fallidos», los falsos positivos de red son raros.
Coste total: 0 €. UptimeRobot free + Cloudflare Workers free + Caddy gratis.
Hardening SSH con fail2ban y key-only auth
El bootstrap inicial desactiva el password SSH, pero en producción hay que ir más allá. Aquí está el hardening a aplicar en todo VPS Contabo, motivado por el escaneo SSH automatizado permanente que sufre todo host expuesto a internet (los bots escanean en continuo los rangos de IP de los hosting, Contabo incluido).
Paso 1 - Puerto SSH custom
Cambiar el puerto SSH no es "seguridad" real (security through obscurity) pero reduce los logs en un 95 %. Los bots escanean prioritariamente el puerto 22.
sudo sed -i 's/^#Port 22/Port 2289/' /etc/ssh/sshd_config
sudo ufw delete allow 22/tcp
sudo ufw allow 2289/tcp
sudo systemctl restart ssh
# Verifica desde otra terminal ANTES de cerrar la primera:
# ssh -p 2289 ericg@TU_IP
⚠ Mantén tu terminal antigua abierta hasta que hayas verificado la conexión en el puerto nuevo. Si no, te bloqueas fuera.
Paso 2 - jail SSH fail2ban custom
Por defecto fail2ban vigila el puerto 22. A adaptar:
sudo tee /etc/fail2ban/jail.d/sshd-custom.local > /dev/null <<EOF
[sshd]
enabled = true
port = 2289
maxretry = 3
findtime = 600
bantime = 86400
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Política: 3 fallos en 10 minutos → ban 24h. Más estricta que la default (5 fallos / 1h ban) porque de todas formas no permitimos passwords - un fallo de auth = un bot.
Paso 3 - Auditar la cuota fail2ban
El jail SSH típico banea 30-80 IP/día en Contabo Nuremberg. Para verificar lo que pasa:
sudo fail2ban-client status sshd
# Currently banned IPs: 47
# Banned IP list: 185.x.x.x 91.x.x.x ...
sudo zcat /var/log/fail2ban.log* | grep "Ban " | wc -l
# Total de bans desde el inicio
Si ves >200 bans/día, puedes endurecer bantime = 604800 (1 semana) para limitar la carga IO en el servidor.
Paso 4 - Claves SSH Ed25519 + passphrase
Si aún no has generado tu clave Ed25519 en el portátil, este es el momento:
# En tu portátil
ssh-keygen -t ed25519 -C "ericg@laptop-2026" -f ~/.ssh/id_ed25519_vpn
# Elige una passphrase fuerte (tecleada 1 vez/día vía ssh-agent)
ssh-add -t 10800 ~/.ssh/id_ed25519_vpn # se olvida tras 3h
Ed25519 > RSA 4096: firmas más rápidas, claves más cortas, estado del arte en 2026. Todos los VPS Contabo Ubuntu 24.04 soportan Ed25519 de forma nativa.
Paso 5 - Desactivar ChallengeResponseAuthentication
Verifica que estas líneas están en /etc/ssh/sshd_config:
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
AuthenticationMethods publickey
Con AuthenticationMethods publickey, incluso si un CVE 0-day permite a un atacante saltar PAM, seguirá necesitando la clave. Belt and suspenders.
Tras estos 5 pasos, la mayoría de los intentos SSH automatizados se bloquean en el firewall y el resto nunca puede autenticarse (login solo por clave). Ninguno tiene éxito. Puedes dormir tranquilo.
Coste mensual: Contabo Cloud VPS 10 vs NordVPN anual
El cálculo honesto a 5 años (Contabo 5,50 €/mes, junio 2026):
| Solución | Año 1 | Año 2 | Año 3 | Año 4 | Año 5 | Total |
|---|---|---|---|---|---|---|
| NordVPN 2 años + renovaciones | 71,76 € | 0 € | 156 € | 156 € | 156 € | 539,76 € |
| Contabo Cloud VPS 10 (5,50 €/mes) | 66 € | 66 € | 66 € | 66 € | 66 € | 330 € |
Ahorro: ~210 € en 5 años, un 39 %. Y como bonus puedes alojar tu Bitwarden, tu Nextcloud, tu Umami, lo que quieras.
Limitaciones honestas del auto-alojamiento
Para ser completos:
- Streaming Netflix US, BBC iPlayer, etc.: casi nunca funciona. Netflix detecta los ASN datacenter (Contabo ASN 51167) y te sirve el catálogo local. Para streaming, mantén un NordVPN 1 año como complemento.
- Bypass DPI Irán/China: WireGuard en el puerto 51820/udp en claro es detectado por DPI sofisticado. Para esos casos, añade V2Ray o Cloak como ofuscación (ver la guía dedicada).
- Sin chat de soporte: Contabo responde por email en 24-48h. Si quieres chat en vivo, mira Hetzner Cloud (~2× el precio, soporte FR/DE/EN por chat).
- Eres el admin: si el VPS se cae, depuras tú. Lo contrario a un servicio gestionado.
Para profundizar
- Contabo vs Hetzner vs OVH: VPS Europa para self-host VPN 2026
- WireGuard vs OpenVPN en VPS: benchmarks reales 2026
- Routing VPN custom en Contabo: bypass DPI Irán/China 2026
- Generador de configuración WireGuard - genera configs de servidor + clientes listos para pegar en 30 segundos
- Calculadora de coste VPN autoalojado - compara Contabo vs NordVPN a 1, 2 y 5 años
- Comparador VPS interactivo - filtra Contabo/Hetzner/OVH por latencia, RAM y precio a 24 meses
- Fuentes oficiales: Whitepaper WireGuard, Documentación VPS Contabo, Guía de hardening Ubuntu 24.04
Artículo publicado el 2026-06-02, última actualización 2026-06-03 (añadido: playbook Ansible idempotente, monitorización UptimeRobot gratuita en 3 endpoints, hardening SSH fail2ban + Ed25519). Última verificación del script bootstrap en Ubuntu 24.04 LTS el 2026-06-03. Si el procedimiento falla, abre una issue en nuestro GitHub o escribe a contact@vpnsmith.com.
★ Datacenter Núremberg GDPR · ✓ IPv4 dedicada incluida · 200+ Mbps garantizados
Aloja tu VPN en tu propio VPS → ContaboAcceso root completo · IPv4 pública · elige tu región→

