Skip to content

Changing PHP Settings with .user.ini

CorePanel runs PHP through PHP-FPM, one pool per account. Which means the two things people reach for first — a php.ini of their own, or php_value lines in an .htaccess — do not work: the pool’s settings come from a file only the server operator can write, and .htaccess PHP directives are a mod_php feature that FPM never reads.

What does work, on every account, with nothing to enable, is a .user.ini file in the site’s document root. PHP-FPM reads it natively:

; ~/public_html/.user.ini
upload_max_filesize = 128M
post_max_size = 128M
max_execution_time = 300
max_input_vars = 5000

This is the supported way to change PHP settings for one site. Most of what CorePanel sets for you is deliberately left overridable from here; the handful that is not is listed below, and each one is locked for a reason.

PHP looks for .user.ini from the site’s document root down to the directory holding the script that is running, so the file must be inside the docroot of the site it should affect. Which directory that is depends on the kind of domain:

The siteWhere its .user.ini goes
Primary domain, and its aliases~/public_html/.user.ini
Addon domain or subdomain~/domains/<domain>/.user.ini
Imported site with a path of its ownThat path — e.g. ~/dl.example.com/.user.ini

A file above the document root — in the home directory, say — is never read. This is the single most common reason a .user.ini “does not work”: on an account with several domains, it was put in ~/public_html while the site being tested serves from ~/domains/shop.example.com.

A file in a subdirectory is read, and applies to that subdirectory and below. A .user.ini in the docroot plus a second one in wp-admin/ both apply inside wp-admin/, with the deeper file winning where the two disagree and the docroot one still supplying everything the deeper file does not mention.

Anything PHP marks as changeable per directory or at runtime. That covers five of the seven per-request limits:

DirectivePool defaultTypical reason to change it
upload_max_filesize64MA site that accepts large media
post_max_size64MMust be raised with the one above, never below it
max_execution_time120A long import or report
max_input_time120A slow upload over a slow link
max_input_vars3000A big form — WooCommerce settings, a menu editor

…plus the everyday ones a site actually reaches for: display_errors, error_reporting, date.timezone, default_charset, auto_prepend_file, most session.* settings.

Two different reasons, and telling them apart saves an afternoon of editing a file that was never going to work.

What CorePanel pins. These are written into the pool with php_admin_value, which no .user.ini and no ini_set() can override. A line naming one of them is read and ignored — no error, no warning, just the old value:

DirectiveWhy it is locked
memory_limitIt bounds how much RAM an account’s PHP can hold. A ceiling a site can raise for itself is not a ceiling.
open_basedirIt is what keeps PHP inside the account’s own trees.
disable_functionsIt is what stops a compromised site from getting a shell.
sys_temp_dir, upload_tmp_dir, session.save_pathThey keep the account’s temporary files out of the shared /tmp.

What PHP itself only reads from php.ini. Directives PHP marks system-level — disable_functions, most opcache.* settings, extension= — would not work from a .user.ini on any host, CorePanel or not. Those are the server operator’s to change.

request_terminate_timeout belongs to neither list: it is a php-fpm directive, not a PHP one, so PHP never looks for it and naming it in a .user.ini does nothing at all. The 300-second kill for a stuck request is not something a site can lift.

If a site genuinely needs more memory than the account is allowed, that is a conversation with the server operator, who can raise it for every account under Resource limits → Per request. A script that needs more than it has stops with Allowed memory size exhausted — see Isolation and Limits.

  • Changes are not instant. PHP caches the result for 5 minutes, so an edit appears within that window on its own. There is nothing to reload, and nothing to be gained by restarting anything. The cache covers absence too: a .user.ini created where there was none can take the same five minutes to be noticed for the first time. Waiting is the fix; editing it again is not.
  • It is not .htaccess. php_value and php_flag lines in an .htaccess only ever worked under mod_php. Under PHP-FPM — here, and on every other FPM host, including the cPanel servers accounts are imported from — they are ignored. Software that offers both (Wordfence, for one) picks .user.ini automatically when it detects FPM.
  • The file is not served. A request for /.user.ini gets a 404, like every path whose name starts with a dot, so putting it in the document root does not publish it.
  • For runtime-changeable directives, ini_set() does the same thing from inside the script and takes effect immediately. Use the file for what has to be set before the script runs — upload sizes, input limits — and ini_set() for the rest.
  • Check what actually took effect with a one-line script — <?php phpinfo(); — and read the Local Value column, not Master Value. The local value is what your .user.ini produced; the master value is the pool’s. Delete the file when you are done.

An operator with root can change anything, and should not do it by editing a pool file: CorePanel rewrites the settings it owns when corepanel-sys starts, so a hand edit there can be normalized away without warning.

  • For the seven per-request limits, use the panel (Resource limits → Per request) or corepanel php limits set. That reaches every account in one step and survives the pool rewrite.
  • For anything else CorePanel does not expose, drop a .ini in the PHP version’s php.d directory. That directory is yours and is never touched — though note it applies to every account on that PHP version, not one site.