Nosso setup de PHP segue a linha do nginx para ser seguro. Por isso temos que olhar para algumas questões específicas e muito mal documentadas por aí. Também é necessário observar que a abordagem do PHP no nginx é radicalmente diferente daquela disponível no Apache. Não existe um mod_php. O nginx usa outro treco para 'conversar' com o PHP: PHP-FPM.

Esse método, que eu considero bem mais eficiente e flexível que o mod_php do Apache, separa bem as coisas. O nginx é servidor web, o PHP é linguagem de programação interpretada. O nginx serve objetos, o PHP executa scripts. O nginx recebe a requisição para executar um script .php, repassa essa tarefa ao PHP-FPM, que por sua vez devolve o resultado ao nginx. Muito mais fácil de entender e isolar problemas.

Natação PHP-FPM

A primeira coisa a fazer é configurar o PHP-FPM e sua piscina (pool). Para isso você vai editar o arquivo /etc/php-fpm/php-fpm.conf e fazer apenas as mudanças apontadas pelo patch abaixo:

--- php-fpm.conf.default        2015-04-17 13:41:55.000000000 -0300
+++ php-fpm.conf        2015-05-14 21:07:00.901951747 -0300
@@ -29,7 +29,7 @@
; in a local file.
; Note: the default prefix is /var
; Default Value: log/php-fpm.log
-error_log = log/php-fpm.log
+error_log = log/php-fpm

; syslog_facility is used to specify what type of program is logging the
; message. This lets syslogd specify that messages from different facilities
@@ -145,8 +145,8 @@
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
-user = apache
-group = apache
+user = nobody
+group = nogroup

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
@@ -156,7 +156,7 @@
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
-listen = 127.0.0.1:9000
+listen = /var/run/php5-fpm.sock

; Set listen(2) backlog.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
@@ -167,8 +167,8 @@
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
;                 mode is set to 0660
-;listen.owner = apache
-;listen.group = apache
+listen.owner = nobody
+listen.group = nogroup
;listen.mode = 0660

; List of ipv4 addresses of FastCGI clients which are allowed to connect.

As alterações relevantes aqui são:

  1. O arquivo de log do PHP-FPM é algo dentro do contexto que o Slackware usa, sem a extensão .log. Se sua distribuição não é assim, essa mudança pode ser ignorada.
  2. O método utilizado para as requisições ao pool de processos do PHP-FPM ([www]). Note que esse método é exatamente aquele esperado pelo nginx, definido no arquivo /etc/nginx/php com a opção fastcgi_pass. Os dois precisam ser iguais. Como o nosso servidor rodará tudo sozinho, não faz sentido ele ouvir numa porta TCP, por isso trocamos para um arquivo socket (/var/run/php5-fpm.sock).
  3. O usuário e grupo utilizados pela execução do pool, que devem ser iguais aos configurados para o nginx.
  4. O usuário e grupo definidos para o socket, também iguais aos do nginx.

PHP regrado

O PHP é usado pelo PHP-FPM para, bem, rodar PHP. Ele faz isso de modo muito semelhante ao que você faria se rodasse php script.php na linha de comando. Isso torna a solução toda muito robusta, mas também suscetível a brechas de segurança se não for bem feita. E não queremos brechas, então configuramos o PHP direito.

Crie o arquivo /etc/php/fastgi.ini e coloque isso nele:

; Enable cgi.fix_pathinfo as required for nginx
; This could be a security risk if not done according to
; http://wiki.nginx.org/PHPFcgiExample
cgi.fix_pathinfo = 1

Agora crie o arquivo /etc/php/logging.ini com esse conteúdo:

; php logging settings
display_errors = off
log_errors = On
error_log = /var/log/php
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

Por fim, crie o arquivo /etc/php/timezone.ini com o conteúdo abaixo. Se o seu fuso horário for diferente, pode alterar de acordo.

; Set default timezone
date.timezone = "America/Sao_paulo"

Ao longo da série, o PHP receberá outras configurações. Por hora essas são suficientes.

Testando, 1, 2, 3...

Agora que o PHP está pronto para falar com o nginx, vamos promover esse belo encontro. Música romântica ao fundo.

Precisamos iniciar o PHP-FPM. Isso é feito com:

# chmod 755 /etc/rc.d/rc.php-fpm
# /etc/rc.d/rc.php-fpm start

Hora de conferir se tudo correu bem.

# ps -ef | grep fpm
root     15515     1  0 21:01 ?        00:00:00 php-fpm: master process (/etc/php-fpm/php-fpm.conf)
nobody   15516 15515  0 21:01 ?        00:00:00 php-fpm: pool www
nobody   15517 15515  0 21:01 ?        00:00:00 php-fpm: pool www
# cat /var/log/php-fpm
[14-May-2015 21:01:01] NOTICE: fpm is running, pid 15515
[14-May-2015 21:01:01] NOTICE: ready to handle connections
# cat /var/log/php
<Nada!>
# ls -lah /var/run/php*
-rw-r--r-- 1 root   root    5 May 14 21:07 /var/run/php-fpm.pid
srw-rw---- 1 nobody nogroup 0 May 14 21:07 /var/run/php5-fpm.sock=
# ss -lxp|grep fpm
u_str  LISTEN     0      128    /var/run/php5-fpm.sock 19241                 * 0       users:(("php-fpm",15670,0),("php-fpm",15669,0),("php-fpm",15668,7))

Se sua saída foi semelhante a acima, tudo certo.

Agora vamos rodar um scriptzinho PHP pra ver se o rolou um lance entre o nginx e o PHP-FPM.

# mkdir -p /var/www/backend/public
# vi /var/www/backend/public/index.php

Cole nele isso e salve:

<?php phpinfo() ?>

Agora acesse https://mail.exemplo.com:3443/. Se aparecer a página de informação do PHP, cara, você é foda!!! Se não, você continua sendo foda, e os fodas cometem erros também. Revise tudo, descubra onde errou e corrija.

Com o teste concluído, remova o diretório do teste:

# rm -rf /var/www/backend/public

Neste ponto você tem um servidor web seguro com PHP e MariaDB que pode ser usado para qualquer finalidade. Se gostou desse setup, você pode adotá-lo como um método padrão. A partir da próxima etapa as coisas começam a ficar diferentes.