Large uploads can fail before the application code ever sees the request, which blocks media libraries, backup restores, theme or plugin installers, and bulk imports that depend on normal multipart uploads. Raising the effective PHP upload size limit lets legitimate requests reach the application instead of being discarded at the runtime boundary.
The main upload ceiling comes from more than one directive. upload_max_filesize limits each uploaded file, post_max_size limits the full request body, and larger uploads can still require extra memory_limit headroom while the application parses archives, images, or other heavy payloads. When the request body exceeds post_max_size, the upload never reaches normal application handling and the submitted body can arrive without the expected $_POST or $_FILES data.
Change the runtime that actually serves the site, not only the CLI binary in PATH. PHP-FPM pool directives, per-directory .user.ini files on CGI/FastCGI, or smaller request-body limits in Apache, Nginx, or a reverse proxy can still win over the base php.ini file. Per-directory .user.ini changes are cached rather than applied immediately, so verification needs to happen against the same site path that handles the real upload.
Related: How to increase PHP memory limit
Related: How to limit request body size in Apache
Related: How to limit request sizes in Nginx
Steps to increase PHP upload size limit:
- Check the web-facing PHP runtime for the loaded configuration file and the current upload-related directives.
$ php-fpm8.3 -i | grep -E 'Loaded Configuration File|^(upload_max_filesize|post_max_size|memory_limit|max_input_time) =>' Loaded Configuration File => /etc/php/8.3/fpm/php.ini max_input_time => 60 => 60 memory_limit => 128M => 128M post_max_size => 8M => 8M upload_max_filesize => 2M => 2M
Use the binary that matches the runtime serving the site, such as php-fpm or php-fpm8.4. If the site runs through the Apache module instead, confirm the active values from a temporary request-side probe because php --ini only reports the CLI configuration tree.
Related: How to find PHP configuration files
- Search PHP-FPM pool files for upload-related overrides before editing the main php.ini file.
$ sudo grep -REn '^[[:space:]]*php(_admin)?_value\\[(upload_max_filesize|post_max_size|memory_limit|max_input_time)\\]' /etc/php/8.3/fpm/pool.d /etc/php-fpm.d 2>/dev/null
No output means no current pool file is overriding these directives. If this command returns a matching line, change that pool file instead because the pool value wins for requests handled by that pool.
- Back up the file that currently controls the effective upload limit.
$ sudo cp /etc/php/8.3/fpm/php.ini /etc/php/8.3/fpm/php.ini.bak-$(date +%Y%m%d%H%M%S)
Back up the pool file instead when the previous step finds an active PHP-FPM override.
Keep the timestamped backup until the new limit is confirmed from the same site path that handles uploads.
- Open the controlling configuration file in a text editor.
$ sudoedit /etc/php/8.3/fpm/php.ini
Open the discovered pool file instead of php.ini when the active values come from /etc/php/8.3/fpm/pool.d/*.conf or /etc/php-fpm.d/*.conf.
Related: How to find PHP configuration files
- Set the per-file and full-request limits high enough for the largest legitimate upload.
; Keep the full request body larger than the per-file limit upload_max_filesize = 128M post_max_size = 160M memory_limit = 256M
post_max_size must stay larger than upload_max_filesize so the multipart body can reach PHP. Keep memory_limit above the amount of memory the application needs while parsing or processing the uploaded data.
On CGI or FastCGI deployments without main configuration access, place the same directives in .user.ini. When PHP runs as an Apache module, use an allowed php_value override point instead. Current PHP documentation still lists the default user_ini.cache_ttl as 300 seconds, so a .user.ini change can take a few minutes to appear.
- Increase max_input_time only when large or slow uploads time out while PHP is still receiving the request body.
max_input_time = 300
max_input_time covers request parsing time, including file uploads. max_execution_time applies after script execution begins.
- Test the PHP-FPM configuration before reloading the runtime.
$ sudo php-fpm8.3 -t [25-Mar-2026 23:02:43] NOTICE: configuration file /etc/php/8.3/fpm/php-fpm.conf test is successful
Use the matching binary name on the host, such as php-fpm on many RHEL-family systems. Skip this syntax test only when the change was made in .user.ini rather than the main PHP-FPM configuration.
Do not reload the runtime until the configuration test succeeds.
- Reload the runtime that serves the application so new workers read the updated directives.
$ sudo systemctl reload php8.3-fpm
Reload Apache instead when PHP runs as an Apache module, and use the unversioned php-fpm unit on hosts that package it that way. A .user.ini change is picked up after the user_ini.cache_ttl interval instead of a service reload.
- Create a temporary diagnostic script under the same site or application path that handles uploads.
$ sudo tee /var/www/app.example.test/public/upload-check.php >/dev/null <<'PHP' <?php header('Content-Type: text/plain'); printf("SAPI=%s\n", PHP_SAPI); printf("Loaded php.ini=%s\n", php_ini_loaded_file() ?: 'none'); printf("upload_max_filesize=%s\n", ini_get('upload_max_filesize')); printf("post_max_size=%s\n", ini_get('post_max_size')); printf("memory_limit=%s\n", ini_get('memory_limit')); printf("max_input_time=%s\n", ini_get('max_input_time')); PHPKeep the probe under the same virtual host, document root, or PHP-FPM pool that receives the real uploads so the result reflects the effective request-side configuration instead of a different SAPI or pool.
Remove the diagnostic file after testing because it exposes runtime details to anyone who can reach the URL.
- Request the diagnostic script through the same site or virtual host and confirm the higher limit.
$ curl -s https://app.example.test/upload-check.php SAPI=fpm-fcgi Loaded php.ini=/etc/php/8.3/fpm/php.ini upload_max_filesize=128M post_max_size=160M memory_limit=256M max_input_time=300
If lower values still appear, inspect later PHP-FPM pool overrides, per-directory .user.ini files, and any request-body limit in Apache, Nginx, or the reverse proxy.
Related: How to find PHP configuration files
- Remove the temporary diagnostic script after confirming the new limit.
$ sudo rm /var/www/app.example.test/public/upload-check.php
Leaving the script in place exposes the site's runtime configuration to anyone who can request the URL.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
