# 03 — `php.ini`: conta vs sistema (WHM/cPanel)

> **Cópias literais:**
> - Conta: [`arquivos/php.ini.recomended`](arquivos/php.ini.recomended) — SHA-256 `f75dd3b38af35e0678937ca1d8dfdf8b57aee8ee1ea0a72183d11a03f36a21b3`
> - Sistema/WHM: [`arquivos/whm.php.ini.recomended`](arquivos/whm.php.ini.recomended) — SHA-256 `ad28420cf931de096bdd52b5969d9d4fbd0f98b5354fbced88347d62cd65a92c`
>
> **Fonte:** `wiki/infra-update/correcao-php-ini-recomendado.md` e `WHM.md`.

---

## 1. O problema que motivou os templates

No servidor, as contas **não tinham um `php.ini` próprio** — ou seja, rodavam com
os *defaults* do EasyApache 4, sem nenhum ajuste de conta. Consequências:

- **Sem padronização:** cada ambiente herdava valores globais que não são ideais
  para produção (ex.: `expose_php` exposto, sessão sem `cookie_secure`/`httponly`,
  limites sem ajuste, sem `pcre.jit`/`zend.assertions`).
- **Inconsistência entre dev/homol/prod:** nada versionado; cada pessoa ajustava
  “na mão” e as contas divergiam.
- **Performance de conta deixada de lado:** chaves `PHP_INI_PERDIR`/`USER` que a
  conta *pode* mudar ficavam nos defaults.

### Causa real

O EasyApache 4 **só cria o `php.ini` da conta** depois que ela é editada via
*MultiPHP INI Editor* (modo “Editor”/avançado) no cPanel/WHM. Enquanto a conta não
edita nada, ela herda **silenciosamente** o php.ini de sistema do EA4
(`/opt/cpanel/ea-php72/root/etc/php.ini`).

Além disso, a pesquisa de segurança mostrou:

- `opcache.*` e `realpath_cache_*` são **`PHP_INI_SYSTEM`** → valores no php.ini da
  conta são **ignorados**.
- O php.ini da conta **só vale para chaves `PHP_INI_PERDIR`/`USER`**.
- O servidor (WHM) governa OPcache/realpath/APCu.

---

## 2. Escopos `PHP_INI_*` — o que vale onde

| Chave | Escopo | Vale na conta? | Onde atua de fato |
|---|---|---|---|
| `pcre.jit`, `zend.assertions`, `auto_globals_jit` | `PERDIR`/`USER` | **Sim** | conta |
| `session.*`, `display_*`, `error_*`, `max_*` | `PERDIR`/`USER` | **Sim** | conta |
| `zlib.output_compression` | `PERDIR` | **Sim** (Off para não conflitar) | conta |
| `expose_php`, `enable_dl`, `cgi.fix_pathinfo` | `PERDIR`/`USER` | **Sim** | conta |
| `opcache.*` | **`SYSTEM`** | **Não** (ignorado) | WHM / php.ini de sistema |
| `realpath_cache_*` | **`SYSTEM`** | **Não** | WHM / php.ini de sistema |
| `apcu.enabled` / `apcu.enable_cli` | **`SYSTEM`** | **Não** | WHM / `php.d` |

> **Regra:** se a chave é `PHP_INI_SYSTEM`, ela pertence ao WHM. Não adianta
> colocá-la no `.user.ini`/MultiPHP INI da conta.

### 2.1 Como confirmar o escopo no host

```bash
# Qual php.ini está carregado e qual scan dir é aplicado
/opt/cpanel/ea-php72/root/usr/bin/php --ini
# esperado:
#   Loaded Configuration File: /opt/cpanel/ea-php72/root/etc/php.ini
#   Scan for additional .ini files in: /opt/cpanel/ea-php72/root/etc/php.d

# Contexto web (FPM): confira o SAPI e o arquivo carregado
/opt/cpanel/ea-php72/root/usr/bin/php -i | grep -E 'Server API|Loaded Configuration|Scan this dir'

# Chaves efetivas (o que realmente vale, independente do arquivo)
/opt/cpanel/ea-php72/root/usr/bin/php -i | grep -E '^opcache\.|^realpath_cache|^apcu\.|^apc\.'
```

Armadilhas:

- O PHP carrega o `php.ini` principal e **depois** os `*.ini` do scan dir. Um
  `zzz-apcu.ini` pode sobrescrever o que está no principal; a última ocorrência
  vence.
