EQVPS
PanelEmpezar

Cómo instalar MySQL en un VPS: usuarios, acceso remoto seguro, menos RAM y copias de seguridad

Instala MySQL 8.0 en un VPS con Ubuntu 24.04, crea una base de datos y un usuario para tu aplicación, accede desde tu ordenador sin abrir el puerto 3306, baja su memoria en reposo de 383 MB a 165 MB y haz copias cada noche con un script que falla de forma visible.

Instalar MySQL lleva un comando. La mayor parte del trabajo viene después: un usuario para la aplicación, una forma de llegar a la base desde tu ordenador sin poner el puerto 3306 en internet, ajustes de memoria para un servidor pequeño y copias que se hagan sin ti. Esta guía cubre las cuatro cosas en Ubuntu 24.04. Cada paso se ejecutó en nuestra imagen de Ubuntu 24.04, y las cifras de abajo salen de ese servidor.

Ejecuta los comandos con un usuario que tenga sudo. La guía de configuración de Ubuntu crea uno.

1. Instala

sudo apt update
sudo apt install -y mysql-server
mysql --version

En nuestro servidor la instalación tardó 51 segundos y nos dio MySQL 8.0.46. Arranca enseguida, vuelve a arrancar en cada inicio y escucha solo en el propio servidor: 127.0.0.1:3306 para las conexiones normales y 127.0.0.1:33060 para el protocolo X, más nuevo. Desde fuera todavía no se puede alcanzar nada.

2. Crea una base de datos y un usuario

La cuenta root de MySQL usa autenticación por socket en Ubuntu, así que sudo mysql te conecta sin contraseña. Crea una base de datos y un usuario para tu aplicación:

sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;

Pruébalo como se conectará tu aplicación:

mysql -u app -p app -e "SELECT CURRENT_USER();"

Debería mostrar app@localhost. Una contraseña incorrecta da ERROR 1045 (28000): Access denied for user 'app'@'localhost'. El usuario puede hacer de todo dentro de app y nada fuera.

3. Conéctate desde tu ordenador: túnel SSH

Para usar un cliente de escritorio como DBeaver, MySQL Workbench o la línea de comandos mysql en tu equipo, no abras ningún puerto. Redirige uno por SSH:

ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP

En un plan NAT, añade -p y el puerto SSH personal de tu panel. Mientras esa ventana esté abierta, apunta tu cliente al host 127.0.0.1, puerto 3307, usuario app. En el lado local usamos 3307 para no chocar con un MySQL que puedas tener en tu ordenador. En nuestra prueba el servidor respondió enseguida por el túnel, mientras que una conexión directa a su dirección en el 3306 se rechazó.

4. Acceso directo para otro servidor

A veces la aplicación corre en un segundo servidor y tiene que conectarse directamente. Para eso la base necesita un plan con IPv4 propia, porque un plan NAT solo redirige tu puerto SSH. Tres cambios, todos limitados a la dirección del servidor de la aplicación (aquí 203.0.113.20):

sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';

Si ufw aún no está activado, permite primero SSH (sudo ufw allow OpenSSH) y luego ejecuta sudo ufw enable. La guía de ufw tiene los detalles.

Comprobamos los dos cerrojos por separado. Con la regla del firewall pero sin un usuario de MySQL que coincidiera, el servidor rechazó con error 1130: Host '…' is not allowed to connect to this MySQL server. Con el usuario añadido, la conexión pasó. Sin la regla del firewall, la conexión simplemente agotó el tiempo de espera. Cualquier otra dirección de internet obtiene ese mismo tiempo agotado.

5. Usa menos RAM

En reposo y sin datos propios, MySQL 8.0 usaba 383 MB en nuestro servidor. Casi todo es el Performance Schema, una función de diagnóstico que reserva memoria por adelantado. En un VPS pequeño, desactívalo y fija tú el tamaño de la caché principal:

sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld

Tras el reinicio usaba 165 MB. El buffer pool guarda en caché tus datos e índices, y 256 MB encajan en un servidor de 2 GB que también ejecuta la aplicación. Súbelo si la base es lo principal del servidor y ya supera el tamaño de la caché. max_connections = 50 es de sobra para una aplicación con pool de conexiones. Pierdes las estadísticas de performance_schema. Vuelve a activarlo si algún día necesitas analizar a fondo consultas lentas.

6. Copias de seguridad nocturnas

mysqldump --single-transaction saca una copia coherente de las tablas InnoDB sin bloquear la aplicación. Ponlo en un pequeño script:

sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql

Cada línea tiene su motivo:

  • umask 077 hace que el volcado solo lo pueda leer root (-rw-------), ya que contiene todos tus datos.
  • pipefail hace que todo el script falle si falla mysqldump. Sin él, gzip escribiría un archivo diminuto y vacío y diría que todo fue bien. Rompimos el comando a propósito y el script terminó con el código 2, como debe ser.
  • find … -mtime +14 -delete guarda dos semanas de copias.
  • El script se ejecuta como root, así que mysqldump entra por el socket y no hay ninguna contraseña guardada en un archivo.

Una copia que nunca has restaurado todavía no cuenta. Restáurala en una base de datos temporal y mira los datos:

sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"

En nuestra prueba, la tabla restaurada tenía las mismas filas que la original. Las copias en el mismo disco no te protegen si pierdes el servidor, así que llévalas de vez en cuando a otra máquina con scp o restic. Managed Backups añade además puntos de restauración diarios de todo el servidor.

Qué plan elegir

Micro (2 vCPU, 2 GB, 25 GB, $5/mes) aguanta MySQL ajustado como arriba más una aplicación web. Si la base en sí pasa de unos pocos gigas, Small con 4 GB y 35 GB por $8/mes te deja dar 1 GB o más al buffer pool. Ambos son planes NAT, y el túnel SSH del paso 3 funciona en ellos. El paso 4 requiere IPv4 propia: Micro-IP cuesta $10/mes.

¿Prefieres PostgreSQL? La guía de PostgreSQL sigue el mismo plan. Todos los planes están en VPS, y el pago es en USDT, USDC o ETH en Base, Ethereum o Polygon.

Preguntas frecuentes

¿MySQL o MariaDB?

Ambos están en los repositorios propios de Ubuntu 24.04: mysql-server instala MySQL 8.0 y mariadb-server instala MariaDB 10.11. La mayoría de las aplicaciones que piden «MySQL» funcionan con cualquiera. Usa el que indique la documentación de tu aplicación, y MySQL 8.0 si le da igual. Esta guía usa MySQL.

¿Cuál es la contraseña de root de MySQL?

No hay ninguna. En Ubuntu, la cuenta root de MySQL usa autenticación por socket: sudo mysql te conecta como root, y nadie puede entrar como root por la red. Déjalo así y crea usuarios separados para tus aplicaciones.

¿Debo abrir el puerto 3306 a internet?

No. Los puertos de bases de datos abiertos se escanean y reciben intentos de contraseña todo el tiempo. Conéctate desde tu ordenador a través de un túnel SSH. Si otro servidor tiene que conectarse directamente, permite solo su IP, tanto en MySQL como en el firewall.

¿Cuánta RAM necesita MySQL?

Recién instalado, MySQL 8.0 usaba 383 MB en nuestro servidor de prueba sin bases propias. Al desactivar el Performance Schema y fijar un buffer pool modesto, bajó a 165 MB. El plan Micro de 2 GB mueve MySQL y una aplicación sin problema; con ese ajuste, 1 GB sirve para un sitio pequeño.

¿Tengo que ejecutar mysql_secure_installation?

En Ubuntu 24.04 casi todo su trabajo ya está hecho. Nuestra instalación nueva no tenía usuarios anónimos ni base de datos de prueba, y root solo puede entrar por el socket local. Ejecútalo si quieres el componente de comprobación de contraseñas que ofrece; si no, puedes saltártelo.

Comentarios

Aún no hay comentarios. Sé el primero.

Deja un comentario

Los comentarios se moderan antes de aparecer.