Plugin WHM · somente root

Docker no cPanel,
sem abrir o terminal.

O cliente deixa um docker-compose.yaml na pasta dele. Você abre o WHM, confere o que o arquivo faz, publica e aponta o domínio. O dPanel cuida da validação, dos limites de recurso, do firewall e do nginx.

O problema

Docker e cPanel não se conhecem

Rodar um container num servidor cPanel normalmente significa SSH, portas escolhidas na mão, um proxy_pass editado na mão, e a esperança de que o docker-compose.yaml do cliente não contenha nada perigoso. Como tudo isso roda como root, um descuido custa o servidor inteiro.

🔍

O arquivo é do cliente

Um privileged: true ou um volume apontando para / transforma o container em root no host. O dPanel recusa antes de executar, explicando o motivo.

📉

Container ignora a LVE

No CloudLinux, containers rodam fora dos limites da conta. Sem teto, um cliente derruba o servidor de todos. O dPanel injeta limites e ainda mantém um teto global no kernel.

🚪

Rede aberta demais

Por padrão um container alcança SSH, WHM, e-mail e o metadata da instância. O dPanel deixa passar só o MySQL, e mantém a regra viva mesmo após um restart do CSF.

Como funciona

Três passos, tudo pelo WHM

Do arquivo do cliente até o domínio no ar.

O cliente entrega o compose

Ele cria /home/conta/docker/docker-compose.yaml. Só isso: nada de SSH, nada de acesso ao Docker.

# /home/conta/docker/docker-compose.yaml
services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "80"
    volumes:
      - ./site:/usr/share/nginx/html:ro

Você confere e publica

O painel mostra o arquivo do cliente lado a lado com o que o root vai realmente executar, depois da validação e da normalização. Se algo for recusado, a mensagem diz o quê e por quê. Publicando, o dPanel grava uma cópia própria: o arquivo do cliente nunca é executado direto.

Aponta o domínio

Sem limite de regras, com caminho opcional. WebSocket e IP real do visitante já vêm configurados, e o /.well-known continua local para o AutoSSL não quebrar.

loja.com.br          → web:80
loja.com.br/api      → api:3000
outrodominio.com     → web:80
Recursos

O que vem pronto

Nada para configurar depois da instalação.

Validação que recusa e explica

Lista de chaves permitidas. privileged, network_mode, cap_add, devices e montagem fora de /home/conta são recusados com a razão em português.

Limites aplicados pelo kernel

Memória, CPU, PIDs e ulimits injetados quando ausentes. Teto por stack, teto global e um dpanel.slice do systemd como rede de segurança final.

Isolamento de rede real

Só a porta 3306 do host. SSH, WHM, cPanel, Exim, redes privadas e o metadata da instância ficam inalcançáveis. Regra reaplicada em três gatilhos diferentes.

Redirecionamento com WebSocket

Handshake 101 verificado, X-Forwarded-For e X-Real-IP repassados. As regras casam pelo Host exato, então mail. e autodiscover. continuam funcionando.

Portas gerenciadas

Alocadas numa faixa reservada, sempre em 127.0.0.1, e estáveis: republicar um stack não muda a porta nem quebra os redirecionamentos.

MySQL sem configuração

Dentro do container, host.docker.internal:3306. O acesso remoto da conta é liberado automaticamente no primeiro deploy.

Build permitido, com regras

Dockerfile próprio funciona: contexto preso ao home, limite de tamanho, e recusa de # syntax=, --mount=type=ssh e --network=host.

Auditoria de tudo

Cada ação registrada em JSONL com usuário WHM, IP de origem, resultado e detalhe. Alertas de segurança também vão para o syslog.

Instalador idempotente

Um comando instala Docker, configura o daemon, o firewall e registra o plugin. Rodar de novo atualiza o código sem tocar nos dados.

Isolamento

O que o container alcança

Verificado em servidor de produção, e revalidado depois de um csf -r, que limpa todas as regras do iptables.

Origem → destinoResultadoPor quê
container → MySQL 3306 do hostpermitido única porta liberada, e apenas no IP do gateway
container → SSH, WHM, cPanel, Exim, Apachebloqueado regra própria no topo da cadeia INPUT
container → metadata da instânciabloqueado evita roubo de credencial de nuvem
container → redes privadas (10/8, 172.16/12, 192.168/16)bloqueado impede varredura da rede interna
container → internetpermitido instalar pacotes e consumir API continua funcionando
container → container da mesma contapermitido rede isolada por conta
internet → porta do containerbloqueado publicação só em 127.0.0.1; quem expõe é o nginx
outra conta do servidor → porta do containerbloqueado na loopback, a porta só aceita o nginx, o root e a conta dona do stack

Instalação em um comando

cPanel/WHM em CloudLinux, AlmaLinux, Rocky, CentOS ou RHEL 8/9.

git clone <repositorio> dpanel
cd dpanel
bash install.sh