phpMyAdmin Nginx Configuration: A Tested Server Block Template

A flat green Nginx logo block being adjusted by a yellow configuration slider.

We may earn a referral fee at no additional cost to you when you shop through the links on this page.

You installed phpMyAdmin on an nginx server, browsed to /phpmyadmin, and got a 404. Nothing is broken: the package only configures Apache and lighttpd automatically, so nginx never learned the path. This DevAnswers guide fixes it with one tested location block, validated end to end on Ubuntu 22.04 through Debian 13.

The Nginx Location Block for phpMyAdmin 

Open the server block file for your site. On a stock setup that is the default file; substitute your own if you use a per-domain config:

Terminal
sudo nano /etc/nginx/sites-enabled/default

Paste the following inside the server { } block, just before its closing bracket. One line needs editing: the fastcgi_pass socket must match your PHP version, which the next section shows you how to check.

/etc/nginx/sites-enabled/default
# Source: https://devanswers.net/nginx-phpmyadmin-configuration-template-for-nginx-conf/
location /phpmyadmin {
    root /usr/share/;
    index index.php;

    # Official phpMyAdmin guidance: no web access to auxiliary folders
    location ~ ^/phpmyadmin/(libraries|templates) {
        deny all;
    }

    location ~ ^/phpmyadmin/(.+\.php)$ {
        root /usr/share/;
        # UPDATE the PHP version to match your server (next section)
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        include snippets/fastcgi-php.conf;
        fastcgi_param HTTP_HOST $host;
    }
}

Save and exit (press CTRL + X, press Y, then press ENTER)

This template targets Debian and Ubuntu, where the files live in /usr/share/phpmyadmin and the snippets/fastcgi-php.conf include exists. On RHEL-family systems (AlmaLinux, Rocky) the socket is under /run/php-fpm/, the server block lives in /etc/nginx/conf.d/, and there is no snippets/ include, so replace that line with include fastcgi_params; plus fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;.

The deny rule is not decoration: phpMyAdmin’s own security guidance says to block web access to the auxiliary files under libraries/ and templates/, which protects against path exposure and cross-site scripting issues found in that code. Most templates floating around omit this.

Find Your PHP-FPM Socket 

The fastcgi_pass line points nginx at PHP-FPM through a UNIX-domain socket. The socket path is whatever the listen directive in your PHP-FPM pool configuration says, and the file usually lives in /run/php/ with the PHP version in its name. List what is actually there:

Terminal
ls /run/php/

Use the versioned .sock file you see (for example php8.3-fpm.sock) in the template’s fastcgi_pass line. If the directory is empty, PHP-FPM is not installed or not running, and you will want our nginx and PHP-FPM setup guide first.

Test and Reload Nginx 

Validate the configuration before reloading; nginx prints the verdict to the terminal:

Terminal
sudo nginx -t
Output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Terminal
sudo systemctl reload nginx

Now load http://devanswers.test/phpmyadmin in your browser (swap in your own domain or server IP). The phpMyAdmin login page should appear, styled and ready to sign in. (If signing in as root fails with Access denied for ‘root’@’localhost’, that’s an authentication-plugin issue, not your Nginx config.)

Why the Template Works 

  • root /usr/share/; and not /usr/share/phpmyadmin. nginx’s root directive appends the entire request URI to the path, so /phpmyadmin/index.php becomes /usr/share/phpmyadmin/index.php, exactly where the package puts the files. Setting root to the package directory itself would double the folder name. (The related alias directive does the opposite: it replaces the matched part of the URI instead of appending the whole thing, which is why root is the right fit here.)
  • The deny location. Straight from the official security guidance: auxiliary files under libraries/ and templates/ should not be reachable over the web. Because it appears first, nginx matches it ahead of the PHP rule for anything inside those folders.
  • The nested PHP location. Only requests like /phpmyadmin/….php are sent to PHP-FPM, so the rest of your site’s PHP handling stays untouched. The included fastcgi-php.conf snippet brings its own try_files $uri =404, so do not add a second one in this block; nginx treats a duplicate try_files as a configuration error.
  • fastcgi_param HTTP_HOST $host; comes from the phpMyAdmin FAQ for nginx setups, so the application sees the hostname the browser asked for.
  • Static assets need no extra block. CSS, icons and JavaScript fall through to the outer location /phpmyadmin and are served from the same root; the test run confirms the login page loads fully styled.

