PHP runs on millions of web servers, but a default installation leaves many dangerous settings enabled that attackers can exploit. On RHEL 8, hardening PHP through /etc/php.ini is one of the most impactful steps you can take to protect your application without touching a single line of code. This tutorial covers the most important security-oriented configuration directives, explains what each one does, and shows you how to verify the changes are live. Following these steps takes less than thirty minutes and significantly reduces your attack surface.
Prerequisites
- RHEL 8 server with a valid subscription or CentOS Stream 8 equivalent
- PHP 7.4 or PHP 8.x installed via AppStream or the Remi repository
- Root or
sudoaccess - A web server (Apache or Nginx) already configured to serve PHP
- Basic familiarity with editing files on the command line
Step 1 — Locate and Back Up php.ini
Before making any changes, find the active configuration file and create a backup so you can roll back quickly if something breaks.
php --ini | grep "Loaded Configuration"
cp /etc/php.ini /etc/php.ini.bak-$(date +%F)
ls -lh /etc/php.ini.bak-*
Step 2 — Disable Dangerous Functions
The disable_functions directive prevents PHP scripts from calling shell-execution and process-spawning functions that are almost never needed by legitimate web applications. Open /etc/php.ini in your editor and set the following:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,phpinfo
Verify the setting was applied without restarting the web server first:
php -r "var_dump(ini_get('disable_functions'));"
Step 3 — Restrict File System Access with open_basedir
The open_basedir directive limits the files PHP can open to a specific set of directory trees, preventing path-traversal attacks from reading arbitrary system files.
open_basedir = /var/www/html:/tmp:/usr/share/php
If you run multiple virtual hosts, set open_basedir per virtual host in your Apache or Nginx configuration instead of globally, since the global value applies to every site.
Step 4 — Hide PHP and Disable Error Display
Exposing the PHP version and stack traces to browsers gives attackers free reconnaissance. Set these four directives in /etc/php.ini:
expose_php = Off
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
Create the log file and set correct ownership so PHP can write to it:
touch /var/log/php_errors.log
chown apache:apache /var/log/php_errors.log
chmod 640 /var/log/php_errors.log
Step 5 — Harden Remote File and Session Settings
Remote file inclusion is a classic attack vector. Disable it, then lock down session cookies so they cannot be stolen via JavaScript or sent over plain HTTP.
allow_url_fopen = Off
allow_url_include = Off
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
session.cookie_samesite = Strict
Step 6 — Enable OPcache for Performance and Security
OPcache compiles PHP scripts to bytecode and stores them in shared memory, which both improves performance and reduces the window for file-tampering attacks because scripts are cached at startup.
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
After editing, restart the web server and confirm the active settings:
systemctl restart httpd
php -r "print_r(opcache_get_status());" | head -20
php -r "echo ini_get('expose_php') . PHP_EOL;"
Conclusion
You have hardened your PHP installation on RHEL 8 by disabling dangerous functions, restricting file system access, hiding version information, disabling browser error output, locking down session cookies, and enabling OPcache. Each of these changes addresses a specific class of vulnerability without requiring application code changes. Review the PHP error log periodically to catch any legitimate application code that relies on functions you disabled, and re-enable only what is strictly necessary.
Next steps: How to Install Xdebug for PHP on RHEL 8, How to Set Up ModSecurity WAF with Apache on RHEL 8, and How to Configure SELinux for a PHP Web Application on RHEL 8.