phpMyAdmin is the classic web interface for MySQL and MariaDB: browse tables, run queries, import and export. It’s also one of the most attacked URLs on the internet, so installing it is easy — and securing it is the part that matters.

Do you need it? For occasional admin work, a desktop client (DBeaver, TablePlus, HeidiSQL, MySQL Workbench) over an SSH tunnel is more secure, since nothing web-facing is added. If you or your team need a browser-based tool, follow the steps below.

1. Install

Ubuntu and Debian package phpMyAdmin:

sudo apt update
sudo apt install -y phpmyadmin php-mbstring php-zip php-gd php-json php-curl

The installer asks:

  • Web server to configure automatically — choose none (press Tab, then Enter). It offers Apache and lighttpd only; we’ll configure Nginx ourselves.
  • Configure database with dbconfig-common — Yes. It creates a phpmyadmin control database and user for advanced features.

Files land in /usr/share/phpmyadmin. The packaged version receives security updates through apt, which is the main reason to prefer it over a manual download.

2. Create a user to log in with

On Ubuntu, MySQL/MariaDB root uses socket authentication and can’t log in through phpMyAdmin. Create a password-based account instead:

CREATE USER 'dbadmin'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON *.* TO 'dbadmin'@'localhost' WITH GRANT OPTION;

Or, better, log in with each application’s own user, which only sees its own database. See MySQL users and privileges.

3. Nginx config with a non-obvious path

Bots probe /phpmyadmin, /pma, /phpMyAdmin and dozens of variants all day. Use a path of your own. Inside an existing HTTPS server block (or a dedicated admin subdomain):

location ^~ /db-a8f3/ {
    alias /usr/share/phpmyadmin/;
    index index.php;

    # Access control — see step 4
    allow 198.51.100.25;
    deny all;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    location ~ ^/db-a8f3/(libraries|setup|templates|locale|sql)/ {
        deny all;
    }
}

The ^~ modifier stops other regex locations (like the site’s general \.php$ block) from catching these requests, and $request_filename resolves correctly with alias.

sudo nginx -t && sudo systemctl reload nginx

Open https://example.com/db-a8f3/ — over HTTPS only, since you’re sending database passwords.

4. Restrict access (pick at least one)

IP allow-list (above) — the strongest simple option if you have a fixed IP.

HTTP basic auth in front of phpMyAdmin’s own login:

sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd-pma alice
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd-pma;

Add these inside the location ^~ /db-a8f3/ block. Bots never reach the phpMyAdmin login page.

SSH tunnel only — bind phpMyAdmin to a server block listening on 127.0.0.1:8081 and reach it with ssh -L 8081:127.0.0.1:8081 user@server. Nothing is exposed publicly.

5. Harden phpMyAdmin’s config

Edit /etc/phpmyadmin/config.inc.php (or add a file in /etc/phpmyadmin/conf.d/):

$cfg['Servers'][$i]['AllowRoot'] = false;          // no root logins
$cfg['LoginCookieValidity'] = 1800;                // 30-minute sessions

The Debian package generates the blowfish_secret used to encrypt cookies automatically.

6. Larger imports

Import size is limited by PHP’s upload_max_filesize/post_max_size and Nginx’s client_max_body_size. For large SQL files, skip the browser entirely and import from the shell — it’s faster and has no limits:

mysql -u dbadmin -p shop < dump.sql

7. Keep it updated

Updates come with your regular sudo apt upgrade. If you installed phpMyAdmin manually from a tarball, you must update it manually too — a frequently forgotten task that leaves vulnerable versions online for years.

Troubleshooting

  • #1698 - Access denied for user 'root'@'localhost' — root uses socket auth; log in with the user from step 2.
  • Page downloads instead of running — PHP isn’t being passed to PHP-FPM; check the nested \.php$ block and the socket path.
  • 404 on the login page — the alias path or trailing slashes don’t match; both the location and the alias should end with /.
  • The configuration file now needs a secret passphrase — set $cfg['blowfish_secret'] to a random 32-character string.
  • Login loops back to the login page — session directory not writable or mixed HTTP/HTTPS; serve it only over HTTPS.

Alternatives

New database server? Start with installing MySQL on Ubuntu.

  • phpMyAdmin
  • MySQL
  • Nginx