docs(seguranca): documentar incidente daemon Docker root + fix aplicado na VPS 1
- seguranca_deploy_user.md: corrige Pilar 2 — adiciona aviso crítico sobre grupo docker em instalações rootless, documenta estado correto da VPS 1 e registra incidente de 2026-05-14 com causa raiz e comandos de correção - scoreodonto/deploy.md: adiciona seção de alerta Docker Duplo com sintoma porta 8020 bloqueada por docker-proxy zumbi e diagnóstico/solução - clube67/arquitetura.md: adiciona regra crítica de Docker Rootless na VPS 1 com tabela de restrições e verificação de saúde pós-manutenção Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -248,6 +248,26 @@ Para garantir que a invasão de um container não resulte no comprometimento do
|
||||
* **CAP Drop**: Remove capacidades de sistema desnecessárias ao container (ex: `NET_ADMIN`, `SYS_ADMIN`, `SYS_CHROOT`).
|
||||
* **Rootless Containers**: Sempre que suportado pela aplicação, os containers devem rodar com IDs de usuário não privilegiados (non-root).
|
||||
|
||||
### ⚠️ Regra Crítica — Docker Rootless na VPS 1
|
||||
|
||||
A VPS 1 roda **Docker Rootless** (daemon como usuário `deploy`, socket em `/run/user/1000/docker.sock`). O daemon root (`docker.service`) está **desabilitado permanentemente**.
|
||||
|
||||
| Regra | Motivo |
|
||||
|-------|--------|
|
||||
| `docker.service` deve permanecer `disabled` | Daemon root + `deploy` no grupo `docker` = escalonamento de privilégios trivial |
|
||||
| `deploy` NÃO deve estar no grupo `docker` | Grupo `docker` dá acesso ao socket root; basta omitir `DOCKER_HOST` para criar containers root |
|
||||
| Todo script que roda na VPS 1 deve usar `DOCKER_HOST` explícito | SSH não herda variáveis de ambiente do shell do usuário por padrão |
|
||||
|
||||
```bash
|
||||
# Verificação de saúde — executar após qualquer manutenção na VPS 1
|
||||
sudo systemctl status docker # deve estar: inactive (dead)
|
||||
groups deploy # não deve conter "docker"
|
||||
DOCKER_HOST=unix:///run/user/1000/docker.sock docker ps # deve listar os containers ativos
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Se o `docker.service` for reativado acidentalmente (ex: `apt upgrade` do pacote docker.io), ele voltará como enabled. Verificar após atualizações de sistema.
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Fluxo de Auto-Cura (Self-Healing) com Grafana/Gitea
|
||||
|
||||
@@ -183,6 +183,47 @@ ssh deploy@10.99.0.1 "docker logs scoreodontocom-scoreodonto-backend-1 --tail 30
|
||||
| `rsync` falha | `ssh deploy@10.99.0.1 echo ok` | Checar chave SSH e VPN WireGuard |
|
||||
| Docker build falha | `docker logs` na VPS 1 | Ver logs do container; checar `npm install` |
|
||||
| Frontend em branco | nginx config / dist vazia | Verificar se `vite build` completou sem erro |
|
||||
| nginx não sobe, porta 8020 ocupada | `sudo ss -tlnp \| grep 8020` | Ver seção abaixo — docker-proxy zumbi |
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Alerta de Segurança — Docker Duplo (Rootless + Root)
|
||||
|
||||
> [!CAUTION]
|
||||
> A VPS 1 usa **Docker Rootless**. O daemon root (`docker.service`) está **desabilitado intencionalmente**. Nunca o reative.
|
||||
|
||||
### Por que o daemon root é perigoso aqui
|
||||
|
||||
O usuário `deploy` tem acesso `sudo`. Se o `docker.service` (root) estiver ativo e `deploy` estiver no grupo `docker`, qualquer `docker compose up` sem `DOCKER_HOST` cria containers como root — paralelos aos rootless, invisíveis ao `docker ps` normal, e inacessíveis ao Traefik (que monitora a rede rootless).
|
||||
|
||||
### Sintoma: porta 8020 ocupada após `docker rm -f`
|
||||
|
||||
Quando um container nginx é `force-remove`d enquanto o daemon root está ativo, o processo `docker-proxy` root pode ficar preso na porta:
|
||||
|
||||
```bash
|
||||
# Diagnóstico
|
||||
sudo ss -tlnp | grep 8020
|
||||
# Se aparecer docker-proxy com PID root → daemon root estava ativo
|
||||
|
||||
# Solução de emergência
|
||||
sudo kill <PID do docker-proxy>
|
||||
cd ~/stack/scoreodonto.com
|
||||
DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock docker compose rm -sf nginx
|
||||
DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock docker compose up -d nginx
|
||||
```
|
||||
|
||||
### Estado correto da VPS 1
|
||||
|
||||
```bash
|
||||
# Verificar que o daemon root está morto
|
||||
sudo systemctl status docker # deve mostrar: inactive (dead)
|
||||
|
||||
# Verificar que deploy não está no grupo docker
|
||||
groups deploy # não deve conter "docker"
|
||||
|
||||
# Verificar que rootless está respondendo
|
||||
DOCKER_HOST=unix:///run/user/1000/docker.sock docker ps | grep scoreodonto
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -32,16 +32,77 @@ find /var/www/meu-app -type f -exec chmod 644 {} \;
|
||||
---
|
||||
|
||||
## 🐋 Pilar 2: Gerenciamento do Docker sem Root
|
||||
Se as suas aplicações rodam em Docker (ou Docker Compose), o usuário `deploy` não precisa usar `sudo docker` para gerenciar os containers.
|
||||
|
||||
### Prática:
|
||||
Adicionamos o usuário `deploy` ao grupo do Docker no Linux:
|
||||
> [!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**: Após fazer logout e login novamente, o usuário `deploy` poderá rodar comandos como `docker ps`, `docker compose up -d`, `docker restart` e fazer builds de imagens diretamente, com total liberdade, sem nunca usar `sudo`.
|
||||
**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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user