Your laptop and your live server should run the same code with different settings. This lesson lists the PHP settings that matter in production.
PHP ships two starting files: php.ini-development and php.ini-production. Copy the second one as a base. Find your active file with:
<?php
echo php_ini_loaded_file();
On the command line: php --ini. Remember that the web server (PHP-FPM, Apache) and the CLI can use different php.ini files.
Errors
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/app-errors.log
error_reporting = E_ALL
See Production Error Handling.
Hide the version
expose_php = Off
Limits
memory_limit = 128M
max_execution_time = 30
post_max_size = 10M
upload_max_filesize = 8M
max_input_vars = 1000
Set these for your needs. post_max_size should be larger than upload_max_filesize. A generous memory limit and execution time for web requests hide performance problems and let one script block the server.
Security-related settings
allow_url_include = Off
allow_url_fopen = On ; Off if you never read remote URLs with file functions
session.use_strict_mode = 1
session.use_only_cookies = 1
session.cookie_httponly = 1
session.cookie_secure = 1 ; when the site uses HTTPS
session.cookie_samesite = Lax
You can also disable dangerous functions you never use (disable_functions = exec,passthru,shell_exec,system,proc_open,popen). Be careful: some libraries need them.
OPcache
OPcache stores compiled PHP code in memory (see Caching Concepts).
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 2
memory_consumption: the size of the cache in MB. If it fills up, files are not cached.max_accelerated_files: how many files it may keep. Set it above the number of PHP files in your project andvendor/.validate_timestamps = 1checks whether files changed. On a deployment pipeline that restarts PHP-FPM or clears OPcache after each release, you can set it to0for a little more speed, but then code changes are not visible until you reset the cache.
Check that OPcache is working:
<?php
echo function_exists("opcache_get_status") ? "the OPcache extension is available" : "OPcache is not installed";
the OPcache extension is available
(OPcache is usually off in the command line by default, opcache.enable_cli=0, so tests from the CLI show different timings than the web.)
JIT
PHP 8 includes a just-in-time compiler (opcache.jit). It helps with CPU-heavy code (maths, image processing). For typical web pages, which wait on the database and the network, the gain is small. Test before you rely on it.
Time zone
date.timezone = "UTC"
Many teams store and process times in UTC, and convert for display.
PHP-FPM
On Nginx and modern Apache setups, PHP runs under PHP-FPM, with pools of worker processes. Key settings (pm.max_children, pm.start_servers) decide how many requests run at the same time. Too few workers makes requests queue. Too many uses all the RAM. Size them by available memory / memory per worker.
Environment-specific values
Do not edit php.ini per deployment by hand if you can avoid it. Use environment variables for secrets and flags, and keep the same php.ini template for staging and production.
A check function
<?php
function productionProblems(array $ini): array
{
$problems = [];
foreach (["display_errors" => "0", "expose_php" => "0", "allow_url_include" => "0"] as $key => $expected) {
if (($ini[$key] ?? $expected) !== $expected) {
$problems[] = "$key should be $expected";
}
}
return $problems;
}
print_r(productionProblems(["display_errors" => "1", "expose_php" => "0"]));
Array
(
[0] => display_errors should be 0
)
In a real check script, you would read each value with ini_get().
After changing php.ini
Restart PHP-FPM or the web server, then verify in a phpinfo page that you protect with a password and delete afterwards, or with php -i | grep memory_limit on the command line.
Do not copy settings blindly
php.ini-production, change what you understand, and measure the effect.