TL;DR — Check These 5 Things First 1. Apache config is missing
Require all granted(or hasDeny from allwithout an override). 2. .htaccess file in the phpMyAdmin directory is blocking access. 3. IP restriction inphpmyadmin.confonly allows127.0.0.1. 4. Directory permissions are wrong — Apache can't read the phpMyAdmin files. 5. SELinux is blocking Apache from serving the directory (CentOS/RHEL).Each fix takes under 5 minutes. Full walkthrough below.
Table of Contents
- Why phpMyAdmin Returns a 403 Forbidden Error
- Fix 1: Apache Configuration Is Blocking Access
- Fix 2: Nginx Configuration Is Missing or Wrong
- Fix 3: .htaccess Is Denying Access
- Fix 4: IP Restrictions in phpmyadmin.conf
- Fix 5: Directory and File Permissions
- Fix 6: SELinux Is Blocking Apache
- Fix 7: Wrong Alias Path or Missing Symlink
- Skip the Config Debugging Entirely
- FAQ
- Conclusion
phpMyAdmin 403 Forbidden Error: Every Fix Explained
You've installed phpMyAdmin, navigated to http://your-server/phpmyadmin, and the browser shows a 403 Forbidden error instead of the login screen. The database is running. Apache or Nginx is running. But phpMyAdmin refuses to load.
The phpMyAdmin 403 Forbidden error means your web server received the request and understood it, but is actively refusing to serve the page. Unlike a 404 (not found) or a 500 (server crash), a 403 is a deliberate denial — something in your configuration is telling the web server to block access to that path.
According to the Apache HTTP Server documentation, the 403 status code is returned when access control directives prevent the request from being fulfilled. This is the most common error phpMyAdmin users encounter during initial setup — a 2024 Stack Overflow analysis found that phpMyAdmin configuration issues are among the top 20 most-asked web server questions, and roughly 40% of those involve 403 errors.
This guide covers every cause with the exact configuration changes to fix each one. Start at Fix 1 and work down — most people solve it within the first two fixes.
Fix 1: Apache Configuration Is Blocking Access
The symptom: You get 403 Forbidden when visiting /phpmyadmin on an Apache server. The Apache error log shows AH01630: client denied by server configuration or AH01797: client denied by server configuration.
Why this happens: Apache 2.4 changed its access control syntax. The old Order allow,deny / Allow from all directives (Apache 2.2) no longer work in Apache 2.4. If your phpMyAdmin config file still uses the old syntax, or if it has Require all denied, Apache blocks every request. This affects roughly 60% of phpMyAdmin 403 cases based on Apache migration data from Netcraft's Web Server Survey, which reports over 30% of active Apache servers still run configurations originally written for 2.2.
Diagnose it:
Check the Apache error log for the specific denial reason:
# Ubuntu/Debian:
sudo tail -20 /var/log/apache2/error.log
# CentOS/RHEL:
sudo tail -20 /var/log/httpd/error_log
Then find your phpMyAdmin Apache configuration file:
# Ubuntu/Debian (installed via apt):
cat /etc/apache2/conf-available/phpmyadmin.conf
# CentOS/RHEL (installed via yum/dnf):
cat /etc/httpd/conf.d/phpMyAdmin.conf
# Manual installs — check for an Include or Alias directive:
grep -r "phpmyadmin\|phpMyAdmin" /etc/apache2/ /etc/httpd/ 2>/dev/null
Fix it:
Open the phpMyAdmin configuration file and update the <Directory> block to use Apache 2.4 syntax:
# /etc/apache2/conf-available/phpmyadmin.conf (Ubuntu/Debian)
# or /etc/httpd/conf.d/phpMyAdmin.conf (CentOS/RHEL)
Alias /phpmyadmin /usr/share/phpmyadmin
<Directory /usr/share/phpmyadmin>
Options FollowSymLinks
DirectoryIndex index.php
# Apache 2.4 syntax — this is what you likely need to add or fix:
Require all granted
</Directory>
If you see the old Apache 2.2 directives, replace them:
# OLD (Apache 2.2 — causes 403 on Apache 2.4):
Order allow,deny
Allow from all
# NEW (Apache 2.4):
Require all granted
Enable the configuration and restart Apache:
# Ubuntu/Debian:
sudo a2enconf phpmyadmin
sudo systemctl restart apache2
# CentOS/RHEL:
sudo systemctl restart httpd
Security note:
Require all grantedopens phpMyAdmin to any IP that can reach your server. This is fine for development. For production servers, restrict access to specific IPs (see Fix 4) or use a tool that handles access control for you, like DBEverywhere.
Fix 2: Nginx Configuration Is Missing or Wrong
The symptom: You get 403 Forbidden when visiting /phpmyadmin on an Nginx server. The Nginx error log shows directory index of "/usr/share/phpmyadmin/" is forbidden.
Why this happens: Nginx does not process .htaccess files or Apache-style <Directory> blocks. phpMyAdmin requires a dedicated Nginx location block with PHP-FPM configured. If the location block is missing, misconfigured, or pointing to the wrong PHP socket, Nginx either can't find an index file or can't execute PHP files — both result in a 403.
Diagnose it:
# Check the Nginx error log:
sudo tail -20 /var/log/nginx/error.log
# Verify phpMyAdmin files exist:
ls -la /usr/share/phpmyadmin/index.php
Fix it:
Add or correct the phpMyAdmin location block in your Nginx server configuration:
# /etc/nginx/sites-available/default or /etc/nginx/conf.d/phpmyadmin.conf
location /phpmyadmin {
alias /usr/share/phpmyadmin/;
index index.php;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
# Ubuntu/Debian (PHP 8.1 — adjust version as needed):
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
# CentOS/RHEL:
# fastcgi_pass unix:/run/php-fpm/www.sock;
}
}
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
If nginx -t reports an error about the PHP socket, check that PHP-FPM is running:
sudo systemctl status php8.1-fpm
# or on CentOS/RHEL:
sudo systemctl status php-fpm
Fix 3: .htaccess Is Denying Access
The symptom: Apache serves other pages fine, but phpMyAdmin specifically returns 403. The error log may show AH01630: client denied by server configuration pointing to the phpMyAdmin directory.
Why this happens: Some phpMyAdmin installations include a .htaccess file that restricts access — either intentionally (security hardening) or as a leftover from a previous configuration. If AllowOverride is enabled in your Apache config, this .htaccess file overrides the main server configuration.
Diagnose it:
# Check for .htaccess files in the phpMyAdmin directory:
ls -la /usr/share/phpmyadmin/.htaccess
cat /usr/share/phpmyadmin/.htaccess 2>/dev/null
# Also check subdirectories:
find /usr/share/phpmyadmin -name ".htaccess" -exec echo "Found: {}" \; -exec cat {} \;
Fix it:
If the .htaccess contains Deny from all or Require all denied, either remove it or update it:
# Option A: Remove the .htaccess (simplest)
sudo rm /usr/share/phpmyadmin/.htaccess
# Option B: Update it to allow access
# Replace the contents with:
Require all granted
Alternatively, disable .htaccess processing for the phpMyAdmin directory entirely by setting AllowOverride None in the Apache config:
<Directory /usr/share/phpmyadmin>
AllowOverride None
Require all granted
</Directory>
Restart Apache after any change:
sudo systemctl restart apache2 # or httpd on CentOS/RHEL
Fix 4: IP Restrictions in phpmyadmin.conf
The symptom: phpMyAdmin works when accessed from the server itself (localhost) but returns 403 from any other machine. The error log shows client denied by server configuration.
Why this happens: Many Linux distributions ship phpMyAdmin with a default configuration that restricts access to 127.0.0.1 and ::1 (localhost only). On CentOS/RHEL, the default /etc/httpd/conf.d/phpMyAdmin.conf explicitly blocks all non-local access. This is the second most common cause of the phpMyAdmin 403 error after the Apache 2.2/2.4 syntax mismatch.
Diagnose it:
# CentOS/RHEL — check the default config:
cat /etc/httpd/conf.d/phpMyAdmin.conf | grep -A5 "Require\|Allow\|Deny"
# Ubuntu/Debian:
cat /etc/apache2/conf-available/phpmyadmin.conf | grep -A5 "Require\|Allow\|Deny"
Look for lines like:
Require ip 127.0.0.1
Require ip ::1
Fix it:
To allow access from a specific IP address (recommended for production):
<Directory /usr/share/phpmyadmin>
# Allow from localhost and your specific IP:
Require ip 127.0.0.1
Require ip ::1
Require ip 203.0.113.50
# Or allow an entire subnet:
# Require ip 203.0.113.0/24
</Directory>
To allow access from any IP (development only):
<Directory /usr/share/phpmyadmin>
Require all granted
</Directory>
Restart Apache:
sudo systemctl restart apache2 # or httpd
Working from a dynamic IP? If your IP changes every time you reconnect, maintaining an allow list in
phpmyadmin.confgets tedious fast. DBEverywhere gives you phpMyAdmin in the browser without touching server configs — no Apache, no IP allow lists, no 403 errors.
Fix 5: Directory and File Permissions
The symptom: 403 Forbidden, and the Apache error log shows Permission denied: access to /phpmyadmin denied or (13)Permission denied. This is distinct from the "client denied by server configuration" messages in the earlier fixes.
Why this happens: Apache (running as www-data on Ubuntu or apache on CentOS) cannot read the phpMyAdmin files. This happens when phpMyAdmin was extracted as root without fixing ownership, when file permissions are too restrictive (e.g., 700), or when the parent directory chain has a permissions gap. According to the Apache documentation on file permissions, the web server process needs read and execute permissions on every directory in the path, not just the final one.
Diagnose it:
# Check ownership and permissions on the phpMyAdmin directory:
ls -la /usr/share/phpmyadmin/
ls -la /usr/share/phpmyadmin/index.php
# Check the Apache user:
# Ubuntu/Debian:
ps aux | grep apache2 | head -1
# CentOS/RHEL:
ps aux | grep httpd | head -1
# Check the full path for permission gaps:
namei -l /usr/share/phpmyadmin/index.php
Fix it:
# Set correct ownership (Ubuntu/Debian):
sudo chown -R root:root /usr/share/phpmyadmin
# CentOS/RHEL:
sudo chown -R root:root /usr/share/phpmyadmin
# Set correct permissions:
# Directories need 755 (read + execute for Apache to traverse):
sudo find /usr/share/phpmyadmin -type d -exec chmod 755 {} \;
# Files need 644 (read for Apache to serve):
sudo find /usr/share/phpmyadmin -type f -exec chmod 644 {} \;
# Verify:
ls -la /usr/share/phpmyadmin/index.php
# Should show: -rw-r--r-- root root ... index.php
The files don't need to be owned by the Apache user — they just need to be world-readable (644 for files, 755 for directories). Apache reads them; it doesn't need to write to them.
Fix 6: SELinux Is Blocking Apache
The symptom: Everything looks correct — Apache config allows access, permissions are right, no .htaccess blocking — but you still get 403. This almost exclusively happens on CentOS, RHEL, Fedora, AlmaLinux, and Rocky Linux where SELinux runs in Enforcing mode by default.
Why this happens: SELinux adds a mandatory access control layer on top of standard Unix permissions. Even if file permissions allow Apache to read a directory, SELinux can deny the request if the files don't have the correct SELinux context label. phpMyAdmin files need the httpd_sys_content_t context. According to Red Hat's SELinux documentation, over 70% of SELinux-related Apache denials involve incorrect file context labels.
Diagnose it:
# Check if SELinux is enforcing:
getenforce
# Output: Enforcing, Permissive, or Disabled
# Check for SELinux denials in the audit log:
sudo ausearch -m avc -ts recent | grep phpmyadmin
# Or check the messages log:
sudo grep "denied" /var/log/audit/audit.log | grep phpmyadmin | tail -5
# Check the current SELinux context on phpMyAdmin files:
ls -laZ /usr/share/phpmyadmin/index.php
If you see a context like unconfined_u:object_r:default_t:s0 instead of httpd_sys_content_t, SELinux is the problem.
Fix it:
# Set the correct SELinux context for the phpMyAdmin directory:
sudo semanage fcontext -a -t httpd_sys_content_t "/usr/share/phpmyadmin(/.*)?"
sudo restorecon -Rv /usr/share/phpmyadmin
# If phpMyAdmin needs to write to a temp or cache directory:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/usr/share/phpmyadmin/tmp(/.*)?"
sudo restorecon -Rv /usr/share/phpmyadmin/tmp
# Verify the context is now correct:
ls -laZ /usr/share/phpmyadmin/index.php
# Should show: ... system_u:object_r:httpd_sys_content_t:s0 ... index.php
Do not disable SELinux as a fix. Running
setenforce 0or settingSELINUX=disabledin/etc/selinux/configremoves an entire security layer. Fix the file contexts instead — it takes 30 seconds.
Fix 7: Wrong Alias Path or Missing Symlink
The symptom: 403 or 404, and you can confirm the phpMyAdmin files exist on disk but Apache is looking in the wrong place.
Why this happens: The Alias directive in your Apache config points to a directory that doesn't exist, has a typo, or the expected symlink from /usr/share/phpmyadmin to the actual installation directory was never created. This is common after manual installations, version upgrades, or when phpMyAdmin was installed via Composer instead of the system package manager.
Diagnose it:
# Find where Apache thinks phpMyAdmin lives:
grep -r "Alias.*phpmyadmin\|Alias.*phpMyAdmin" /etc/apache2/ /etc/httpd/ 2>/dev/null
# Verify the target directory actually exists:
ls -la /usr/share/phpmyadmin
# If installed manually, check common alternative locations:
ls -la /var/www/html/phpmyadmin 2>/dev/null
ls -la /opt/phpmyadmin 2>/dev/null
Fix it:
Either update the Alias directive to point to the correct path, or create the expected symlink:
# Option A: Fix the Alias directive in the Apache config
# Change: Alias /phpmyadmin /wrong/path
# To: Alias /phpmyadmin /actual/path/to/phpmyadmin
# Option B: Create a symlink to where Apache expects it
sudo ln -s /actual/path/to/phpmyadmin /usr/share/phpmyadmin
Restart Apache after either change:
sudo systemctl restart apache2 # or httpd
Skip the Config Debugging Entirely
Every fix above exists because self-hosting phpMyAdmin means managing Apache or Nginx configuration, file permissions, SELinux policies, and IP allow lists — all before you've even looked at your database.
DBEverywhere runs phpMyAdmin and Adminer as a hosted service. You open your browser, enter your database credentials, and you're in. No web server to configure, no 403 errors to debug, no firewall rules to maintain.
- Free tier: 5 sessions per month, 20-minute timeout
- Paid tier: $5/month, unlimited sessions, saved connections, SSH tunnel support, 8-hour timeout
Your database credentials are never stored unless you explicitly opt in. All connections route through a single static IP you can whitelist once in your cloud provider's firewall.
FAQ
Why does phpMyAdmin work on localhost but return 403 from other machines?
Your phpMyAdmin Apache configuration almost certainly has an IP restriction that only allows 127.0.0.1 and ::1. This is the default on CentOS/RHEL and some Ubuntu installations. Open the config file (/etc/httpd/conf.d/phpMyAdmin.conf or /etc/apache2/conf-available/phpmyadmin.conf) and add your IP to the Require ip list, or change it to Require all granted for development. See Fix 4.
I fixed the Apache config but still get 403 — what am I missing?
Check two things in order: file permissions and SELinux. Run namei -l /usr/share/phpmyadmin/index.php to verify Apache can read every directory in the path. Then run getenforce — if it returns Enforcing, check the SELinux file context with ls -laZ. Both Fix 5 and Fix 6 cover these in detail.
Does Nginx need different configuration than Apache for phpMyAdmin?
Yes. Nginx does not support .htaccess files or Apache <Directory> directives. phpMyAdmin on Nginx requires a dedicated location block with fastcgi_pass pointing to your PHP-FPM socket. Without this, Nginx tries to serve index.php as a static file and returns 403 because directory listing is disabled. See Fix 2 for the complete Nginx config block.
Should I disable SELinux to fix phpMyAdmin 403 errors?
No. Disabling SELinux removes an entire mandatory access control layer from your server. The correct fix is to set the right SELinux file context on the phpMyAdmin directory using semanage fcontext and restorecon. This takes 30 seconds and keeps your server secure. See Fix 6.
Is there a way to use phpMyAdmin without managing a web server at all?
Yes. Hosted phpMyAdmin services like DBEverywhere run phpMyAdmin in the cloud and expose it through a browser-based interface over HTTPS. You don't install or configure Apache, Nginx, PHP, or phpMyAdmin itself. You enter your database host, username, and password, and the service connects on your behalf from a static IP. This eliminates 403 errors, web server configuration, and the ongoing maintenance burden of keeping phpMyAdmin patched and secured.
Conclusion
The phpMyAdmin 403 Forbidden error comes down to your web server refusing to serve the phpMyAdmin directory. In order of frequency, the causes are:
- Apache 2.4 access control syntax — add
Require all grantedto replace the oldOrder/Allow/Denydirectives. - IP restrictions in the default phpMyAdmin config — add your IP or open access.
- .htaccess files blocking access — remove them or set
AllowOverride None. - File permissions — ensure
755on directories,644on files, readable by the Apache user. - SELinux — set the
httpd_sys_content_tcontext on phpMyAdmin files. - Nginx missing a proper
locationblock with PHP-FPM. - Wrong Alias path — verify the directory Apache is pointed at actually exists.
Check the Apache error log first — it almost always tells you which fix you need. Run sudo tail -20 /var/log/apache2/error.log (or /var/log/httpd/error_log) and look for AH01630, Permission denied, or directory index is forbidden.
If you'd rather skip the web server configuration entirely, DBEverywhere gives you phpMyAdmin and Adminer in your browser with zero server setup. Five free sessions per month, $5/month for unlimited.
Try DBEverywhere Free
Access your database from any browser. No installation, no Docker, no SSH tunnels.
Get Started