- `.user.ini` é lido por diretório e cacheado (`user_ini.cache_ttl`, default 300s).
  Ele **não** altera `PHP_INI_SYSTEM`; no CLI, normalmente não é lido no contexto
  da conta.
- `php_admin_value`/`php_admin_flag` no pool FPM conseguem forçar diretivas
  `SYSTEM`, mas em cPanel compartilhado isso é configuração de root/WHM, não da
  conta.
- O `php.ini` do MultiPHP INI Editor (modo “Editor”) é o da **conta**; o modo
  “System” grava no `php.ini` do EA4. Não confunda os dois.

---

## 3. `php.ini` da CONTA (`php.ini.recomended`)

### 3.1 Como aplicar

1. No repo, copie o template e substitua o placeholder do caminho do log:

```bash
sed 's#__USUARIO_DO_CPANEL__#SEU_USUARIO#' \
  php.ini.recomended > /tmp/php.ini.conta
```

2. cPanel da conta » **Software » MultiPHP INI Editor** » modo **“Editor”**
   (avançado).
3. Cole o conteúdo (ou aplica via `.user.ini` na raiz `public/` — mesma eficácia
   para chaves `PERDIR`; `.user.ini` é lido pelo PHP-FPM/CGI do EA4).
4. **Não** espere OPcache/realpath aqui — eles são WHM.
5. Opcional: versionar o mesmo conteúdo como `.user.ini` no deploy para
   idempotência entre contas.

### 3.2 Decisões do template

- **Erro e log:** `display_errors=Off`, `log_errors=On`,
  `error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT`, `error_log` por conta
  (placeholder `__USUARIO_DO_CPANEL__`).
- **Superfície:** `expose_php=Off`, `enable_dl=Off`, `cgi.fix_pathinfo=0`.
- **Wrappers:** `allow_url_include=Off`, `allow_url_fopen=On` (Laravel/Guzzle
  dependem de wrappers HTTP).
- **Sessão:** `use_strict_mode=1`, `cookie_httponly=1`, `cookie_secure=On`,
  `sid_bits_per_char=5`, `save_path` no socket de sessões do EA4, GC ajustado.
  `cookie_samesite` fica comentado — só PHP 7.3+; SameSite via `.htaccess` H7.
- **Limites:** `max_execution_time=300`, `memory_limit=512M`,
  `post_max_size=105M`, `upload_max_filesize=100M`, etc.
- **OPcache/realpath:** bloco **mantido só como referência visual** — são
  `PHP_INI_SYSTEM` e não surtem efeito na conta.
- **I/O e localidade:** `zlib.output_compression=Off` (compressão é server-side;
  ligar aqui duplicaria/conflictaria), `date.timezone=America/Sao_Paulo`.
- **Performance USER/PERDIR (APLICA):** `pcre.jit=On`, `zend.assertions=-1`,
  `auto_globals_jit=On`.

### 3.3 Observações importantes

- `session.save_path` aponta para `/var/cpanel/php/sessions/ea-php72`. É inofensivo:
  o Laravel com driver `file` usa `storage/framework/sessions`; afeta só driver
  `native`.
- `allow_url_fopen=On` é mantido; `allow_url_include=Off` blinda contra `include`
  remoto.
- `zend.exception_ignore_args` **não existe no PHP 7.2** (só 7.4+). Não incluir
  até upgrade de versão.
- `session.cookie_samesite` **não existe no PHP 7.2** (só 7.3+). O SameSite é feito
  via `.htaccess` e `config/session.php`.

### 3.4 Verificação

```bash
# na conta (contexto do PHP em uso)
php -i | grep -E 'expose_php|display_errors|pcre.jit|zend.assertions|session.cookie_secure'

# esperado:
#   expose_php => Off
#   display_errors => Off
#   pcre.jit => On
#   zend.assertions => -1
#   session.cookie_secure => On

# opcache/realpath NÃO aparecem com valor da conta (são SYSTEM)
php -i | grep -E 'opcache.validate_timestamps'   # reflete o WHM, não este arquivo
```

### 3.5 Rollback

Restaurar o php.ini anterior no MultiPHP INI Editor (ou remover o `.user.ini`) e
reiniciar o PHP-FPM. Nenhuma chave do template altera dados ou código.

---

## 4. `php.ini` de SISTEMA (`whm.php.ini.recomended`)

