PHP’s behaviour — memory limits, upload sizes, error handling, performance — is controlled by php.ini. On a server there are usually several of them, which is the first source of confusion. This guide shows where they are and which settings matter in production.
Which php.ini is used?
Each SAPI (the way PHP runs) has its own configuration on Debian/Ubuntu:
/etc/php/8.3/cli/php.ini # command line (php, composer, artisan, wp-cli)
/etc/php/8.3/fpm/php.ini # PHP-FPM (Nginx, Apache with FPM)
/etc/php/8.3/apache2/php.ini # mod_php
Plus extra files loaded after the main one:
/etc/php/8.3/fpm/conf.d/*.ini
Check:
php --ini # CLI only!
php -i | grep -i "loaded configuration"
For the web, create a temporary file <?php phpinfo(); in your site, open it, look at Loaded Configuration File and Additional .ini files parsed, then delete it. RHEL-family systems use /etc/php.ini and /etc/php.d/.
Don’t edit php.ini directly — add an override
Package updates may replace php.ini. Put your changes in a file that sorts last:
sudo nano /etc/php/8.3/fpm/conf.d/99-custom.ini
sudo systemctl restart php8.3-fpm
Per-site settings belong in the PHP-FPM pool (php_admin_value[...]), so each site can differ — see PHP-FPM tuning.
Recommended production settings
; Resources
memory_limit = 256M
max_execution_time = 60
max_input_time = 60
max_input_vars = 3000
; Uploads
upload_max_filesize = 64M
post_max_size = 64M
file_uploads = On
; Errors: log, don't display
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_log = /var/log/php/php-errors.log
; Security
expose_php = Off
allow_url_include = Off
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1
session.cookie_samesite = Lax
; Time zone
date.timezone = UTC
; Performance
realpath_cache_size = 4096K
realpath_cache_ttl = 600
Create the log directory and give PHP-FPM’s user write access, or omit error_log to send errors to the FPM log.
What the important ones do
memory_limit — maximum memory per request. Too low → “Allowed memory size exhausted”. Too high doesn’t consume memory by itself, but allows runaway scripts to eat RAM × number of workers. See WordPress memory limit.
max_execution_time — CPU time limit per request (on Linux, time waiting for the database isn’t counted). Keep moderate; run long tasks via CLI or queues. Must fit within the web server’s timeouts — see Nginx 504.
upload_max_filesize / post_max_size — upload limits; post_max_size must be ≥ upload_max_filesize. Also raise the web server’s limit (client_max_body_size). See increasing upload size.
max_input_vars — maximum form fields; complex admin forms (menus, page builders, WooCommerce variations) may need 3000–5000.
display_errors = Off — showing errors to visitors leaks paths, queries and sometimes credentials. Log them instead and read the log.
expose_php = Off — removes the X-Powered-By: PHP/8.x header.
session.cookie_secure / httponly / samesite — safer session cookies on HTTPS sites.
OPcache
OPcache caches compiled PHP code and is essential for performance. Typical production settings:
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60
With validate_timestamps = 0, PHP never checks for changed files — fastest, but you must reload PHP-FPM after every deploy. See PHP OPcache.
disable_functions
Disabling shell-execution functions limits what an attacker can do through a vulnerable script:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec
Some legitimate software (backup plugins, image tools, Composer scripts) uses them — test, and apply per pool where possible. It must be set in php.ini or php_admin_value, not at runtime.
Apply and verify
sudo php-fpm8.3 -t # test FPM config
sudo systemctl restart php8.3-fpm
php -r 'echo ini_get("memory_limit"), PHP_EOL;' # CLI value
Verify web values with a temporary phpinfo page or your app’s diagnostics (WordPress: Tools → Site Health → Info → Server).
Common mistakes
- Editing the CLI php.ini and wondering why the website didn’t change.
- Forgetting to restart PHP-FPM.
- Using
php_valuein.htaccesswith PHP-FPM (causes 500 errors) — use.user.inior pool settings. - Raising limits to hide problems (memory leaks, slow queries) instead of fixing them.
Related: installing PHP and MySQL, PHP versions on Ubuntu and PHP error log.