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 deniedEsse 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:8423Soluçã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-datanos 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









