How to Install phpMyAdmin with Nginx on Debian (13, 12, 11)

Last updated Saturday, March 21, 2026 7:39 am 15 min read 6 comments

Managing MariaDB or MySQL from a shell is fine until you need to inspect grants, import a dump, or compare table structures quickly. You can install phpMyAdmin with Nginx on Debian 13, 12, and 11 by pairing the upstream phpMyAdmin tarball with Debian’s Nginx, MariaDB, and PHP-FPM packages, then signing in with a regular database account instead of exposing socket-authenticated root over the web.

The upstream phpMyAdmin release keeps the file layout and manual upgrade path consistent across Debian releases. If you would rather build the stack one component at a time, see install LEMP on Debian, install Nginx on Debian, install MariaDB on Debian, and install PHP on Debian.

Install phpMyAdmin with Nginx on Debian

Start by installing the web stack packages, downloading the current phpMyAdmin release, and creating the small override file that phpMyAdmin needs for cookie authentication.

Debian’s default APT sources already include phpMyAdmin, but they currently package 5.2.2 on Debian 13, 5.2.1 on Debian 12, and 5.0.4 on Debian 11. The upstream tarball keeps the Nginx layout predictable and makes it easier to move to newer upstream releases without waiting for the next Debian package refresh.

Update Debian system packages

Refresh the package index and install any pending security updates before you add the rest of the stack.

sudo apt update && sudo apt upgrade -y

These commands use sudo where root privileges are required. If your account does not have sudo access yet, follow the guide on how to add a user to sudoers on Debian.

Reboot before continuing if the upgrade pulled in a new kernel or critical system libraries.

Install Nginx, MariaDB, and PHP on Debian

Install the Nginx web server, MariaDB database server, PHP-FPM, and the extensions phpMyAdmin needs. Desktop installs may already include a few of these packages, but minimal and server images usually do not.

sudo apt install nginx mariadb-server mariadb-client php-fpm php-mbstring php-bcmath php-xml php-mysql php-common php-gd php-cli php-curl php-zip curl ca-certificates gpg openssl -y

Check that each service is active before you move on to the phpMyAdmin files.

# Debian 13
systemctl is-active nginx mariadb php8.4-fpm

# Debian 12
systemctl is-active nginx mariadb php8.2-fpm

# Debian 11
systemctl is-active nginx mariadb php7.4-fpm
active
active
active

Debian 13 uses php8.4-fpm, Debian 12 uses php8.2-fpm, and Debian 11 uses php7.4-fpm. Keep that version match in mind for the Nginx socket path later.

Run the MariaDB hardening script on Debian

Debian’s current MariaDB packages use mariadb-secure-installation for the initial hardening pass. Run it once to remove anonymous users, drop the test database, and confirm the local root access model.

sudo mariadb-secure-installation
Switch to unix_socket authentication [Y/n]
Change the root password? [Y/n]
Remove anonymous users? [Y/n]
Disallow root login remotely? [Y/n]
Remove test database and access to it? [Y/n]
Reload privilege tables now? [Y/n]

The exact prompts vary a little by MariaDB release, but answering the cleanup questions with Y gives you the safer default state that phpMyAdmin should sit on top of.

Create a phpMyAdmin login on Debian

phpMyAdmin does not ship with its own username or password. Sign in with a MariaDB or MySQL account, and avoid using the socket-authenticated root account for browser access.

sudo mariadb <<'SQL'
CREATE USER 'pmaadmin'@'localhost' IDENTIFIED BY 'change-this-strong-password';
GRANT ALL PRIVILEGES ON *.* TO 'pmaadmin'@'localhost';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'pmaadmin'@'localhost';
SQL

This example creates a broad administrative login for phpMyAdmin without letting that user grant privileges to other MariaDB accounts. If you only need phpMyAdmin for one application database, replace the global grant with database-scoped privileges instead of giving this account full server access.

Verify that the new login can connect before you expose phpMyAdmin in a browser.

