DevOps Mind
Como resolver erros de permissões no Laravel logs
O erro no Laravel sobre Permission Denied é um dos problemas mais frustrantes que desenvolvedores e times de DevOps/SRE podem encontrar ao trabalhar com o framework Laravel. Este problema geralmente ocorre devido a configurações incorretas de permissões de arquivos e diretórios relacionados a Laravel Logs, especialmente em ambientes de produção. Neste artigo, vamos explorar as principais causas e apresentar soluções definitivas para resolver este erro e evitar indisponibilidades na sua aplicação PHP.
Tópicos
Principais erros de permissões no Laravel
O Laravel é um popular framework PHP usado por muitos desenvolvedores para criar aplicativos web. Um problema comum que pode ocorrer ao trabalhar com o Laravel é o erro:
The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: permission denied
Esse erro ocorre quando o Laravel não consegue gravar em seu arquivo de log, porque não tem permissão para acessar a pasta de armazenamento.
Outro erro muito comum, que pode acontecer quanto não temos as permissões definidas corretamente no Laravel, é o erro abaixo:
Error in exception handler: The stream or file "/var/www/laravel/app/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied in /var/www/laravel/bootstrap/compiled.php:8423
Solução paliativa
Uma solução que é indicada em muitos fóruns e blogs, é aplicarmos a permissão chmod 777
, que acaba deixando nosso servidor muito exposto.
Em alguns casos são sugeridos outros comandos chmod
, chgrp
, que até podem não deixar o servidor com a segurança menor, mas não trazem uma solução definitiva para erros de permissão no Laravel.
Solução definitiva
Felizmente, há uma solução relativamente fácil para esse problema. Você pode aplicar permissões e herança nas permissões da pasta /var/www/html/storage/logs
no servidor.
Para fazer isso, você precisará acessar o servidor onde o Laravel está hospedado e executar alguns comandos na pasta do projeto(neste exemplo estamos usando a /var/www/html/
).
Outro ponto importante é que eu procuro adicionar os usuários que trabalham com o Laravel ao grupo www-data
, para que após aplicada a solução eles consigam manipular os arquivos sem trazer problemas e novos erros de permissão no Laravel.
Segue o script que devemos utilizar, adapte ele conforme a sua necessidade:
## laravel log permission
cd /var/www/html/
sudo chgrp -R www-data bootstrap/ storage/ storage/logs/
sudo chmod -R 755 bootstrap/ storage/ storage/logs/
sudo chmod -R g+w bootstrap/ storage/ storage/logs/
cd bootstrap/
sudo find -type d -exec chmod g+s {} +
cd ..
cd storage/
sudo find -type d -exec chmod g+s {} +
cd ..
cd storage/logs/
sudo find -type d -exec chmod g+s {} +
Um pouco mais sobre cada comando
Esse script em Bash é usado para conceder permissões corretas para os diretórios bootstrap/
, storage/
e storage/logs/
de um projeto Laravel que está localizado em /var/www/html/
. Especificamente, o script define o grupo proprietário desses diretórios como www-data
, que é o usuário e grupo padrão do servidor da web no Ubuntu. Além disso, o script garante que esses diretórios tenham permissões de gravação para o grupo www-data
.
A parte do script que se refere a herança de permissões é a seguinte linha:
sudo find -type d -exec chmod g+s {} +
Essa linha define o bit SGID em todos os diretórios dentro dos diretórios bootstrap/
, storage/
e storage/logs/
. Quando o bit SGID é definido em um diretório, ele garante que todos os novos arquivos criados dentro desse diretório herdem o grupo proprietário do diretório pai. Isso é útil para garantir que todos os arquivos criados dentro dos diretórios bootstrap/
, storage/
e storage/logs/
tenham o mesmo grupo proprietário (www-data
) e, portanto, possam ser lidos e gravados pelo servidor da web.
Em resumo, o script executa as seguintes ações:
- Navega até a pasta do projeto Laravel em
/var/www/html/
. - Define o grupo proprietário dos diretórios
bootstrap/
,storage/
estorage/logs/
comowww-data
. - Concede permissões 755(O dono do arquivo tem permissão total. O grupo do arquivo tem permissão de leitura e execução. Outros usuários têm permissão de leitura e também de execução.) e gravação para o grupo
www-data
nos diretóriosbootstrap/
,storage/
estorage/logs/
. - Define o bit SGID em todos os diretórios dentro dos diretórios
bootstrap/
,storage/
estorage/logs/
, para garantir a herança de permissões de grupo em novos arquivos criados nesses diretórios.
Detalhando cada opção dos comandos
sudo chgrp -R
sudo
: o comando sudo
é usado para executar comandos com privilégios de super usuário (root) no sistema operacional Linux ou Unix.
chgrp
: o comando chgrp
é usado para alterar o grupo proprietário de um arquivo ou diretório.
-R
: é uma opção para o comando chgrp
que significa “recursivamente”. Ela faz com que o comando seja executado em todos os diretórios e subdiretórios abaixo do diretório atual.
Em resumo, o comando sudo chgrp -R altera recursivamente o grupo proprietário de todos os arquivos e diretórios abaixo do diretório atual.
sudo chmod 755
A permissão 755 é uma configuração de permissões comumente usada em sistemas operacionais baseados em Unix, como Linux e macOS. Ela define os seguintes níveis de acesso:
- Dono do arquivo:
- Leitura (r)
- Escrita (w)
- Execução (x)
- Grupo do arquivo:
- Leitura (r)
- Execução (x)
- Outros usuários:
- Leitura (r)
- Execução (x)
Isso significa que:
- O dono do arquivo tem permissão total (leitura, escrita e execução).
- O grupo do arquivo tem permissão de leitura e execução.
- Outros usuários têm permissão de leitura e a permissão de execução.
sudo chmod -R g+w
sudo
: igual ao anterior
chmod
: é um comando que é usado para alterar as permissões de acesso de um arquivo ou diretório.
-R
: igual ao anterior
g+w
: é uma opção para o comando chmod
que significa “adicionar permissão de escrita para o grupo”. “g” é o grupo proprietário do arquivo ou diretório.
Em resumo, o comando sudo chmod -R g+w
adiciona a permissão de escrita para o grupo proprietário em todos os arquivos e diretórios abaixo do diretório atual.
sudo find -type d -exec chmod g+s {} +
sudo
: igual ao anterior
find
: é um comando usado para encontrar arquivos e diretórios com base em critérios específicos.
-type d
: é uma opção para o comando find
que significa “encontrar apenas diretórios”.
-exec
: é uma opção para o comando find
que executa um comando em cada arquivo ou diretório encontrado.
chmod g+s
: é o comando que será executado em cada diretório encontrado pelo find
. “g” é o grupo proprietário do diretório e “s” é uma opção que significa “definir o bit setgid”. Isso faz com que todos os arquivos criados dentro do diretório herdem o grupo proprietário do diretório.
{}
: é um espaço reservado para o nome do arquivo ou diretório encontrado pelo find
.
+
: indica que o comando chmod g+s
deve ser executado uma vez para cada grupo de arquivos ou diretórios encontrados.
Em resumo, o comando sudo find -type d -exec chmod g+s {} +
encontra todos os diretórios abaixo do diretório atual e executa o comando chmod g+s
em cada um deles, garantindo que todos os arquivos criados dentro desses diretórios tenham o mesmo grupo proprietário.
Exemplo na prática
Aqui no meu laboratório eu gosto de utilizar o projeto Travellist – Laravel Demo App, que utiliza framework PHP Laravel, para praticar a instalação e o uso básico do Laravel, ele sobe um aplicativo de lista de viagens de exemplo, para mostrar uma lista de lugares para onde um usuário gostaria de viajar e uma lista de lugares que ele já visitou.
Após subir o projeto e acessar ele via Browser, esta é a página que é mostrada:
Como é possível verificar na imagem abaixo, os arquivos e pastas estão com as permissões setadas de forma correta e os Containers estão funcionando dentro do esperado:
Um diretório que é bem importante, pois grava todos os logs do Laravel, é o diretório storage/logs
Verificando as permissões deste diretório e dos diretórios que estão dentro do storage
:
Erros de permissões no Laravel e seu diretório storage
ou no diretório logs
, podem levar a falhas na sua aplicação e ocorrência de erros de “Permission denied” relacionados a pasta /var/www/storage/logs
Neste exemplo abaixo eu estou efetuando um ajuste incorreto nas permissões do diretório storage
, para forçar a ocorrência do erro de permissão:
Com as permissões setadas incorretamente, se eu tento acessar novamente a página do Travellist no meu ambiente local, ocorre o seguinte erro:
Mensagem de erro:
UnexpectedValueException
There is no existing directory at "/var/www/storage/logs" and its not buildable: Permission denied
Para regularizar as permissões do diretório storage e os diretórios abaixo dele, executei os comandos abaixo:
docker exec -u 0 -it travellist-app /bin/bash
chgrp -R www-data storage/ storage/logs/
chmod -R 755 storage/ storage/logs/
chmod -R g+w storage/ storage/logs/
cd storage/
find -type d -exec chmod g+s {} +
Importante destacar que, neste caso eu utilizei um comando Docker para acessar o container como usuário root, para conseguir aplicar estes comandos, conforme o parâmetro:
-u 0
: Especifica o ID do usuário (0
é o ID do root
)
Não devem ocorrer erros durante a aplicação dos comandos, conforme abaixo:
Após aplicar os comandos, o acesso a página do projeto em Laravel é restabelecido:
Material de apoio
- Vou estar disponibilizando o Script da solução definitiva no meu Github, caso precisem:
- Documentação do Laravel
- Guia de Configuração do Laravel
- Guia de Segurança do Laravel
O erro “Laravel Permission Denied” pode parecer complicado, mas as soluções são diretas quando entendemos o funcionamento do sistema de permissões. Configurar corretamente os diretórios storage
e bootstrap/cache
, ajustar o usuário e grupo, e garantir que não sejam modificadas as permissões de forma indevida são etapas fundamentais para evitar que esse erro atrapalhe o funcionamento do projeto.
Mais dicas sobre solução de problemas? Acesse: https://devopsmind.com.br/category/troubleshooting