How to Secure a PHP Configuration File (e.g., php.ini)
When a PHP application runs, the php.ini file is the single source of truth for all runtime settings. Because it can contain database credentials, error‑display directives, and other sensitive information, protecting this file is a critical part of any web‑application hardening strategy. In this guide we’ll walk through proven techniques to keep your php.ini safe from accidental exposure and malicious attackers.
Why the php.ini File Needs Protection
The php.ini file controls everything from memory limits to error reporting. If an attacker can read or modify it, they may:
- Discover database usernames and passwords embedded in
mysqli.default_userorpdo_mysql.default_socket. - Enable
display_errorsin production, leaking stack traces and file paths. - Lower security limits (e.g.,
disable_functions) to run arbitrary code. - Inject malicious
auto_prepend_fileorauto_append_filedirectives.
Sensitive Settings Exposed
Even seemingly innocuous directives can reveal internal architecture. For example, open_basedir and include_path give clues about directory structures that aid reconnaissance.
Best Practices for Securing php.ini
1. Keep the File Outside the Web Root
The safest location for php.ini is a directory that the web server never serves directly. On most Linux distributions the default location is /etc/php/7.x/cli/php.ini (CLI) and /etc/php/7.x/apache2/php.ini (Apache). If you need a custom configuration, place it in /etc/php/7.x/conf.d/ or another non‑public path and reference it with the -c flag or PHP_INI_SCAN_DIR environment variable.
2. Restrict File System Permissions
Apply the principle of least privilege:
# Owner: root, Group: root
chmod 640 /etc/php/7.x/apache2/php.ini
chown root:root /etc/php/7.x/apache2/php.ini
Only the web‑server user (e.g., www-data or apache) should have read access if the file must be read at runtime. Avoid giving write permissions to the web‑server user; use root or a dedicated admin account for updates.
3. Use .user.ini for Per‑Directory Overrides
If you need to adjust settings for a specific virtual host or directory, prefer .user.ini files instead of editing the global php.ini. These files are parsed only by PHP and never served by the web server, reducing the risk of accidental exposure.
4. Disable Display of Errors in Production
Set display_errors = Off and log_errors = On in the production php.ini. Log files should be stored outside the document root and protected with proper permissions.
display_errors = Off
log_errors = On
error_log = /var/log/php/error.log
5. Leverage Environment Variables & PHP‑FPM Pools
Modern deployments (Docker, Kubernetes, CI/CD pipelines) often inject configuration via environment variables. You can reference these variables inside php.ini using the ${VAR_NAME} syntax, keeping secrets out of the file itself.
mysqli.default_user = ${MYSQL_USER}
mysqli.default_pw = ${MYSQL_PASSWORD}
When using PHP‑FPM, create separate pool configurations (.conf files in /etc/php/7.x/fpm/pool.d/) for each application, each with its own php_admin_value directives. This isolates settings per site and prevents a compromised site from affecting others.
Additional Hardening Techniques
Limit Access with Web‑Server Rules
Even though php.ini is usually outside the web root, a misconfiguration can expose it. Add explicit deny rules:
- Apache (in
.htaccessorhttpd.conf):<FilesMatch "^php\.ini$"> Require all denied </FilesMatch> - Nginx (in the server block):
location ~* ^/php\.ini$ { deny all; access_log off; }
Monitor Changes with Auditing Tools
Set up file integrity monitoring (FIM) with tools like AIDE, Tripwire, or OS‑level auditd rules to alert you when php.ini is modified.
# Example auditd rule
-w /etc/php/7.x/apache2/php.ini -p wa -k phpini_change
Testing Your Configuration
After applying hardening steps, verify that the file cannot be accessed publicly:
- Use
curl -I https://yourdomain.com/php.ini– you should receive403 Forbiddenor404 Not Found. - Run
php -i | grep "Loaded Configuration File"to ensure PHP is still loading the intended configuration. - Check error logs to confirm that
display_errorsis disabled and that logs are being written to the correct location.
Conclusion
Securing the php.ini file is a straightforward yet vital part of PHP application hardening. By moving the file out of the web root, tightening file permissions, leveraging per‑directory .user.ini files, disabling error display, and using environment variables or PHP‑FPM pools, you dramatically reduce the attack surface. Pair these steps with web‑server deny rules and continuous monitoring, and you’ll have a robust defense against both accidental leaks and targeted attacks.