Filesystem e permissões: rwx, chown, symlink, hardlink
Permissões quebradas causam mais incidentes de segurança e deploy do que quase qualquer outro erro de configuração. Entender rwx, inodes, e a diferença entre symlinks e hardlinks não é opcional — é o básico do básico.
Inodes: o que é um arquivo de verdade
No Linux, um "arquivo" é na verdade duas coisas separadas: o inode (que contém metadados: permissões, dono, tamanho, timestamps, ponteiros para blocos de dados) e a entrada de diretório (que mapeia um nome para um número de inode).
# Ver o inode de um arquivo
ls -i arquivo.txt # mostra número do inode
stat arquivo.txt # metadados completos do inode
# Exemplo de stat output:
# File: arquivo.txt
# Size: 1234 Blocks: 8 IO Block: 4096
# Inode: 393217 Links: 1
# Access: -rw-r--r-- Uid: 1000 / fernando Gid: 1000 / fernando
# Access: 2025-01-15 10:23:45
# Modify: 2025-01-14 09:11:22
# Change: 2025-01-14 09:11:22 ← mtime vs ctime: importante para backupsO diretório é apenas uma tabela: nome → número de inode. Por isso você pode ter múltiplos nomes apontando para o mesmo inode (hardlinks), e por isso renomear um arquivo no mesmo filesystem é instantâneo (só muda a entrada na tabela de diretório, não move dados).
Permissões: lendo rwxr-xr-x
A saída de ls -l mostra algo como: -rwxr-xr-x 1 fernando devs 4096 jan 15 script.sh
- rwx r-x r-x 1 fernando devs 4096 jan 15 script.sh
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ └─ nome
│ │ │ │ │ │ │ │ └─ data modificação
│ │ │ │ │ │ │ └─ tamanho (bytes)
│ │ │ │ │ │ └─ grupo
│ │ │ │ │ └─ dono
│ │ │ │ └─ número de hardlinks
│ │ │ └─ permissões de outros (others)
│ │ └─ permissões do grupo
│ └─ permissões do dono (user)
└─ tipo: - arquivo, d diretório, l symlink, p pipe, s socket Cada grupo de 3 letras significa: r (read=4), w (write=2), x (execute=1). - significa ausência. A notação octal soma os valores:
| Octal | Simbólico | Significado |
|---|---|---|
| 7 | rwx | leitura + escrita + execução |
| 6 | rw- | leitura + escrita |
| 5 | r-x | leitura + execução |
| 4 | r-- | somente leitura |
| 0 | --- | nenhuma permissão |
# Permissões mais comuns em produção
chmod 644 arquivo.html # rw-r--r--: servidor lê, outros lêem, só dono escreve
chmod 755 script.sh # rwxr-xr-x: executável por todos, escrita só dono
chmod 600 .env # rw-------: só o dono lê/escreve (chaves privadas)
chmod 700 ~/.ssh # rwx------: só dono acessa o diretório ~/.ssh
chmod 400 chave.pem # r--------: SSH key — só leitura pelo dono
# Modificações relativas (sem precisar saber o octal atual)
chmod +x script.sh # adiciona execute para todos
chmod -w arquivo.txt # remove write de todos
chmod u+x,g-w script.sh # dono ganha x, grupo perde w
chmod o= arquivo.txt # others ficam sem nenhuma permissão
# Recursivo (cuidado — não use em /!)
chmod -R 755 public/ # recursivo em diretórioDono e grupo: chown e chgrp
# Ver dono e grupo
ls -l arquivo.txt
stat arquivo.txt
# Mudar dono
chown fernando arquivo.txt # muda só o dono
chown fernando:devs arquivo.txt # muda dono e grupo
chown :devs arquivo.txt # muda só o grupo
chown -R www-data:www-data /var/www/html/ # recursivo
# Mudar só o grupo
chgrp devs projeto/
# Ver grupos do usuário atual
id # uid=1000(fernando) gid=1000(fernando) groups=...
groups # lista grupos do usuário corrente
# Adicionar usuário a um grupo
sudo usermod -aG docker fernando # adiciona ao grupo docker
# Após isso, fazer logout+login para o grupo aparecer em `groups`www-data é o usuário padrão do Apache/Nginx. Arquivos do site devem pertencer a www-data ou ter permissão de leitura para ele. Configurar dono errado é a causa mais comum de erros 403 Forbidden em produção.
Symlinks vs Hardlinks: quando usar cada um
# Hardlink — dois nomes para o mesmo inode
ln original.txt hardlink.txt
ls -li # ambos têm o mesmo número de inode e Links: 2
# Deletar um não afeta o outro
# Limitação: não pode cruzar filesystems, não funciona para diretórios
# Symlink (soft link) — arquivo que aponta para um caminho
ln -s /etc/nginx/sites-available/meu-site /etc/nginx/sites-enabled/meu-site
ln -s /home/fernando/projects projeto # link relativo ou absoluto
ls -la # mostra: projeto -> /home/fernando/projects
# Verificar se é link
ls -la arquivo # l no início do tipo (lrwxrwxrwx)
readlink link.txt # mostra o alvo do symlink
realpath link.txt # resolve symlinks e mostra caminho absoluto real
# Remover symlink (NÃO use rm -rf link/ — o / faz remover o conteúdo do alvo!)
rm symlink # correto
unlink symlink # alternativa| Aspecto | Hardlink | Symlink |
|---|---|---|
| Inode | Mesmo inode | Inode próprio |
| Deletar original | Arquivo persiste | Link quebra |
| Cross-filesystem | Não | Sim |
| Para diretórios | Não (na prática) | Sim |
| Caso de uso | Backups incrementais | Alias de config, versionamento |
Casos práticos que quebram deploys
# PROBLEMA 1: script não executa
$ ./deploy.sh
bash: ./deploy.sh: Permission denied
# SOLUÇÃO:
chmod +x deploy.sh
# PROBLEMA 2: app não consegue ler config
# (app roda como www-data, config pertence a root com chmod 600)
ls -la /etc/myapp/config.yaml
# -rw------- 1 root root 512 jan 15 config.yaml
sudo chown www-data /etc/myapp/config.yaml
# ou: sudo chmod 640 /etc/myapp/config.yaml && sudo chgrp www-data /etc/myapp/config.yaml
# PROBLEMA 3: upload de arquivos falha
# (diretório de uploads com dono root, app roda como node)
ls -la /var/www/uploads/
# drwxr-xr-x 2 root root 4096 uploads/
sudo chown -R node:node /var/www/uploads/
# PROBLEMA 4: symlink quebrado após deploy
ls -la /etc/nginx/sites-enabled/
# meu-site -> /etc/nginx/sites-available/meu-site (em vermelho = quebrado)
# O arquivo de origem foi deletado ou está no caminho errado
ln -sf /etc/nginx/sites-available/meu-site /etc/nginx/sites-enabled/meu-siteChecklist de permissões para produção: arquivos de config com segredos → 600 (só dono lê). Executáveis → 755. Uploads/static → 644. Diretórios → 755 ou 750. Nunca 777 em produção.
Próximo: Processos, jobs e sinais — PID, fork, kill, SIGTERM vs SIGKILL, e o que roda no seu sistema.
Próximos passos sugeridos
Discussão
Carregando…