From 131d4060fbcd77c44fdb3627e12f2078594cc7f2 Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Thu, 14 May 2026 22:34:03 +0200 Subject: [PATCH] docs(seguranca): documentar incidente daemon Docker root + fix aplicado na VPS 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- clube67/arquitetura.md | 20 ++++++++++++ scoreodonto/deploy.md | 41 ++++++++++++++++++++++++ seguranca_deploy_user.md | 69 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/clube67/arquitetura.md b/clube67/arquitetura.md index e9298d5..a36389f 100644 --- a/clube67/arquitetura.md +++ b/clube67/arquitetura.md @@ -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 diff --git a/scoreodonto/deploy.md b/scoreodonto/deploy.md index a8c4352..3c173e3 100644 --- a/scoreodonto/deploy.md +++ b/scoreodonto/deploy.md @@ -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 +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 +``` --- diff --git a/seguranca_deploy_user.md b/seguranca_deploy_user.md index d76a841..b9ec4e5 100644 --- a/seguranca_deploy_user.md +++ b/seguranca_deploy_user.md @@ -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 +``` ---