Deploy com Docker
O mxout é distribuído como uma imagem scratch com binário estático musl (~6 MB). A configuração e as chaves são montadas em runtime — nenhum segredo é embutido na imagem.
Pré-requisitos
- Porta 25 de saída liberada no servidor (verifique com seu provedor).
- Registro PTR (rDNS) configurado no IP do servidor apontando para o hostname de envio.
- Kit DKIM gerado com
mxout-keygen. Ver Configuração.
O que montar
Tudo que o mxout precisa fica em /etc/mxout/:
| Caminho no container | Conteúdo |
|---|---|
/etc/mxout/mxout.json |
Arquivo de configuração principal. |
/etc/mxout/kits/<dominio>.<selector>.key.pem |
Chave privada DKIM de cada domínio. |
Monte esse diretório como read-only. O mxout não escreve nada em disco.
Variáveis de ambiente
| Variável | Obrigatória | Descrição |
|---|---|---|
MXOUT_AUTH_TOKEN |
Sim | Token de autenticação das requisições HTTP. Trate como secret. |
MXOUT_CONFIG |
Não | Caminho do mxout.json. Padrão: /etc/mxout/mxout.json. |
MXOUT_DNS |
Sim (scratch) | Resolver DNS explícito (ex.: 1.1.1.1). Obrigatório porque a imagem scratch não tem /etc/resolv.conf. |
RUST_LOG |
Não | Verbosidade dos logs. Padrão: info. |
Rodar com docker run
docker run -d \
--name mxout \
--restart unless-stopped \
-p 8080:8080 \
-v /etc/mxout:/etc/mxout:ro \
-e MXOUT_AUTH_TOKEN=<TOKEN_SECRETO> \
-e MXOUT_DNS=1.1.1.1 \
-e RUST_LOG=info \
ghcr.io/ccs-systems/mxout:latestVerifique se o serviço está saudável:
curl http://localhost:8080/healthResposta esperada: ok
Rodar com docker compose
services:
mxout:
image: ghcr.io/ccs-systems/mxout:latest
container_name: mxout
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /etc/mxout:/etc/mxout:ro
environment:
MXOUT_AUTH_TOKEN: "${MXOUT_AUTH_TOKEN}"
MXOUT_DNS: "1.1.1.1"
RUST_LOG: "info"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
labels:
- "ccs.systems/project=mxout"
- "ccs.systems/type=sys"
- "ccs.systems/env=prod"
- "traefik.enable=true"
- "traefik.http.routers.mxout.rule=Host(`mxout.exemplo.com`)"
- "traefik.http.routers.mxout.entrypoints=websecure"
- "traefik.http.routers.mxout.tls.certresolver=myresolver"
- "traefik.http.services.mxout.loadbalancer.server.port=8080"
networks:
- public
networks:
public:
external: trueArmazene MXOUT_AUTH_TOKEN no .env (nunca no docker-compose.yml):
MXOUT_AUTH_TOKEN=<TOKEN_SECRETO>Dev vs produção
| Aspecto | Dev (local) | Prod (Runner/CI-CD) |
|---|---|---|
| Acesso | http://localhost:8080 |
HTTPS via Traefik (https://mxout.exemplo.com) |
| Deploy | docker compose up -d manual |
Push na branch dist aciona o Runner |
| Config | Montada do host | Montada via volume declarado no .deploy.yml |
| Token | Valor local de teste | Secret gerenciado pelo Runner (--ckey) |
| Traefik | Opcional | Obrigatório (termina TLS, roteia domínio) |
Em produção, o mxout nunca é exposto diretamente na internet. O Traefik recebe o tráfego HTTPS e encaminha para a porta 8080 interna.
O deploy em produção passa pelo CI/CD Runner (branch dist + .deploy.yml). Não use docker compose up direto no servidor de produção.
Verificar entrega
Após subir o serviço, envie um e-mail de teste e acompanhe os eventos do ledger:
docker logs -f mxout | grep 'mxout::ledger'Ver também: Ledger — mecanismo de controle.
Referências
- Configuração — campos do
mxout.jsone montagem dos kits. - Configurar DNS — registros DKIM, SPF e DMARC.