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.