# Changing PHP Settings with .user.ini

> How a site owner changes PHP settings on a CorePanel server: where the .user.ini file goes for each kind of domain, which directives it can and cannot set, and why a change takes five minutes to appear.

Source: https://www.corepanel.net/docs/php/user-ini/
Last updated: 2026-08-27
Part of the CorePanel documentation — https://www.corepanel.net/docs

---

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:

```ini
; ~/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](https://www.corepanel.net/docs/php/isolation-and-limits) is deliberately left overridable
from here; the handful that is not is listed below, and each one is locked for a reason.

## Where the file goes

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 site | Where 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 own | That 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.

## What it can set

Anything PHP marks as changeable per directory or at runtime. That covers five of the
seven [per-request limits](https://www.corepanel.net/docs/php/isolation-and-limits#per-request-limits):

| Directive | Pool default | Typical reason to change it |
|---|---|---|
| `upload_max_filesize` | 64M | A site that accepts large media |
| `post_max_size` | 64M | Must be raised with the one above, never below it |
| `max_execution_time` | 120 | A long import or report |
| `max_input_time` | 120 | A slow upload over a slow link |
| `max_input_vars` | 3000 | A 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.

> **Raise `post_max_size` with `upload_max_filesize`**
>
> PHP checks the POST size first, so an `upload_max_filesize` above `post_max_size` can
> never be reached — the upload is rejected before the upload limit applies, and the error
> does not mention the setting that actually stopped it. Set both, to the same number.
## What it cannot set

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:

| Directive | Why it is locked |
|---|---|
| `memory_limit` | It bounds how much RAM an account's PHP can hold. A ceiling a site can raise for itself is not a ceiling. |
| `open_basedir` | It is what keeps PHP inside the account's own trees. |
| `disable_functions` | It is what stops a compromised site from getting a shell. |
| `sys_temp_dir`, `upload_tmp_dir`, `session.save_path` | They 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](https://www.corepanel.net/docs/php/isolation-and-limits#per-request-limits).

## Points that catch people out

- **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`](https://www.corepanel.net/docs/web/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.

## For operators

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`](https://www.corepanel.net/docs/cli#corepanel-php). 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.