mariadb -u pmaadmin -p -e "SELECT VERSION();"
VERSION()
11.8.3-MariaDB-0+deb13u1 from Debian

Download the latest phpMyAdmin release on Debian

Fetch the upstream release metadata first, then use the version number to build the tarball URLs. Keep using the same terminal session so the shell variables stay available for the next code block.

cd /tmp
curl -fsSL https://www.phpmyadmin.net/home_page/version.txt -o version.txt
sed -n '1p' version.txt
sed -n '3p' version.txt
5.x.x
https://files.phpmyadmin.net/phpMyAdmin/5.x.x/phpMyAdmin-5.x.x-all-languages.zip

The first line is the current phpMyAdmin version. The metadata file points to the ZIP archive on line three, but the commands below keep the .tar.gz format that fits the standard Linux extraction workflow.

VERSION=$(sed -n '1p' version.txt)
BASE_URL="https://files.phpmyadmin.net/phpMyAdmin/${VERSION}"

curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz"
curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256"
curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz.asc" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz.asc"

Verify the phpMyAdmin release files on Debian

Import the official phpMyAdmin keyring, confirm the SHA256 checksum, and then validate the detached signature. Using the project keyring avoids depending on public keyserver availability.

curl -fL -o phpmyadmin.keyring https://files.phpmyadmin.net/phpmyadmin.keyring
gpg --batch --import phpmyadmin.keyring
sha256sum -c "phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256"
gpg --verify "phpMyAdmin-${VERSION}-all-languages.tar.gz.asc" "phpMyAdmin-${VERSION}-all-languages.tar.gz"
phpMyAdmin-5.x.x-all-languages.tar.gz: OK
gpg: Good signature from "Isaac Bennetch <isaac@bennetch.org>"
Primary key fingerprint: 3D06 A59E CE73 0EB7 1B51  1C17 CE75 2F17 8259 BD92

The signature check can still warn that the key is not yet trusted locally. That warning is normal until you personally trust the key on your GnuPG keyring.

Install the phpMyAdmin files on Debian

Extract the upstream archive into /var/www/phpmyadmin and create a dedicated temp directory outside the web root.

tar -xzf "phpMyAdmin-${VERSION}-all-languages.tar.gz"
sudo rm -rf /var/www/phpmyadmin
sudo mv "phpMyAdmin-${VERSION}-all-languages" /var/www/phpmyadmin
sudo install -d -o www-data -g www-data -m 0755 /var/lib/phpmyadmin/tmp

Create the phpMyAdmin override config on Debian

Generate a secret for cookie authentication, then write a small config.user.inc.php override. The tee command is used because a plain > redirection would still run as your regular shell instead of writing the file as root.

BLOWFISH_SECRET=$(openssl rand -hex 16)

sudo tee /var/www/phpmyadmin/config.user.inc.php > /dev/null <<EOF
<?php
\$cfg['blowfish_secret'] = '${BLOWFISH_SECRET}';
\$cfg['TempDir'] = '/var/lib/phpmyadmin/tmp';
EOF

Check the file for syntax errors before you hand it to PHP-FPM.

php -l /var/www/phpmyadmin/config.user.inc.php
No syntax errors detected in /var/www/phpmyadmin/config.user.inc.php

Set phpMyAdmin permissions on Debian

Give the web server ownership of the phpMyAdmin tree and keep the directory modes readable without leaving everything writable.

sudo chown -R www-data:www-data /var/www/phpmyadmin /var/lib/phpmyadmin
sudo chmod -R u=rwX,go=rX /var/www/phpmyadmin /var/lib/phpmyadmin

Configure Nginx for phpMyAdmin on Debian

Use a dedicated subdomain such as pma.example.com instead of exposing phpMyAdmin on the same path as a public site. That keeps the URL cleaner, makes SSL simpler, and reduces accidental routing conflicts with other PHP applications.

