Tema
Configurar un VPS desde cero
Un VPS recién creado es como una casa nueva sin cerraduras: funciona, pero cualquiera puede intentar entrar. En esta lección vas a crear un servidor Ubuntu y dejarlo seguro y listo para alojar sitios: usuario administrador, SSH con llaves, firewall, actualizaciones automáticas y más.
Concepto
El proceso estándar de "primeros 15 minutos" en cualquier VPS es:
- Crear el servidor con tu llave SSH.
- Actualizar el sistema.
- Crear un usuario con
sudo(no trabajar como root). - Endurecer SSH.
- Activar el firewall (ufw).
- Ajustes: zona horaria, swap, actualizaciones automáticas, fail2ban.
- Apuntar el dominio.
Lo harás una vez a mano para entenderlo y al final tendrás un script que lo automatiza.
Paso 1: crear el VPS
En el proveedor que elijas (DigitalOcean, Hetzner, Vultr, Linode, Contabo, Hostinger VPS):
- Sistema: Ubuntu 24.04 LTS (soporte hasta 2029).
- Plan: 1 vCPU / 1–2 GB RAM basta para empezar con varios sitios pequeños.
- Región: la más cercana a los usuarios del cliente.
- Autenticación: SSH key → pega tu llave pública (ver SSH y llaves).
- Nombre: algo descriptivo, p. ej.
web-clientes-01.
Anota la IP pública. Usaremos 203.0.113.10 como ejemplo.
Paso 2: primer acceso y actualización
bash
# Desde tu computadora
ssh root@203.0.113.10
# Ya en el servidor: actualizar todo
apt update && apt upgrade -y
# Si pide reiniciar (kernel nuevo)
rebootPaso 3: crear tu usuario administrador
bash
# Crear el usuario (te pedirá contraseña: úsala para sudo)
adduser deploy
# Darle permisos de administrador
usermod -aG sudo deploy
# Copiar las llaves autorizadas de root al nuevo usuario
rsync --archive --chown=deploy:deploy ~/.ssh /home/deployEn otra terminal de tu computadora, comprueba:
bash
ssh deploy@203.0.113.10
sudo whoami # debe responder: rootPaso 4: endurecer SSH
bash
sudo nano /etc/ssh/sshd_configtxt
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication nobash
# Revisa si un archivo en sshd_config.d reactiva las contraseñas
grep -r "PasswordAuthentication" /etc/ssh/sshd_config.d/
sudo sshd -t && sudo systemctl restart sshPrueba antes de cerrar
Mantén abierta tu sesión actual y abre una nueva con ssh deploy@203.0.113.10. Si entra, todo bien. Si no, corrige desde la sesión que sigue abierta.
Paso 5: firewall con ufw
ufw (Uncomplicated Firewall) bloquea todo excepto los puertos que permitas.
bash
# Política por defecto: bloquear entradas, permitir salidas
sudo ufw default deny incoming
sudo ufw default allow outgoing
# ¡PRIMERO permite SSH o te quedarás fuera!
sudo ufw allow OpenSSH
# Web
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Activar
sudo ufw enable
# Ver reglas
sudo ufw status verboseMás adelante, al instalar Nginx o Apache, puedes usar sus perfiles: sudo ufw allow 'Nginx Full' o sudo ufw allow 'Apache Full'.
Error común
Abrir el puerto de MySQL (3306) o PostgreSQL (5432) a todo internet "para conectarme desde mi casa". Nunca. Usa un túnel SSH:
bash
# En tu computadora: el puerto 3307 local apunta al 3306 del servidor
ssh -L 3307:127.0.0.1:3306 deploy@203.0.113.10
# Luego conecta tu cliente (DBeaver, TablePlus, Workbench) a 127.0.0.1:3307Docker y ufw
Docker manipula iptables directamente y los puertos publicados con -p se saltan ufw. Lo verás en Docker: publica servicios internos solo en 127.0.0.1.
Paso 6: ajustes recomendados
Zona horaria y nombre del host
bash
sudo timedatectl set-timezone America/Mexico_City
timedatectl
sudo hostnamectl set-hostname web-clientes-01Swap (memoria de respaldo)
En VPS con 1–2 GB de RAM, un archivo swap evita que procesos como npm install o composer maten al servidor por falta de memoria.
bash
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# Hacerlo permanente
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# Usar swap solo cuando haga falta
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --system
free -hActualizaciones de seguridad automáticas
bash
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades # responde "Yes"
# Ver configuración
cat /etc/apt/apt.conf.d/20auto-upgradesDebe contener:
txt
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";Fail2ban
bash
sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdHerramientas útiles
bash
sudo apt install -y git curl wget unzip htop ncduPaso 7: apuntar el dominio
En el panel DNS:
txt
A @ 203.0.113.10
CNAME www tudominio.com.Comprueba con dig +short tudominio.com. Ya puedes instalar Nginx o Apache.
Ejemplo: script de configuración inicial
Guárdalo como setup-vps.sh, súbelo y ejecútalo como root en un servidor nuevo. Revísalo y ajusta las variables antes de usarlo.
bash
#!/usr/bin/env bash
# setup-vps.sh — configuración inicial de Ubuntu 24.04
# Uso: bash setup-vps.sh
set -euo pipefail
NUEVO_USUARIO="deploy"
ZONA_HORARIA="America/Mexico_City"
SWAP_GB=2
echo "==> Actualizando sistema"
apt update && apt upgrade -y
apt install -y ufw fail2ban unattended-upgrades git curl wget unzip htop
echo "==> Creando usuario $NUEVO_USUARIO"
if ! id "$NUEVO_USUARIO" &>/dev/null; then
adduser --disabled-password --gecos "" "$NUEVO_USUARIO"
usermod -aG sudo "$NUEVO_USUARIO"
# sudo sin contraseña (cómodo para automatizar; quítalo si prefieres pedirla)
echo "$NUEVO_USUARIO ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-$NUEVO_USUARIO
chmod 440 /etc/sudoers.d/90-$NUEVO_USUARIO
fi
rsync --archive --chown="$NUEVO_USUARIO:$NUEVO_USUARIO" /root/.ssh "/home/$NUEVO_USUARIO"
echo "==> Endureciendo SSH"
cat > /etc/ssh/sshd_config.d/99-seguro.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF
# Desactivar archivos del proveedor que reactiven contraseñas
sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config.d/*.conf || true
sshd -t && systemctl restart ssh
echo "==> Firewall"
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
echo "==> Zona horaria"
timedatectl set-timezone "$ZONA_HORARIA"
echo "==> Swap de ${SWAP_GB}G"
if [ ! -f /swapfile ]; then
fallocate -l "${SWAP_GB}G" /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
echo 'vm.swappiness=10' > /etc/sysctl.d/99-swappiness.conf
sysctl --system >/dev/null
fi
echo "==> Actualizaciones automáticas y fail2ban"
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
systemctl enable --now fail2ban
echo "==> Listo. Prueba en otra terminal: ssh $NUEVO_USUARIO@$(curl -s https://ifconfig.me)"Buena práctica
Guarda este script en un repositorio privado. Cada servidor nuevo quedará configurado igual en dos minutos. Herramientas como Ansible o cloud-init llevan esta idea al siguiente nivel.
Checklist del VPS
- [ ] Ubuntu LTS actualizado
- [ ] Usuario con sudo, sin trabajar como root
- [ ] Acceso solo con llave SSH, root deshabilitado
- [ ] ufw activo con solo 22, 80 y 443
- [ ] Bases de datos sin puertos públicos
- [ ] Zona horaria correcta
- [ ] Swap configurado
- [ ] unattended-upgrades y fail2ban activos
- [ ] Snapshots o respaldos activados en el proveedor
- [ ] Dominio apuntando a la IP
Ejercicios
- Escribe los comandos para permitir en ufw el puerto 2222 (SSH personalizado) y quitar la regla de OpenSSH.
- Tu servidor tiene 1 GB de RAM y
npm run buildse muere con "Killed". ¿Qué haces? - ¿Por qué se recomienda un usuario normal con sudo en lugar de trabajar como root?
Ver solución
- Primero cambias
Port 2222ensshd_configy luego:
bash
sudo ufw allow 2222/tcp
sudo systemctl restart ssh
# prueba: ssh -p 2222 deploy@IP — y solo entonces:
sudo ufw delete allow OpenSSH- Es falta de memoria: crea un swap de 2 GB (sección Swap) o compila en tu computadora / en CI y sube solo el resultado.
- Porque un error con root no tiene red de seguridad, los bots atacan siempre al usuario root, y
sudodeja registro de quién hizo qué.
Resumen
- Crea el VPS con Ubuntu LTS y tu llave SSH.
- Actualiza, crea un usuario sudo y desactiva root y contraseñas.
- ufw: denegar todo, permitir OpenSSH, 80 y 443.
- Añade swap, zona horaria, unattended-upgrades y fail2ban.
- Automatiza todo con un script para repetirlo en cada servidor.
- Siguiente: Apache.