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 sudo access
  • 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.