chmod 777 não é solução: permissões no Linux, na prática
Todo tutorial de fórum termina em chmod -R 777. Ele faz o erro sumir e deixa o servidor aberto. Este é o modelo mental que faz você acertar a permissão de primeira.
Equipe EasyOps Cloud · · 7 min de leitura
Permission denied. Você pesquisa, o primeiro resultado manda rodar chmod -R 777,
o erro some e a aplicação volta. Funcionou — e agora qualquer processo do servidor,
incluindo um que entre por uma falha da sua aplicação, pode reescrever esses
arquivos.
O 777 é sedutor porque acerta por eliminação: ele libera tudo, então
necessariamente inclui a permissão que faltava. O custo é que você nunca descobre
qual era.
Os três grupos e as três letras
Toda permissão no Linux responde a duas perguntas: quem e o quê.
O "quem" tem exatamente três faixas:
- user (u) — o dono do arquivo.
- group (g) — o grupo do arquivo.
- other (o) — todo o resto do sistema.
O "o quê" tem três letras, e o valor numérico de cada uma é o que aparece no
chmod:
| Letra | Valor | Em arquivo | Em diretório |
|---|---|---|---|
| r | 4 | ler o conteúdo | listar os nomes dentro |
| w | 2 | alterar o conteúdo | criar e apagar entradas |
| x | 1 | executar | atravessar, acessar o que está dentro |
A coluna da direita é a parte que quase todo mundo aprende errado. Em diretório as letras significam outra coisa, e é daí que vem a maior parte da confusão.
Um diretório com r e sem x permite listar os nomes e não permite abrir nenhum
deles. Um diretório com x e sem r permite abrir um arquivo cujo caminho você já
conhece e não permite descobrir o que existe ali. E w em diretório é a permissão
de apagar os arquivos de dentro — mesmo os que pertencem a outro usuário, mesmo
os marcados como somente leitura. Quem controla quem pode apagar /var/www/html/index.php
é a permissão de /var/www/html, não a do arquivo.
Lendo o ls -l sem decorar
ls -l /var/www/htmldrwxr-xr-x 3 www-data www-data 4096 ago 6 10:12 uploads
-rw-r----- 1 www-data www-data 812 ago 6 10:12 config.phpO primeiro caractere é o tipo (d diretório, - arquivo comum, l link). Os nove
seguintes são três blocos de rwx: dono, grupo, outros. Depois vêm o dono e o
grupo.
Somando os valores por bloco, rwxr-xr-x é 755 e rw-r----- é 640.
Na dúvida, o stat responde nos dois formatos de uma vez:
stat -c '%a %U:%G %n' config.phpOs números que você realmente vai usar
Para a esmagadora maioria dos casos, quatro valores bastam:
644— arquivo comum. O dono edita, o resto lê. É o padrão de código, configuração pública, HTML, imagem.755— diretório, ou script executável. O dono altera, os demais entram e leem.640/750— quando "os demais" não deveriam nem ler. É o valor certo para arquivo com credencial, e600quando nem o grupo precisa.600— chave privada. O SSH recusa a chave se ela for mais aberta que isso, e faz muito bem — é o motivo de metade dos erros ao usar chaves SSH em vez de senha.
Repare que x não aparece em arquivo comum. Um .php, um .env ou um .jpg não
precisam ser executáveis, e marcar tudo como executável de uma vez é outro efeito
colateral do chmod -R 777.
Quase sempre o problema é o dono, não a permissão
Este é o ponto que muda a forma de resolver: Permission denied costuma significar
que o processo certo não é o dono, não que a permissão está apertada demais.
O nginx roda como www-data, o PHP-FPM como www-data, o PostgreSQL como
postgres, a sua aplicação Node como o usuário do User= na unit do systemd. Se
os arquivos pertencem ao root porque você fez o deploy com sudo, a aplicação
não escreve — e a correção é ajustar o dono:
sudo chown -R www-data:www-data /var/www/html/uploads
sudo find /var/www/html -type d -exec chmod 755 {} +
sudo find /var/www/html -type f -exec chmod 644 {} +Os dois find fazem o que chmod -R 755 não faz: aplicam 755 só em diretórios e
644 só em arquivos. Um -R com valor único inevitavelmente erra um dos dois
lados.
Para descobrir com que usuário um serviço roda:
systemctl show nginx -p User
ps -eo user,comm | grep -E 'nginx|php-fpm|node'Quando duas contas precisam do mesmo diretório
O caso comum: você faz deploy com seu usuário e o servidor web precisa ler — ou
escrever — no mesmo lugar. A resposta é grupo compartilhado, não 777.
sudo usermod -aG www-data deploy
sudo chown -R deploy:www-data /var/www/html
sudo chmod -R g+rwX /var/www/html
sudo chmod g+s /var/www/htmlDuas sutilezas valiosas nesse bloco:
Xmaiúsculo aplicaxapenas onde ele faz sentido: diretórios e arquivos que já eram executáveis. É a forma correta de usar-Rsem transformar todo arquivo em executável.g+s(setgid) faz todo arquivo novo criado ali herdar o grupo do diretório. Sem isso, o próximo arquivo que odeploycriar nasce com o grupodeploye o servidor web perde o acesso de novo — motivo pelo qual a permissão "volta a quebrar sozinha" depois de cada deploy.
Depois de usermod -aG, o usuário precisa abrir uma sessão nova para o grupo valer.
Confirme com id deploy.
umask: por que o arquivo novo já nasce assim
Arquivo novo não nasce 777. O sistema aplica uma máscara que subtrai permissões:
umask # normalmente 022Com 022, arquivos nascem 644 e diretórios 755. É por isso que o arquivo que
seu script acabou de criar não é gravável pelo grupo mesmo com o diretório
configurado — a máscara tirou. Para um processo específico, ajuste o UMask= na
unit do systemd em vez de mexer no valor global:
[Service]
UMask=0002ACL: quando o modelo de três faixas não chega
Dono, grupo e outros dão conta de quase tudo. Quando não dão — dois grupos com níveis diferentes no mesmo diretório, por exemplo — a saída não é abrir para "outros", é usar ACL:
sudo setfacl -m g:auditoria:rx /var/log/meuapp
sudo setfacl -d -m g:auditoria:rx /var/log/meuapp # vale para arquivos futuros
getfacl /var/log/meuappO -d define a ACL padrão, que é o equivalente do setgid para permissões: sem
ele, você acerta os arquivos de hoje e erra os de amanhã.
Um + no fim do ls -l (-rw-rwxr--+) indica que o arquivo tem ACL. Se as
permissões parecem certas e o acesso não bate, getfacl costuma explicar.
O caso especial: /tmp e o sticky bit
ls -ld /tmp
drwxrwxrwt 15 root root 4096 ago 6 10:12 /tmpO t final é o sticky bit. Ele existe justamente para consertar o efeito
colateral do 777 em diretório: com ele, qualquer um cria arquivo ali, mas só o
dono do arquivo pode apagá-lo. É a prova de que "todo mundo pode escrever" e
"todo mundo pode destruir" precisaram ser separados.
O checklist para quando aparecer Permission denied
- Quem está tentando?
systemctl show <unit> -p User, ou o usuário do processo nops. - Qual arquivo, exatamente? A mensagem quase sempre diz. Se não disser, o
strace -f -e trace=filemostra a chamada que falhou. - Ele consegue atravessar o caminho todo?
namei -l /var/www/html/uploads/foo.txtimprime a permissão de cada nível. Um diretório semxno meio do caminho bloqueia tudo abaixo, mesmo com o arquivo final aberto. - É dono ou é permissão?
chownresolve o primeiro caso,chmodo segundo. Nesta ordem. - Nada bate? Procure SELinux ou AppArmor:
sudo ausearch -m avc -ts recent, ousudo dmesg | grep -i denied.
Antes de sair distribuindo chmod em produção
Uma alteração recursiva de permissão é fácil de fazer e difícil de desfazer — não
existe "desfazer" para um chmod -R que passou por cima de milhares de arquivos
com valores diferentes. Tire um snapshot antes,
ou pelo menos guarde o estado atual para poder reconstruir:
getfacl -R /var/www > /root/permissoes-var-www.acl
# para restaurar:
setfacl --restore=/root/permissoes-var-www.aclE se o servidor está exposto à internet, a permissão de arquivo é a segunda camada. A primeira é não deixar a porta aberta: veja como configurar regras de firewall.