Dedicated Servers & VPSFebruary 6, 2026 16 views

Install and secure phpMyAdmin with Nginx on Debian 13

Install and secure phpMyAdmin with Nginx on Debian 13

Install and Secure phpMyAdmin with Nginx on Debian 13

Managing your MySQL/MariaDB databases via the command line is powerful but not always practical. phpMyAdmin provides you with a web interface to view, modify, and administer your databases without typing SQL queries by hand. The problem is that if misconfigured, phpMyAdmin becomes a gateway for attacks.

This guide shows you how to properly install phpMyAdmin behind Nginx on Debian 13 (Trixie), with HTTPS, access restrictions, and protections against brute force attacks. A configuration designed for production, not just for a test lab.


What You Need Before You Start

  • A Debian 13 (Trixie) server with sudo access
  • Ports 80 and 443 open
  • A domain name pointing to your server (recommended for HTTPS)

Debian 13 comes with PHP 8.3 by default. Check your version:

php -v

Note the version number, you will need it for the configuration file paths.


Update the System

We always start with this:

sudo apt update && sudo apt -y full-upgrade
sudo reboot

Install Nginx, PHP-FPM, and Necessary Extensions

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

Check that the PHP-FPM socket exists:

ls -l /run/php/ | grep fpm
# You should see something like: php8.3-fpm.sock

Install and Secure MariaDB

sudo apt install -y mariadb-server mariadb-client
sudo mysql_secure_installation

During the security assistant:

  • Set a strong SQL root password
  • Remove anonymous users
  • Disable remote root login
  • Remove the test database
  • Reload privileges

Create a Dedicated User for phpMyAdmin

Using the SQL root account for phpMyAdmin is a bad idea. Create a dedicated admin account:

sudo mysql

In the SQL shell:

CREATE USER 'pma_admin'@'localhost' IDENTIFIED BY 'YourStrongPassword!';
GRANT ALL PRIVILEGES ON *.* TO 'pma_admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

This is the account you will use to log in to phpMyAdmin.


Install phpMyAdmin

Two options depending on your preferences.

Option A: via apt (simple and quick)

sudo apt install -y phpmyadmin

During the installation:

  • When asked about the web server, do not check anything (we configure Nginx manually)
  • Accept dbconfig-common and set a password for the internal user pma

The files are installed in /usr/share/phpmyadmin.

Option B: via the official archive (newer version)

cd /var/www
sudo mkdir -p pma && cd pma
wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-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

Create the configuration file:

sudo -u www-data cp /var/www/pma/phpmyadmin/config.sample.inc.php /var/www/pma/phpmyadmin/config.inc.php
sudo -u www-data nano /var/www/pma/phpmyadmin/config.inc.php

Generate a secret key of at least 32 characters and add it:

$cfg['blowfish_secret'] = 'PutAUniqueAndLongSecretPhraseHere!!!!';

Configure Nginx

Two possible approaches: an alias /phpmyadmin on an existing vhost, or a dedicated subdomain pma.yourdomain.com. The latter is cleaner for managing access restrictions.

Option A: Alias on an existing vhost

Add these blocks to your existing Nginx configuration:

location /phpmyadmin {
    alias /usr/share/phpmyadmin;  # or /var/www/pma/phpmyadmin if using method B
    index index.php;
    try_files $uri $uri/ /phpmyadmin/index.php?$args;
}

location ~ ^/phpmyadmin/(.+\.php)$ {
    alias /usr/share/phpmyadmin;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_read_timeout 120s;
}

location ~* ^/phpmyadmin/(.+\.(?:png|jpg|jpeg|gif|css|js|ico|svg))$ {
    alias /usr/share/phpmyadmin;
    access_log off;
    expires 7d;
}

Option B: Dedicated subdomain (recommended)

Create /etc/nginx/sites-available/pma.conf:

server {
    listen 80;
    server_name pma.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name pma.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/pma.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pma.yourdomain.com/privkey.pem;

    root /usr/share/phpmyadmin;
    index index.php;

    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.3-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;
    }
}

Enable the config and test:

sudo ln -s /etc/nginx/sites-available/pma.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Enable HTTPS with Let's Encrypt

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d pma.yourdomain.com

Check that automatic renewal is active:

systemctl status certbot.timer

Secure phpMyAdmin

Block Access to /setup

location ^~ /phpmyadmin/setup { deny all; }
# or for a dedicated vhost:
location ^~ /setup { deny all; }

Disable AllowArbitraryServer

In config.inc.php, ensure this option is disabled to prevent SSRF attacks:

$cfg['AllowArbitraryServer'] = false;

Adjust PHP Limits

To be able to import large databases, edit /etc/php/8.3/fpm/php.ini:

upload_max_filesize = 512M
post_max_size = 512M
max_execution_time = 300
memory_limit = 512M

Restart PHP-FPM:

sudo systemctl restart php8.3-fpm

Restrict Access by IP and HTTP Password

IP Whitelist

location /phpmyadmin {
    allow 203.0.113.10;   # your fixed IP
    deny all;
    alias /usr/share/phpmyadmin;
    index index.php;
}

HTTP Basic Authentication

Create the password file:

sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd-pma admin

Add to the Nginx config:

location /phpmyadmin {
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/.htpasswd-pma;
    alias /usr/share/phpmyadmin;
    index index.php;
    try_files $uri $uri/ /phpmyadmin/index.php?$args;
}

Tip: Combine IP whitelist + HTTP auth for a double layer of security.


Protect Against Brute Force with Fail2ban

Rate-limit Nginx

In /etc/nginx/nginx.conf, add in the http block:

limit_req_zone $binary_remote_addr zone=pma_limit:10m rate=5r/s;

In your server block:

location /phpmyadmin/ {
    limit_req zone=pma_limit burst=20 nodelay;
}

Configure Fail2ban

sudo apt install -y fail2ban

Create the filter /etc/fail2ban/filter.d/nginx-phpmyadmin.conf:

[Definition]
failregex = ^<HOST> - .* "(GET|POST) /phpmyadmin.*" .* (401|403) .*$
ignoreregex =

Create the jail /etc/fail2ban/jail.d/nginx-phpmyadmin.local:

[nginx-phpmyadmin]
enabled = true
port    = http,https
filter  = nginx-phpmyadmin
logpath = /var/log/nginx/access.log
maxretry = 8
findtime = 10m
bantime  = 1h

Restart Fail2ban:

sudo systemctl restart fail2ban
sudo fail2ban-client status nginx-phpmyadmin

Enable the UFW Firewall

sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

Common Troubleshooting

502 Bad Gateway Error

The PHP-FPM socket is not accessible. Check:

ls -l /run/php/php8.3-fpm.sock
sudo systemctl status php8.3-fpm

403 Forbidden Error

Permission or configuration issue with alias/root. Ensure the folder belongs to www-data:

sudo chown -R www-data:www-data /usr/share/phpmyadmin

Timeout on Large Imports

Increase client_max_body_size in the Nginx server block and fastcgi_read_timeout.

Invalid CSRF Token

Ensure that the blowfish_secret is set, that cookies are working, and that the system clock is synchronized (timedatectl).


Final Checklist

  • Updated Debian 13 system
  • Functional Nginx and PHP-FPM 8.3
  • Secured MariaDB with mysql_secure_installation
  • phpMyAdmin accessible via HTTPS
  • Restricted access (IP and/or HTTP Auth)
  • Rate-limit and Fail2ban active
  • Configured UFW firewall
  • Scheduled backups

In Summary

Installing phpMyAdmin on Debian 13 with Nginx is quite straightforward. The real added value of this guide is the security part: HTTPS, access restrictions, brute force protection. An exposed phpMyAdmin without protection is an easy target for bots that constantly scan the web.

Need a VPS to host all this? OuiHeberg offers Linux VPS with Debian pre-installed, ready to host your LEMP stack and phpMyAdmin in just a few minutes.