Files
instrucoes_gerais/global/seguranca_deploy_user.md
T

219 lines
10 KiB
Markdown

# 🛡️ Guia de Segurança e Liberdade para o Usuário `deploy`
Na cultura de DevOps moderna, a "lenda" do usuário `deploy` poder trabalhar com total liberdade sem ter acesso ao usuário `root` é, na verdade, uma **melhor prática de segurança chamada "Princípio do Menor Privilégio" (Least Privilege)**.
Se o usuário `deploy` pudesse dar `sudo su` e virar `root` a qualquer momento, qualquer vulnerabilidade na sua aplicação web (ex: um upload de arquivo malicioso ou injeção de código) daria controle total do servidor inteiro para um invasor.
Para dar ao usuário `deploy` toda a liberdade de desenvolvimento e publicação de aplicações com **segurança absoluta**, implementamos 4 pilares práticos:
---
## 🏗️ Pilar 1: Controle Total do Diretório Web (Sem `sudo`)
O usuário `deploy` não precisa de permissão de root para alterar os arquivos da aplicação. Basta torná-lo dono dos diretórios de publicação.
### Prática:
Geralmente usamos a pasta `/var/www/` ou criamos um diretório de aplicações na própria Home do usuário (`/home/deploy/apps/`).
Para dar controle total ao `deploy` sem precisar de `sudo` para editar arquivos:
```bash
# Criar a pasta do seu projeto
sudo mkdir -p /var/www/meu-app
# Definir o usuário deploy como proprietário da pasta
sudo chown -R deploy:deploy /var/www/meu-app
# Aplicar permissões recomendadas (pastas 755 e arquivos 644)
find /var/www/meu-app -type d -exec chmod 755 {} \;
find /var/www/meu-app -type f -exec chmod 644 {} \;
```
**Resultado**: O usuário `deploy` agora pode usar Git, SFTP, VSCode, criar arquivos, deletar e subir atualizações dentro de `/var/www/meu-app` com total liberdade e **zero** necessidade de usar `sudo`.
---
## 🐋 Pilar 2: Gerenciamento do Docker sem Root
> [!CAUTION]
> **Esta infraestrutura usa Docker Rootless (VPS 1).** As instruções abaixo são válidas para instalações com Docker tradicional. Para Docker Rootless, veja a seção específica mais abaixo.
Se as suas aplicações rodam em Docker (ou Docker Compose) **com o daemon tradicional (root)**, o usuário `deploy` não precisa usar `sudo docker` para gerenciar os containers.
### Prática (Docker tradicional):
Adicionar o usuário `deploy` ao grupo `docker`:
```bash
sudo usermod -aG docker deploy
```
**Resultado**: O usuário `deploy` poderá rodar `docker compose up -d`, builds etc. sem `sudo`.
> [!WARNING]
> **Nunca faça isso em servidores que também rodam Docker Rootless.** Adicionar `deploy` ao grupo `docker` dá acesso ao socket `/var/run/docker.sock` (root), criando um vetor de escalonamento de privilégios. Qualquer `docker compose up` sem `DOCKER_HOST` explícito cria containers como root silenciosamente.
---
### Prática correta para Docker Rootless (VPS 1):
A VPS 1 usa **Docker Rootless** (`rootlesskit` + `vpnkit`, daemon rodando como `deploy`). A configuração correta é:
1. **`deploy` NÃO está no grupo `docker`** — sem acesso ao socket root `/var/run/docker.sock`
2. **`DOCKER_HOST` definido por padrão** no `~/.bashrc` e `~/.profile`:
```bash
export DOCKER_HOST=unix:///run/user/1000/docker.sock
```
3. **Daemon root desabilitado** (`docker.service` e `docker.socket` disabled)
Com isso, qualquer `docker` ou `docker compose` executado pelo `deploy` — interativo ou via script SSH — sempre usa o daemon rootless automaticamente.
#### Verificar estado correto:
```bash
# deploy NÃO deve aparecer em:
groups deploy # não deve conter "docker"
# daemon root deve estar morto:
sudo systemctl status docker # inactive (dead)
# rootless deve responder:
DOCKER_HOST=unix:///run/user/1000/docker.sock docker ps
```
---
### Incidente registrado — 2026-05-14
**O que aconteceu:** O daemon root (`/usr/bin/dockerd`) estava ativo em paralelo com o rootless. O usuário `deploy` pertencia ao grupo `docker`. Durante um deploy, `docker compose up --build` executou sem `DOCKER_HOST`, criando containers duplicados como root (frontend, backend, nginx) que rodavam ao lado dos containers rootless corretos — invisíveis ao monitoramento normal (`docker ps` sem sudo não os mostrava).
**Consequência direta:** O `docker-proxy` root reteve a porta 8020 após um `docker rm -f`, bloqueando o nginx rootless de reiniciar. O site ficou inacessível até o `docker-proxy` zumbi ser identificado (`sudo ss -tlnp`) e morto.
**Correção aplicada:**
```bash
# 1. Remover containers e imagens duplicados do daemon root
cd /home/deploy/stack/scoreodonto.com
sudo docker compose down --remove-orphans
sudo docker image rm scoreodontocom-scoreodonto-frontend scoreodontocom-scoreodonto-backend
sudo docker network rm soc web
sudo docker builder prune -af
# 2. Desabilitar daemon root definitivamente
sudo systemctl disable --now docker docker.socket
# 3. Remover deploy do grupo docker
sudo gpasswd -d deploy docker
# 4. Garantir DOCKER_HOST nos shells de login (já estava no .bashrc, adicionado ao .profile)
echo 'export DOCKER_HOST=unix:///run/user/1000/docker.sock' >> ~/.profile
```
---
## ⚙️ Pilar 3: Sudoers com Limitação Cirúrgica (Segurança Avançada)
Muitas vezes, a aplicação precisa apenas de tarefas muito específicas do sistema operacional, como por exemplo:
* Reiniciar o servidor web Nginx (`systemctl restart nginx`).
* Recarregar as configurações do Nginx (`systemctl reload nginx`).
* Reiniciar um serviço específico da sua aplicação em NodeJS/Python criado no Systemd (`systemctl restart api-app`).
### Prática:
Em vez de dar acesso total ao `sudo` para o `deploy`, nós liberamos **apenas estes comandos específicos**, sem requisição de senha!
1. Criamos um arquivo de configuração exclusivo no Sudoers para o `deploy`:
```bash
sudo nano /etc/sudoers.d/deploy
```
2. Adicionamos a regra cirúrgica:
```text
# Permite que o usuário deploy execute APENAS estes comandos listados como root, sem pedir senha:
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx
```
3. Aplicamos a permissão correta ao arquivo do sudoers:
```bash
sudo chmod 440 /etc/sudoers.d/deploy
```
**Resultado**: O usuário `deploy` agora pode rodar `sudo systemctl reload nginx` para aplicar uma mudança de domínio na web com total liberdade, mas se ele tentar rodar `sudo apt update` ou `sudo userdel`, o sistema **negará o acesso**.
---
## 🔄 Pilar 4: Processos em Espaço de Usuário (PM2 / Systemd User)
Se a sua aplicação web não roda em Docker e precisa ficar ativa em segundo plano (ex: aplicações Node.js, Python FastAPI, Go), o usuário `deploy` pode gerenciá-la de duas formas sem root:
### A. Utilizando o PM2 (NodeJS Process Manager)
O PM2 roda diretamente no espaço de memória do usuário `deploy`.
```bash
# Como usuário deploy, instalar e rodar apps:
pm2 start app.js --name "minha-api"
pm2 save
```
O `deploy` tem controle total para reiniciar (`pm2 restart minha-api`), parar, e ver logs sem precisar do root.
### B. Serviços Systemd do Usuário (`systemd --user`)
O Linux moderno permite que usuários criem seus próprios arquivos de serviço que rodam sob sua conta na pasta:
`~/.config/systemd/user/`
Você pode gerenciar o serviço rodando:
```bash
systemctl --user daemon-reload
systemctl --user restart meu-servico.service
```
---
## 📊 Tabela de Comparação de Segurança:
| Ação | Como o Root faria (Inseguro) | Como o `deploy` faz com segurança |
| :--- | :--- | :--- |
| **Subir arquivos Web** | Usa `sudo` ou loga como `root` | Altera livremente dentro de `/var/www/` (Dono da pasta) |
| **Gerenciar Containers** | `sudo docker compose restart` | `docker compose restart` (Membro do grupo `docker`) |
| **Reiniciar Nginx** | `sudo systemctl restart nginx` | `sudo systemctl restart nginx` (Autorizado via Sudoers Cirúrgico) |
| **Atualizar Código (Git)** | Roda `git pull` como root | Roda `git pull` usando suas chaves SSH do usuário |
---
## 🧹 Pilar 5: Hardening de Terminal e Wiping de Histórico (SecOps)
Para evitar o vazamento acidental de credenciais passadas inline (como senhas, chaves de API, segredos do banco de dados) e proteger o buffer visual do console em acessos públicos, todas as VPSs do enxame contam com a **limpeza automática de sessão e apuramento de logs no logout**.
### Prática:
Configuramos o arquivo `/home/deploy/.bash_logout` do usuário `deploy` em todas as máquinas para disparar a seguinte rotina de segurança ao encerrar a conexão:
```bash
# ~/.bash_logout: executado pelo bash quando a sessão do terminal termina.
# Hardening de Segurança (SecOps) - Limpeza automática de histórico e console
if [ "$SHLVL" = 1 ]; then
# 1. Limpa o histórico em memória e apaga o arquivo do disco para evitar vazamento
history -c
rm -f ~/.bash_history
# 2. Limpa visualmente o console para o próximo login (anti shoulder-surfing)
[ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q
clear
fi
```
**Resultado**: Sempre que um administrador humano ou agente de IA desconectar do SSH ou fechar o terminal, todos os comandos executados em memória são permanentemente apagados do disco (`.bash_history`), mantendo os segredos totalmente protegidos contra leitores indesejados.
---
## 🛡️ Pilar 6: Micro-segmentação de Rede e Firewall Restritivo (SecOps)
Para evitar a movimentação lateral caso qualquer VPS de staging (como a VPS 4) seja comprometida, a **VPS 3 (Cérebro)** possui uma política rígida de firewall (UFW) baseada no **Princípio do Menor Privilégio a Nível de Rede**.
### Configuração do Firewall da VPS 3 (`wg0`):
1. **Acesso Total para o Administrador**:
O notebook do administrador (`10.99.0.10`) possui acesso irrestrito a todas as portas sobre a VPN:
```bash
sudo ufw allow in on wg0 from 10.99.0.10 to any
```
2. **Acesso Restrito para Servidores do Swarm**:
A VPS 1 (`10.99.0.1`) e a VPS 4 (`10.99.0.4`) possuem acesso permitido **exclusivamente** às portas TCP necessárias para a operação:
* **Porta 22** (Gitea SSH / Terminal SSH)
* **Porta 3000** (Gitea HTTP Web Interface)
* **Porta 5000** (Swarm Dispatcher Webhook Listener)
* **Porta 5432** (PostgreSQL Database Port)
* **Porta 6379** (Redis/Dragonfly Key-Value Queue)
3. **default-deny Policy**:
Todas as demais conexões de qualquer outra origem da subrede VPN (ex: uma VPS de CRM vulnerável) são **bloqueadas sumariamente por padrão**, blindando o cérebro do enxame contra vazamentos e invasões.