Secure the Installation 

phpMyAdmin’s security guidance recommends requiring extra HTTP authentication at the web-server level for public installations, and serving the app over HTTPS, preferably with HSTS so you are protected from protocol downgrade attacks. On nginx that outer gate is auth_basic: add it inside location /phpmyadmin with an htpasswd file, exactly as covered in our guide to password-protecting a directory in nginx. Give the htpasswd user a strong, randomly generated password (the preset skips look-alike characters, since you type this one at a prompt).

Inside the app, cookie authentication mode is, per the same guidance, probably the best choice for shared hosting setups; it is also the Debian package default, so there is usually nothing to change.

Troubleshooting 

Worked through everything and something still fails? The usual suspects:

  • Still 404 at /phpmyadmin. Check the root line: it must be /usr/share/ with the trailing slash and WITHOUT the package folder, because root appends the whole URI. And remember why nothing worked out of the box: the package’s automatic web-server configuration covers Apache and lighttpd; nginx is not on that list.
  • 502 Bad Gateway. nginx reached the PHP location but could not connect to the FastCGI backend; in practice that is nearly always a fastcgi_pass socket that does not exist. Re-run ls /run/php/ and fix the version. More depth in our nginx + PHP-FPM guide.
  • 403 errors while using phpMyAdmin. If the login works but actions inside the app return 403, that is typically a web application firewall false positive, covered in our phpMyAdmin 403 fix.
  • The login page is unstyled. The outer location lost its root (or you placed root only inside the PHP location), so static assets cannot resolve. Keep root /usr/share/; at the location /phpmyadmin level.
  • The installer asked about Apache and a database. Normal for the Debian package: it offers Apache/lighttpd configuration and sets up phpMyAdmin’s configuration storage through dbconfig-common. On an nginx server, select no web server; this article replaces that step.

Summary 

One location block and the right PHP-FPM socket are all nginx needs to serve phpMyAdmin: root at /usr/share/, a scoped PHP handler, and the officially recommended deny rules for the auxiliary folders. Test with nginx -t, reload, and put auth_basic in front of it before you call it done.

Support DevAnswers
Written, tested and maintained by one developer. Your support keeps these guides accurate and ad-light.
Buy me a coffee

5 replies

Leave a reply

  1. Ronald Oliveira

    Man, i’ve saved my entire day. Holy Jesus

  2. Walshak Timothy Apollos

    Thanks….saved me hours of searching…the only modification I had to make was the socket…everything worked out of the box.

  3. Ali Liaquit

    Hi, Thanks for your support, But I am facing the following error:

    nginx: [emerg] “location” directive is not allowed here in /etc/nginx/conf.d/phpmyadmin.conf:1
    nginx: configuration file /etc/nginx/nginx.conf test failed

    Please guide after having look at the following phpmyadmin.conf file as per my system:

    location /testvm {
    root /var/www/html/phpmyadmin;
    index index.php index.html index.htm;
    location ~ ^/testvm/(.+\.php)$ {
    try_files $uri =404;
    root /var/www/html/;
    fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
    }
    location ~* ^/testvm/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
    root /var/www/html/;
    }
    }

    In the above code: testvm is my hostname of the server
    Direcotry path containing phpmyadmin: /var/www/html/phpmyadmin

    Regards

  4. Gaara Madara

    You are the best!!!

  5. bahman

    after too much investigation just your code works for me
    Thanks