Instalar y asegurar phpMyAdmin con Nginx en Debian 13
phpMyAdmin te da una interfaz web para gestionar tus bases de datos MariaDB o MySQL sin escribir consultas SQL. Esta guía explica cómo instalar phpMyAdmin en Debian 13 detrás de Nginx, con HTTPS, acceso restringido y protección contra los ataques de fuerza bruta. Sin protección, phpMyAdmin atrae enseguida a los bots que rastrean la web.
Necesitas un VPS con Debian 13 y acceso sudo y, para HTTPS, un subdominio que apunte a su IP, por ejemplo pma.example.com.
Preparar Debian 13
Actualiza el sistema y reinicia si el núcleo ha cambiado.
sudo apt update && sudo apt -y full-upgrade
sudo reboot
Instala Nginx, PHP-FPM y las extensiones que necesita phpMyAdmin. Debian 13 trae PHP 8.4.
sudo apt install -y nginx php-fpm php-cli php-mbstring php-xml php-zip php-curl php-mysql php-gd php-intl php-bcmath
sudo apt install -y php-imagick php-apcu
Comprueba la versión de PHP y el socket de PHP-FPM. Los necesitarás en la configuración de Nginx.
php -v
ls -l /run/php/ | grep fpm
# En Debian 13, el socket se llama php8.4-fpm.sock
La guía Nginx y PHP-FPM en un VPS Linux explica esta pila y sus ajustes.
Instalar y proteger MariaDB
sudo apt install -y mariadb-server mariadb-client
sudo mariadb-secure-installation
En Debian 13, el asistente se llama mariadb-secure-installation. El nombre antiguo, mysql_secure_installation, solo existe si está instalado el paquete mariadb-client-compat. Responde así a las preguntas.
Mantén la autenticación de root por socket Unix. La cuenta root de SQL solo será accesible con
sudoen el VPS.Elimina los usuarios anónimos.
Prohíbe la conexión remota de root.
Borra la base de datos de prueba y recarga los privilegios.
Crear un usuario propio
No entres en phpMyAdmin con root. Crea una cuenta de administración aparte. Abre la consola SQL.
sudo mariadb
Escribe después estas consultas, con tu propia contraseña.
CREATE USER 'pma_admin'@'localhost' IDENTIFIED BY 'StrongPassword_ChangeMe';
GRANT ALL PRIVILEGES ON *.* TO 'pma_admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;
Con esta cuenta te conectarás a phpMyAdmin.
Instalar phpMyAdmin
Con apt
El paquete de Debian 13 es el más fácil de mantener, porque sigue las actualizaciones del sistema.
sudo apt install -y phpmyadmin
Cuando pregunte por el servidor web, no marques nada. Nginx se configura más abajo. Acepta dbconfig-common y elige una contraseña para el usuario interno pma. Los archivos van a /usr/share/phpmyadmin y la configuración a /etc/phpmyadmin/config.inc.php.
Con el archivo oficial
El archivo te da la última versión publicada en phpmyadmin.net. Las actualizaciones corren de tu cuenta.
sudo mkdir -p /var/www/pma && cd /var/www/pma
sudo wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz
sudo tar xzf phpMyAdmin-*-all-languages.tar.gz
sudo mv phpMyAdmin-*-all-languages phpmyadmin
sudo chown -R www-data:www-data /var/www/pma/phpmyadmin
Crea el archivo de configuración y genera la clave secreta de las cookies. Debe medir exactamente 32 bytes, es decir, 64 caracteres hexadecimales.
sudo -u www-data cp /var/www/pma/phpmyadmin/config.sample.inc.php /var/www/pma/phpmyadmin/config.inc.php
openssl rand -hex 32
sudo -u www-data nano /var/www/pma/phpmyadmin/config.inc.php
Pega el valor generado en lugar del valor de ejemplo.
$cfg['blowfish_secret'] = sodium_hex2bin('f16ce59f45714194371b48fe362072dc3b019da7861558cd4ad29e4d6fb13851');
Con este método, cambia /usr/share/phpmyadmin por /var/www/pma/phpmyadmin en la configuración de Nginx.
Configurar Nginx
Un subdominio propio es la opción más limpia. Las restricciones de acceso se aplican entonces a todo phpMyAdmin, scripts PHP incluidos.
En un subdominio propio
Crea el archivo /etc/nginx/sites-available/pma.conf. Empieza funcionando en HTTP. Certbot añadirá HTTPS en el paso siguiente.
server {
listen 80;
listen [::]:80;
server_name pma.example.com;
root /usr/share/phpmyadmin;
index index.php;
access_log /var/log/nginx/pma.access.log;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy no-referrer-when-downgrade always;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 120s;
}
location ~* \.(?:css|js|ico|gif|jpe?g|png|svg)$ {
access_log off;
expires 7d;
}
}
Activa el sitio, prueba la configuración y recarga Nginx.
sudo ln -s /etc/nginx/sites-available/pma.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
En un sitio existente, bajo /phpmyadmin
Añade estos bloques en el bloque server del sitio, antes de su bloque location ~ \.php$. Nginx prueba los bloques con expresiones regulares en el orden del archivo.
location /phpmyadmin {
alias /usr/share/phpmyadmin;
index index.php;
try_files $uri $uri/ /phpmyadmin/index.php?$args;
}
location ~ ^/phpmyadmin/(.+\.php)$ {
alias /usr/share/phpmyadmin/$1;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
fastcgi_read_timeout 120s;
}
location ~* ^/phpmyadmin/(.+\.(?:png|jpg|jpeg|gif|css|js|ico|svg))$ {
alias /usr/share/phpmyadmin/$1;
access_log off;
expires 7d;
}
Con este método, una restricción puesta en
location /phpmyadminno cubre los scripts PHP, que trata el bloque siguiente. Para restringir el acceso, mejor usa el subdominio.
Activar HTTPS con Let's Encrypt
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d pma.example.com
Certbot obtiene el certificado, añade la escucha en HTTPS al bloque server y redirige HTTP a HTTPS. Escribe líneas como estas en pma.conf.
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pma.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pma.example.com/privkey.pem; # managed by Certbot
Para activar HTTP/2, añade la línea http2 on; en este bloque server y recarga Nginx. Desde Nginx 1.25, la opción http2 ya no va en la línea listen. Comprueba por último que la renovación automática está activa.
systemctl status certbot.timer
La guía Certbot: instalar un SSL de Let's Encrypt en un VPS trata los demás casos.
Restringir el acceso a phpMyAdmin
Crea primero el archivo de contraseñas de la autenticación HTTP. Pide credenciales antes incluso de la página de inicio de sesión de phpMyAdmin.
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd-pma admin
En /etc/nginx/nginx.conf, añade una zona de limitación de peticiones en el bloque http.
limit_req_zone $binary_remote_addr zone=pma_limit:10m rate=5r/s;
Añade después estas líneas en el bloque server de pma.conf que escucha en el 443, el que modificó Certbot. Cambia 198.51.100.20 por tu IP fija.
# Bloquear el asistente de configuración
location ^~ /setup { deny all; }
# Solo pasa tu IP
allow 198.51.100.20;
deny all;
# Credenciales HTTP además de las de phpMyAdmin
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd-pma;
# Limitar el ritmo de peticiones
limit_req zone=pma_limit burst=20 nodelay;
En un sitio existente, bloquea el asistente con location ^~ /phpmyadmin/setup { deny all; }. Prueba y recarga Nginx después de cada cambio.
sudo nginx -t && sudo systemctl reload nginx
Por último, comprueba en el archivo config.inc.php que phpMyAdmin solo puede llegar al servidor local. Es el valor por defecto y evita los ataques de tipo SSRF.
$cfg['AllowArbitraryServer'] = false;
Frenar la fuerza bruta con Fail2ban y UFW
Fail2ban bloquea las direcciones que fallan demasiadas veces. El filtro siguiente lee el registro del subdominio y cuenta los rechazos de Nginx, códigos 401 (credenciales HTTP incorrectas) y 403 (IP rechazada). La guía Instalar y configurar Fail2ban presenta la herramienta.
sudo apt install -y fail2ban
Crea el filtro /etc/fail2ban/filter.d/nginx-phpmyadmin.conf.
[Definition]
failregex = ^<HOST> -[^"]*"(?:GET|POST) /\S* HTTP/[^"]*" (?:401|403)\s
ignoreregex =
Crea la regla /etc/fail2ban/jail.d/nginx-phpmyadmin.local.
[nginx-phpmyadmin]
enabled = true
port = http,https
filter = nginx-phpmyadmin
logpath = /var/log/nginx/pma.access.log
maxretry = 8
findtime = 10m
bantime = 1h
Prueba el filtro con el registro, reinicia Fail2ban y comprueba la regla.
sudo fail2ban-regex /var/log/nginx/pma.access.log /etc/fail2ban/filter.d/nginx-phpmyadmin.conf
sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-phpmyadmin
Por último, cierra todo lo demás con UFW. La guía Cómo configurar el firewall UFW en Ubuntu y Debian explica estas reglas.
sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
Resolver los errores frecuentes
502 Bad Gateway
Nginx no llega a PHP-FPM. Comprueba el socket y el servicio.
ls -l /run/php/php8.4-fpm.sock
sudo systemctl status php8.4-fpm
403 Forbidden
Tu IP no está en la lista allow, o los permisos de los archivos no son correctos. Con el archivo oficial, la carpeta debe pertenecer a www-data.
sudo chown -R www-data:www-data /var/www/pma/phpmyadmin
Importaciones grandes que fallan
Sube los límites de PHP en /etc/php/8.4/fpm/php.ini.
upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 300
memory_limit = 512M
Añade también client_max_body_size 512M; en el bloque server de Nginx. Después reinicia PHP-FPM y recarga Nginx.
sudo systemctl restart php8.4-fpm
sudo systemctl reload nginx
Token CSRF no válido
Comprueba que la clave blowfish_secret está definida, que tu navegador acepta las cookies y que el reloj del VPS está sincronizado. El comando timedatectl muestra su estado.
¿Necesitas ayuda?
Abre un ticket desde Tickets › Abrir un ticket, o desde el recuadro Contactar con el soporte al pie de la ficha del VPS. En el campo Servicio afectado, elige el VPS para que el equipo gane tiempo. También puedes preguntar en el Discord de OuiHeberg.
Acceso root, la distribución que elijas y gestión desde el área de cliente de OuiHeberg.
Ver ofertas →