Replace the PHP-FPM socket with the one that matches your Debian release: /run/php/php8.4-fpm.sock on Debian 13, /run/php/php8.2-fpm.sock on Debian 12, or /run/php/php7.4-fpm.sock on Debian 11. If another stack such as iRedMail rewrites PHP-FPM to a TCP listener, use that address instead and verify the listener first with ss -ltnp | grep 9999 or the port your stack configured.

Create the phpMyAdmin server block on Debian

Create a dedicated Nginx site file, then paste in the server block below with your real hostname.

sudo nano /etc/nginx/sites-available/phpmyadmin.conf
server {
    listen 80;
    listen [::]:80;
    server_name pma.example.com;

    root /var/www/phpmyadmin;
    index index.php;

    access_log /var/log/nginx/phpmyadmin_access.log;
    error_log /var/log/nginx/phpmyadmin_error.log;

    location = / {
        return 302 /index.php;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

The layout keeps the root request simple, passes PHP files to PHP-FPM, and blocks stray .ht requests without relying on Debian’s stock welcome page or a front-controller rewrite that does not add anything here.

Enable the phpMyAdmin site on Debian

Disable the stock default site if it is still enabled, then activate the phpMyAdmin site and test the configuration before you reload Nginx.

sudo rm -f /etc/nginx/sites-enabled/default
sudo ln -sf /etc/nginx/sites-available/phpmyadmin.conf /etc/nginx/sites-enabled/phpmyadmin.conf
sudo nginx -t
sudo systemctl reload nginx
curl -I http://127.0.0.1/index.php
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8

Sign in to phpMyAdmin on Debian

Open your browser and visit http://pma.example.com. For a local test before DNS is ready, you can also browse to the server IP and append /index.php. Sign in with pmaadmin or another MariaDB account that already has the privileges you need.

Once the login page loads, the Nginx and PHP-FPM side is working. If you plan to use this stack for a CMS next, install WordPress with Nginx on Debian on the same base services.

Review the phpMyAdmin dashboard on Debian

The Status page shows the server load, connection counts, and query activity in one place.

The Advisor page suggests database tuning changes after it has seen real workload data.

The advisor is most useful after the database has been under real load for a while. Test any suggested changes on staging before you apply them to production.

The Monitor page adds live graphs that make it easier to spot spikes and long-running activity.

Secure phpMyAdmin on Debian

After the login page works, tighten the web access path with HTTPS, firewall rules, and optional IP restrictions.

Add Let’s Encrypt SSL to phpMyAdmin on Debian

Use a real DNS name that points to your server and make sure port 80 is reachable before you ask Certbot to rewrite the Nginx site. If you want the deeper walkthrough, follow secure Nginx with Let’s Encrypt on Debian.

sudo apt install certbot python3-certbot-nginx -y
certbot --version
certbot 4.0.0

Request the certificate after DNS is live and the HTTP site is already responding.

sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email you@example.com -d pma.example.com

A successful Certbot run prints the saved certificate path and expiry date, then updates the Nginx server block for HTTPS. Once the first certificate is in place, test renewal before you trust the timer.

systemctl status certbot.timer --no-pager
sudo certbot renew --dry-run
certbot.timer - Run certbot twice daily
     Loaded: loaded (/usr/lib/systemd/system/certbot.timer; enabled; preset: enabled)
     Active: active (waiting)
    Trigger: Fri 2026-03-13 10:29:52 AWST
   Triggers: certbot.service

Limit phpMyAdmin access by IP on Debian

If you administer the server from a stable office or home IP, add an allowlist inside the phpMyAdmin server block and deny everything else.

allow 198.51.100.10;
deny all;

Place those directives inside the server { } block, then reload Nginx.

sudo nginx -t
sudo systemctl reload nginx

Open UFW ports for phpMyAdmin on Debian

If this host uses UFW, allow SSH first, then open HTTP and HTTPS. The full firewall workflow lives in install UFW on Debian.

Allow SSH before you enable or reload firewall rules from a remote session. If you already allowed the Nginx Full application profile, you do not need duplicate 80/tcp and 443/tcp rules.

sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

Troubleshoot phpMyAdmin with Nginx on Debian

These checks cover the most common post-install problems: the stock Nginx page, PHP-FPM socket mismatches, root login failures, and missing cookie secrets.

Fix phpMyAdmin 404 errors or the Nginx welcome page on Debian

If you still land on the stock Nginx page, the default site is winning, the phpMyAdmin symlink is missing, or you are testing the wrong path.

ls -l /etc/nginx/sites-enabled/
curl -I http://127.0.0.1/index.php
phpmyadmin.conf -> /etc/nginx/sites-available/phpmyadmin.conf
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=utf-8

If the symlink is missing or the default site is still enabled, restore the phpMyAdmin site and reload Nginx.

sudo rm -f /etc/nginx/sites-enabled/default
sudo ln -sf /etc/nginx/sites-available/phpmyadmin.conf /etc/nginx/sites-enabled/phpmyadmin.conf
sudo nginx -t
sudo systemctl reload nginx

Fix phpMyAdmin 502 Bad Gateway on Debian

A 502 error usually means the PHP-FPM service is stopped or the socket path in the Nginx site file does not match the Debian release.

# Debian 13
systemctl is-active php8.4-fpm

# Debian 12
systemctl is-active php8.2-fpm

# Debian 11
systemctl is-active php7.4-fpm

grep fastcgi_pass /etc/nginx/sites-available/phpmyadmin.conf
ls /run/php/
active
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
php8.4-fpm.pid
php8.4-fpm.sock

If the service is inactive, start it and reload Nginx after you confirm the socket name matches the version in your site file.

If your server stack uses a TCP listener instead of a Unix socket, confirm that PHP-FPM is actually bound to the same address and port before you blame the Nginx site file.

ss -ltnp | grep 9999
LISTEN 0      4096       127.0.0.1:9999      0.0.0.0:*
# Debian 13
sudo systemctl enable --now php8.4-fpm

# Debian 12
sudo systemctl enable --now php8.2-fpm

# Debian 11
sudo systemctl enable --now php7.4-fpm

sudo systemctl reload nginx

Fix Access denied for user ‘root’@’localhost’ in phpMyAdmin on Debian

MariaDB on Debian usually keeps root on local socket authentication, which works from the shell with sudo mariadb but not from a web form. Use the dedicated phpMyAdmin account instead.

sudo mariadb -e "SHOW GRANTS FOR 'pmaadmin'@'localhost';"
GRANT ALL PRIVILEGES ON *.* TO `pmaadmin`@`localhost` IDENTIFIED BY PASSWORD '...'

If that account is missing, recreate it with the SQL block from the install section and sign in with that user instead of trying to reconfigure MariaDB root for web access.

Fix blank phpMyAdmin page with valid HTML source on Debian

If Firefox shows a blank page but View Source contains the full phpMyAdmin HTML, PHP is already rendering the page. In that case the usual problem is that JavaScript or CSS assets are not loading, so phpMyAdmin’s temporary cfs-style hide rule never gets removed.

One common cause on mail-server stacks such as iRedMail is a Content-Security-Policy header set at the Nginx http level. iRedMail ships default-src https: in its global headers.conf, which tells the browser to load scripts and stylesheets only over HTTPS. If you serve phpMyAdmin over plain HTTP, the browser obeys the policy and blocks every JS and CSS request silently. Since Nginx inherits add_header directives from the parent level only when the current level defines none, adding any add_header inside a location block stops that inheritance and removes the restrictive policy.

Check which headers the server is actually sending before you change the vhost.

curl -sI http://127.0.0.1/index.php | grep -iE 'content-security|x-frame|strict-transport'

If the response includes Content-Security-Policy: default-src https: and the vhost serves phpMyAdmin over HTTP, that header is blocking assets. The cleanest fix is to serve phpMyAdmin over HTTPS so the policy is satisfied. If you need to keep HTTP access, override the global headers inside the phpMyAdmin server block with a policy that allows the correct scheme.

On iRedMail specifically, the stock subdomain templates include snippets from /etc/nginx/templates/. When you create a phpMyAdmin vhost alongside iRedMail, start from one of those working templates and change only the phpMyAdmin-specific directives (server_name, root, fastcgi_pass) so that template includes and header overrides stay in place.

curl -I http://127.0.0.1/index.php
curl -I "http://127.0.0.1/js/vendor/jquery/jquery.min.js?v=5.2.3"
curl -I "http://127.0.0.1/themes/pmahomme/css/theme.css?v=5.2.3"
sudo nginx -T | grep -nE 'phpmyadmin|fastcgi_pass|root /var/www/phpmyadmin'
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
server_name pma.example.com;
root /var/www/phpmyadmin;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;

If index.php returns 200 OK but one of the asset requests returns 404, 403, or the wrong content type, fix the Nginx root, alias, or include order before you keep changing PHP-FPM. If all three requests return 200 OK, check the browser Network and Console tabs for blocked or rewritten asset paths.

Fix phpMyAdmin blowfish_secret errors on Debian

If phpMyAdmin says the configuration file needs a secret passphrase, rewrite the override file with a fresh secret and reload the site.

NEW_SECRET=$(openssl rand -hex 16)

sudo tee /var/www/phpmyadmin/config.user.inc.php > /dev/null <<EOF
<?php
\$cfg['blowfish_secret'] = '${NEW_SECRET}';
\$cfg['TempDir'] = '/var/lib/phpmyadmin/tmp';
EOF

sudo systemctl reload nginx

Update or Remove phpMyAdmin on Debian

Keep the upstream files current by replacing the whole directory, and remove the dedicated site cleanly if you no longer need phpMyAdmin.

Update phpMyAdmin on Debian

Never extract a new phpMyAdmin release over the existing directory. Back up config.user.inc.php, unpack the new release into a fresh directory, and then swap the directory so old files do not linger behind.

Reuse the same terminal session so the VERSION and BASE_URL variables stay available from one block to the next.

cd /tmp
curl -fsSL https://www.phpmyadmin.net/home_page/version.txt -o version.txt
VERSION=$(sed -n '1p' version.txt)
BASE_URL="https://files.phpmyadmin.net/phpMyAdmin/${VERSION}"

curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz"
curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256"
curl -fL -o "phpMyAdmin-${VERSION}-all-languages.tar.gz.asc" "$BASE_URL/phpMyAdmin-${VERSION}-all-languages.tar.gz.asc"
curl -fL -o phpmyadmin.keyring https://files.phpmyadmin.net/phpmyadmin.keyring
gpg --batch --import phpmyadmin.keyring
sha256sum -c "phpMyAdmin-${VERSION}-all-languages.tar.gz.sha256"
gpg --verify "phpMyAdmin-${VERSION}-all-languages.tar.gz.asc" "phpMyAdmin-${VERSION}-all-languages.tar.gz"
tar -xzf "phpMyAdmin-${VERSION}-all-languages.tar.gz"

sudo cp /var/www/phpmyadmin/config.user.inc.php /tmp/config.user.inc.php.backup
sudo mv /var/www/phpmyadmin /var/www/phpmyadmin-old
sudo mv "phpMyAdmin-${VERSION}-all-languages" /var/www/phpmyadmin
sudo cp /tmp/config.user.inc.php.backup /var/www/phpmyadmin/config.user.inc.php
sudo chown -R www-data:www-data /var/www/phpmyadmin /var/lib/phpmyadmin
sudo chmod -R u=rwX,go=rX /var/www/phpmyadmin /var/lib/phpmyadmin
sudo rm -rf /var/www/phpmyadmin-old
curl -I http://127.0.0.1/index.php

Remove phpMyAdmin on Debian

Remove the phpMyAdmin files, its Nginx site, and the temp directory if you no longer need the web interface.

sudo rm -rf /var/www/phpmyadmin
sudo rm -rf /var/lib/phpmyadmin
sudo rm -f /etc/nginx/sites-enabled/phpmyadmin.conf
sudo rm -f /etc/nginx/sites-available/phpmyadmin.conf
sudo nginx -t
sudo systemctl reload nginx

If you created a dedicated MariaDB login or issued a dedicated certificate for phpMyAdmin, remove those separately.

sudo mariadb -e "DROP USER IF EXISTS 'pmaadmin'@'localhost'; FLUSH PRIVILEGES;"
sudo certbot delete --cert-name pma.example.com

phpMyAdmin with Nginx on Debian FAQ

Should I use Debian’s phpMyAdmin package or the upstream tarball on Debian?

Debian’s phpmyadmin package integrates cleanly with the distro, but its version follows the Debian release cycle and its defaults are more package-managed than Nginx-focused. The upstream tarball takes a little more manual setup and manual upgrades, but it gives you a predictable file layout for Nginx and quicker access to new phpMyAdmin releases.

What username and password should I use in phpMyAdmin on Debian?

phpMyAdmin does not create its own login. Use a MariaDB or MySQL account such as pmaadmin, or another existing database account with the privileges you need. There are no default phpMyAdmin credentials to try.

Why does phpMyAdmin say Access denied for user ‘root’@’localhost’ on Debian?

Debian’s MariaDB packages usually keep the root account on local socket authentication. That lets sudo mariadb work from the shell, but it prevents the web form from logging in as root. Create a dedicated MariaDB account for phpMyAdmin instead of changing root to password-based web access.

Which PHP-FPM socket should Nginx use for phpMyAdmin on Debian 13, 12, and 11?

Use /run/php/php8.4-fpm.sock on Debian 13, /run/php/php8.2-fpm.sock on Debian 12, and /run/php/php7.4-fpm.sock on Debian 11. A mismatched socket path is one of the most common reasons for phpMyAdmin 502 errors behind Nginx.

Conclusion

phpMyAdmin with Nginx is now running on Debian, with a dedicated MariaDB login, an upstream update path, and the option to lock the interface behind HTTPS and IP filtering. For the next hardening steps, secure Nginx with Let’s Encrypt on Debian, configure security headers in Nginx, or rate limit Nginx before you expose the server to wider traffic.

Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffee Buy me a coffee

6 thoughts on “How to Install phpMyAdmin with Nginx on Debian (13, 12, 11)”

  1. Hello,

    I followed your tutorial and everything went fine on the fresh Debian Trixie server I installed.
    Then I installed iRedMail to get the webmail solution to replace my old iRedMail server.
    After the iRedMail installation the configuration file was not working due to the file ‘fastcgi_pass unix:/run/php/php8.4-fpm.sock;’ which was not available anymore, replaced with a PID file.
    So I changed the fastcgi_pass command to ‘fastcgi_pass 127.0.0.1:9999’ as the iRedMail server modified the configuration files for php-fpm to use a TCP socket instead of a unix file.

    When I try to access the servername, the page display is blank.
    I have no error displayed, the phpmyadmin_error.log file is empty, and the CTRL+U in the Firefox wen browser displays html code generated by the php code.

    What can be the reason for this blank page display with no errors ?

    Reply
    • Laurent, you were right to flag this. When you commented, the guide still assumed Debian’s default Unix socket layout and did not cover iRedMail switching PHP-FPM to 127.0.0.1:9999. If Firefox View Source showed full phpMyAdmin HTML, your TCP change had likely already fixed the PHP side.

      That blank page usually means phpMyAdmin’s JavaScript or CSS assets are not loading, so the temporary cfs-style hide rule never gets removed. I have updated the article with a new troubleshooting section for TCP listeners and blank pages with valid HTML source, including asset checks and nginx -T diagnostics for stacks like iRedMail.

      Reply
      • In case someone is trying to use PhpMyAdmin on a debian 13 server with iRedMail installed on like on mine, here is the virtualhost code I had to modifiy to make it work with the nginx configuration modified after the iRedMail installation.

        server {
        listen 80;
        listen [::]:80;
        server_name pma.mydomain.ext;
        root /var/www/phpmyadmin/;
        index index.php;

        access_log /var/log/nginx/phpmyadmin_access.log;
        error_log /var/log/nginx/phpmyadmin_error.log;

        location / {
        try_files $uri $uri/ /index.php;
        }

        location ~ ^/(doc|sql|setup)/ {
        deny all;
        }

        location ~ \\.php$ {
        include fastcgi_params;
        include /etc/nginx/templates/hsts.tmpl;
        fastcgi_pass 127.0.0.1:9999;
        include snippets/fastcgi-php.conf;
        }

        location ~ /\\.ht {
        deny all;
        }

        allow 127.0.0.1;
        deny all;
        }

        I had to add the ‘include /etc/nginx/templates/hsts.tmpl;’ which adds a header to the html page generated by the php code which allows the correct page display instead of a blank page.

        Reply
        • Thanks for posting the full server block, Laurent. Looking at the iRedMail source on GitHub, I think I can see why the blank page happened and why the HSTS include fixed it, though I do not have access to your actual server config so take this as my best read of the situation.

          iRedMail ships a global headers.conf at the Nginx http level that includes Content-Security-Policy: default-src https:. If that file is active on your server, the browser would only load scripts and stylesheets over HTTPS. Since your phpMyAdmin vhost listens on port 80, the browser would silently block every JS and CSS file, leaving phpMyAdmin stuck on its startup hide rule and producing a blank page even though the HTML source renders fine.

          What I think happened with the HSTS include: Nginx only inherits add_header directives from the parent level when the current level defines none. By adding include /etc/nginx/templates/hsts.tmpl; inside the PHP location block, you introduced an add_header at that level, which would have stopped the parent-level CSP (and the other security headers like X-Frame-Options) from being inherited. If that is what happened, any add_header directive at the location level would have had the same effect, and the HSTS header itself would not be the piece doing the work.

          You can check with curl -sI http://127.0.0.1/index.php | grep -iE 'content-security|x-frame|strict-transport' to see which headers the server is actually sending. If you see the default-src https: policy on the response, that confirms it. Either way, the cleanest long-term path is serving phpMyAdmin over HTTPS so the CSP policy is satisfied without losing the other security headers.

          I have updated the troubleshooting section with the CSP-inheritance explanation and a diagnostic command so other iRedMail users can identify the issue faster. Thanks for taking the time to post the full server block.

          Reply
  2. Thanks for a flawlessly working tutorial, but ….
    at starting (with an empty screen) of phpmyadmin using Google developer tools I found problems with
    Refused to execute script from because its MIME type (…) and strict MIME type (…)
    file not founnd
    autoload
    I changed the setup as follows
    moved php,yadmin to a subfolder of /var/www/
    deleted phpmyadmin.conf
    use 127.0.0.1:9000 instead of php8.2-fpm.sock
    in /etc/nginx/sites_enabled/mylocal and in /etc/php/8.2/fpm/pool.d/www.conf

    I did the setup on a fresh installed Raspberry Pi OS 64 bit for a Raspberry Pi 3B+

    All is working fine now.

    Reply
    • Thanks for sharing your setup and the detailed troubleshooting, Michael. The MIME type warnings you encountered back in August typically point to PHP-FPM not executing files properly. Your solution switching to TCP socket 127.0.0.1:9000 makes perfect sense for Raspberry Pi OS, where Unix socket permissions can behave differently than standard Debian.

      The guide assumes standard Debian server environments where Unix sockets offer better performance, but TCP sockets are absolutely valid for embedded systems or when debugging permission issues. Good instincts moving phpMyAdmin to a subfolder and testing with different socket configurations until it worked.

      Reply
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Leave a Comment

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: