Tabela de conteúdos

Nginx com PHP-FPM para framework Laravel

Objetivo

Essta página visa apresentar a configuração correta para configurar o PHP-FPM juntamente com o framework Laravel nos moldes como são desenvolvidas as aplicações pela InfoTIC.

Arquitetura de programação

Os novos sistemas desenvolvidos pela InfoTIC possuem uma separação de camadas. A primeira camada é a de apresentação, geralmente desenvolvido com o framework AngularJS. A segunda camada é a API do sistema, que pode ser desenvolvida em qualquer linguagem de programação e/ou frameworks.

O acesso a API é feito através de funções javascript existentes na camada de apresentação. A API então retorna o resultado para apresentação em tela.

A padronização que estamos adotando para esta configuração é a seguinte:

- url.ufrj.br/ : Endereço para acessar a camada de aplicação (interface do usuário). - url.ufrj.br/api : Endereço para acessar a API desta aplicação.

A figura abaixo mostra como funciona a distribuição da API pelo Nginx, inclusive com possibilidade de balanceamento de carga.

Definição de diretórios

Os diretórios do programa desenvolvido estão organizados, no servidor web, da seguinte forma:

- /var/www       --> Aplicação
-  /var/www/api  --> Diretório da API, que pode ser um apontamento, link simbólico ou local físico.

No servidor php, todos os arquivos estão dentro do diretório /var/www.

Arquivo de configuração

Aqui apresento apenas os arquivos de configuração do virtual host e do php-fpm.

As configurações básicas do nginx não estão descritas nesta página.

PHP-FPM: www.conf

Temos que definir primeiramente a porta que o php escutará no servidor. Por padrão estamos usando a porta 9000, mas qualquer outra pode ser usada.

listen = 9000

Depois disso precisamos dizer com qual usuário o deamon do php-fpm executará.

user = www-data
group = www-data

O próximo passo é a definição das diretivas do pool. Estamos usando o valor padrão nos servidores:

pm = dynamic
pm.max_children = 6
pm.start_servers = 3
pm.min_spare_servers = 3
pm.max_spare_servers = 5
pm.max_requests = 500
pm.status_path = /fpm-status-zwei
ing.path = /ping-zwei
request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/$pool.log.slow
rlimit_files = 4096
rlimit_core = 0
catch_workers_output = yes

Precisamos definir em qual diretório o php-fpm interpretará os arquivos php. Adotamos como padrão executar os arquivos no diretório /var/www.

chdir = /var/www

Por fim, definimos o timezone.

php_admin_value[date.timezone] = America/Sao_Paulo

Nginx: vhos.conf

O arquivo de configuração do nginx possui algumas características próprias para configurar a api. Descreverei abaixo cada uma delas e o porquê de serem feitas desta forma.

Iniciamos pelo root da aplicação. Apesar de estarmos tratando da API, o nginx processará todas as páginas, tando da inteface quanto API. Por este motivo o root da aplicação deve ser o diretório /var/www.

    root /var/www;
 
    # Localização básica do website.
    location /{
       index index.html;
    }

O próximo passo é fazer com que o nginx encaminhe todas as requisições da API para o servidor PHP-FPM.

location /api  {
        alias /var/www/api/public;
        try_files $uri $uri/ @api;
    }
 
    # Reescrita da URL usando o caminho correto (alias) da uri /api.
    location @api{
        rewrite ^/api/(.*)$ /api/public/index.php?$1 last; # THIS IS THE IMPORTANT LINE
    }

Aqui cabe uma observação: precisamos criar uma localização funcional chamada @api, pois sem ela o nginx não envia corretamente a informação ao servidor PHP.

Outra observação necessária é que o location tem que ser em /api, sem o til, pois de outra forma o arquivo é enviado para o servidor php, mas em diretório absoluto, o que gera o erro de arquivo não encontrado.

Apesar da presença do comando try_files, nem todos os arquivos são ignorados. A solução foi forçar a área de exclusão do nginx:

 # Esta diretiva faz com que o php não processe arquivos de website.
    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html|pdf)$ {
	access_log off;
	expires max;
	log_not_found off; 
    }

O próximo passo é informar o servidor do PHP-FPM para processamento.

# Diretivas do PHP-FPM
    location ~ \.php(?:$|/) {
        fastcgi_pass phpfpm:9000;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

Aqui estou usando o nome phpfpm ao invés do IP. Isso é útil caso eu queira, no futuro, criar um sistema de balanceamento de carga pro meu serviço da API.