# 🛡️ 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.