### 4.1 Onde aplicar

**WHM » Software » MultiPHP INI Editor » System » `ea-php72`**.

O editor abre `/opt/cpanel/ea-php72/root/etc/php.ini`; ele funde/sobrescreve as
chaves. Não editar o arquivo na mão.

### 4.2 O que vai e o que NÃO vai

- **Só chaves `PHP_INI_SYSTEM`** valem no sistema/WHM. O template contém só essas.
- **Não inclui endurecimento de conta** (`expose_php`, `session.*`, limites,
  `pcre.jit`, `zend.assertions`): são `PERDIR`/`USER` e vão no template da conta.
- **Não use `error_log` com caminho de usuário** aqui: escopo global direcionaria
  o log de todas as contas para um único diretório (ou falharia).
- `opcache.validate_timestamps=0` exige reset de OPcache no deploy.
- **Ordem:** P0-A (compressão) → P0-B (OPcache) → P0-C (APCu).

### 4.3 Verificação

```bash
/opt/cpanel/ea-php72/root/usr/bin/php -i \
  | grep -E 'opcache.enable|opcache.memory_consumption|opcache.interned_strings_buffer|opcache.max_accelerated_files|opcache.validate_timestamps|realpath_cache'
```

Valores esperados: `enable=On`, `memory_consumption=256`,
`interned_strings_buffer=32`, `max_accelerated_files=10000`,
`validate_timestamps=Off`, `realpath_cache_size=4096K`, `realpath_cache_ttl=600`.

### 4.4 Rollback

Restaurar os valores originais no MultiPHP INI Editor » System e salvar; reiniciar
o PHP-FPM.

---

## 5. Anexo A — `php.ini.recomended` (conta) literal

```ini
; ==============================================================================
; PORTAIS V5/V6 — php.ini de PRODUÇÃO (EasyApache4 / cPanel, ea-php72 / PHP 7.2)
; APLICAR: cPanel > MultiPHP INI Editor > modo "Editor" (avancado)
; ==============================================================================

[PHP]

; --- Erro e log ---
display_errors = Off
display_startup_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

; ---- ATENCAO AO USUARIO -----
error_log = "/home/__USUARIO_DO_CPANEL__/logs/php.error.log"
; -----------------------------

; --- Superficie do interpretador ---
expose_php = Off
enable_dl = Off
cgi.fix_pathinfo = 0

; --- URL wrappers ---
allow_url_include = Off
allow_url_fopen = On

; --- Sessao (endurecimento nativo) ---
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_secure = On
session.sid_bits_per_char = 5
session.save_path = "/var/cpanel/php/sessions/ea-php72"
session.gc_maxlifetime = 2880
session.gc_probability = 1
session.gc_divisor = 100
; session.cookie_samesite = "Lax"   ; PHP 7.3+ (ea-php72=7.2: ignorado; SameSite via .htaccess H7)

; --- Limites operacionais ---
max_execution_time = 300
max_input_time = 300
max_input_vars = 5000
memory_limit = 512M
post_max_size = 105M
upload_max_filesize = 100M
max_file_uploads = 50

; --- OPcache (producao) ---
; ATENCAO RESTRICAO DE ESCOPO: opcache.* e realpath_cache.* sao PHP_INI_SYSTEM.
; Neste php.ini de CONTA (MultiPHP INI "Editor") eles sao IGNORADOS silenciosamente.
; A fonte real e o WHM MultiPHP INI Editor > System > ea-php72.
; Veja wiki/infra-update/WHM.md (P0-B). Bloco mantido so como referencia visual.
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 16229
opcache.revalidate_freq = 15
opcache.validate_timestamps = 1

; --- I/O e localidade ---
; realpath_cache_* TAMBEM e PHP_INI_SYSTEM (no-op na conta; ver WHM P0-B).
realpath_cache_size = 4096K
realpath_cache_ttl = 600
; OFF de proposito: a compressao e server-side (cPanel Optimize Website / mod_deflate).
; Ligar aqui duplicaria a compressao e conflituaria com o gzip do Apache.
zlib.output_compression = Off
date.timezone = "America/Sao_Paulo"

; --- Performance extra (escopo USER/PERDIR — APLICA na conta) ---
; PCRE JIT: acelera todas as regex (rotas, validacao, filtros). PERDIR: valido no .user.ini.
pcre.jit = On
; Desliga assertions em producao (ganho de CPU + evita vazamento de info via assert).
; PHP_INI_PERDIR: valido na conta.
zend.assertions = -1
; JIT de variaveis globais super ($_GET/$_POST) ja On por padrao; explicito p/ robustez.
auto_globals_jit = On

; NOTA: zend.exception_ignore_args = On existe so a partir do PHP 7.4
; (ea-php72 = 7.2, NAO disponivel). Incluir apos upgrade de versao.
```

---

## 6. Anexo B — `whm.php.ini.recomended` (sistema/WHM) literal

> Aplicar em **WHM » MultiPHP INI Editor » System » ea-php72**. Contém apenas
> chaves `PHP_INI_SYSTEM`.

```ini
; ==============================================================================
; PORTAIS V5/V6 — php.ini DE SISTEMA recomendado (EasyApache4 / cPanel, ea-php72 / PHP 7.2)
; APLICAR EM: WHM > Software > MultiPHP INI Editor > System > ea-php72
; (cole o conteudo abaixo no editor "System"; ele funde/sobrescreve as chaves no
;  php.ini de sistema do EA4: /opt/cpanel/ea-php72/root/etc/php.ini)
; ==============================================================================
;
; ATENCAO — o que vai AQUI e o que NAO vai:
; - So chaves PHP_INI_SYSTEM valem no sistema/WHM. Este arquivo contem so essas.
; - NAO inclui endurecimento de CONTA (expose_php, session.*, limites, pcre.jit,
;   zend.assertions): sao PERDIR/USER e vao no php.ini.recomended da CONTA.
; - NAO use error_log com caminho de usuario aqui: escopo global direcionaria o log
;   de TODAS as contas para um unico diretorio (ou falharia).
; - opcache.validate_timestamps = 0 exige reset de OPcache no deploy (wiki WHM.md B.4).
;
; Ordem (wiki/infra-update/WHM.md): P0-A (compressao) -> P0-B (OPcache) -> P0-C (APCu).

[PHP]

; --- OPcache (producao) — PHP_INI_SYSTEM ---
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 32
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 60
opcache.validate_timestamps = 0
opcache.save_comments = 1

; --- realpath cache — PHP_INI_SYSTEM ---
realpath_cache_size = 4096K
realpath_cache_ttl = 600

; --- APCu autoloader (P0-C) — PHP_INI_SYSTEM ---
; 1) Instale a extensao no WHM EasyApache 4 (Customize > PHP Extensions > apcu > Provision).
;    O pacote ea-php72-php-apcu ja habilita apcu.enabled = 1 por padrao (nao precisa das linhas).
; 2) So descomente apos instalar o pacote; senao o PHP emite warning de diretiva invalida:
; apcu.enabled = 1
; apcu.enable_cli = 1
; apc.shm_size = 32M

```

---

## 7. Achado de revisão — comentário do template de sistema sobre APCu

O bloco literal de `whm.php.ini.recomended` (Anexo B) contém este comentário:

```ini
; 1) Instale a extensao no WHM EasyApache 4 (Customize > PHP Extensions > apcu > Provision).
;    O pacote ea-php72-php-apcu ja habilita apcu.enabled = 1 por padrao (nao precisa das linhas).
```

Ele **não corresponde** ao que o próprio `WHM.md` documenta para este servidor:

- o RPM `ea-php72-php-apcu` **não existe** no repositório EA4 deste host;
- a instalação documentada é manual (`pecl install apcu` + `php.d/zzz-apcu.ini`);
- o estado do APCu é **conflitante** entre os documentos (ver `01-whm-cpanel.md` §5.2).

O template foi mantido **literal** por rastreabilidade. Antes de aplicar:

1. Rode `php -m | grep -i '^apcu$'` no `ea-php72`.
2. Se ausente, **não** descomente `apcu.enabled`/`apcu.enable_cli` no sistema sem
   instalar a extensão — o PHP pode emitir warning de diretiva desconhecida.
3. Se presente via `pecl`, garanta que `extension=apcu.so` está no scan dir do EA4
   e revalide após cada rebuild do EasyApache 4.
4. O `composer.json` com `"apcu-autoloader": true` degrada graciosamente; não é
   dependência obrigatória.

> **Regra:** o comentário do template é histórico e não deve ser usado como
> instrução operacional. A fonte de verdade é o `phpinfo`/`php -m` do host.
