Como configurar HTTPS local com Caddy em projetos de desenvolvimento
1. Por que usar HTTPS local no desenvolvimento?
Desenvolver com HTTPS local não é apenas um luxo — é uma necessidade técnica. Ambientes de produção modernos exigem conexões seguras, e replicar isso localmente evita surpresas desagradáveis. A diferença entre HTTP e HTTPS no ambiente local vai além do cadeado verde no navegador: cookies com flag Secure, Service Workers, geolocalização e notificações push simplesmente não funcionam em HTTP.
Além disso, simular produção com HTTPS previne problemas de mixed content — quando uma página carregada por HTTPS tenta carregar recursos HTTP — e evita dores de cabeça com CORS em APIs que exigem origens seguras. Sem HTTPS local, você descobre esses problemas apenas no deploy, o que custa tempo e retrabalho.
2. Conhecendo o Caddy como servidor de desenvolvimento
Caddy é um servidor web moderno escrito em Go que se destaca por uma característica única: HTTPS automático. Diferente de nginx ou Apache, que exigem configuração manual de certificados TLS, o Caddy obtém, renova e gerencia certificados automaticamente via ACME (Let's Encrypt). Para desenvolvimento local, ele oferece certificados autoassinados confiáveis sem precisar de ferramentas auxiliares como mkcert.
Vantagens do Caddy:
- Configuração declarativa e legível via Caddyfile
- HTTPS automático sem scripts externos
- Proxy reverso nativo com balanceamento de carga
- Suporte a HTTP/2 e HTTP/3
- Baixo consumo de recursos
Instalação:
# Linux (Ubuntu/Debian)
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy
# macOS
brew install caddy
# Windows (via chocolatey)
choco install caddy
3. Configuração básica do Caddyfile para HTTPS local
O Caddyfile é o coração da configuração. Sua estrutura é simples: domínio seguido de diretivas entre chaves.
Exemplo mínimo — proxy reverso para app Node.js na porta 3000:
app.localhost {
reverse_proxy localhost:3000
}
Salve como Caddyfile e execute:
caddy run
O Caddy automaticamente criará um certificado autoassinado para app.localhost. Acesse https://app.localhost no navegador — você verá um aviso de certificado não confiável, que pode ser ignorado em desenvolvimento.
Para domínios reais (ex.: meuapp.test), o Caddy tentará obter certificados Let's Encrypt. Para desenvolvimento offline, use tls internal.
4. Gerenciamento de certificados TLS com Caddy
O Caddy gerencia certificados de forma transparente. Quando você define um domínio público (ex.: exemplo.com), ele automaticamente solicita certificados Let's Encrypt via ACME. Para ambientes offline ou testes, use a diretiva tls internal:
app.localhost {
tls internal
reverse_proxy localhost:3000
}
Isso gera certificados autoassinados que o Caddy armazena em seu diretório de configuração (~/.local/share/caddy ou equivalente no Windows). Para confiar nesses certificados no navegador, você pode importar a CA raiz do Caddy:
# Linux
sudo cp ~/.local/share/caddy/pki/authorities/local/root.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/Library/Application\ Support/Caddy/pki/authorities/local/root.crt
5. Configurações avançadas para projetos reais
Proxy reverso para múltiplos serviços:
api.localhost {
tls internal
reverse_proxy localhost:4000
}
app.localhost {
tls internal
reverse_proxy localhost:3000
}
static.localhost {
tls internal
root * /var/www/meuapp/static
file_server
}
Headers de segurança essenciais:
app.localhost {
tls internal
reverse_proxy localhost:3000
header / {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Content-Security-Policy "default-src 'self'"
}
}
Logs e debugging:
app.localhost {
tls internal
reverse_proxy localhost:3000
log {
output file /var/log/caddy/access.log
format json
}
errors {
log file /var/log/caddy/errors.log
}
}
6. Integração com Docker e ambientes conteinerizados
Rodar Caddy em Docker é ideal para ambientes de desenvolvimento replicáveis.
Dockerfile para Caddy:
FROM caddy:alpine
COPY Caddyfile /etc/caddy/Caddyfile
COPY site /usr/share/caddy
docker-compose.yml completo:
version: '3.8'
services:
caddy:
image: caddy:alpine
container_name: caddy-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- dev-network
node-app:
build: ./node-app
container_name: node-backend
expose:
- "3000"
networks:
- dev-network
react-app:
build: ./react-app
container_name: react-frontend
expose:
- "5173"
networks:
- dev-network
volumes:
caddy_data:
caddy_config:
networks:
dev-network:
driver: bridge
Caddyfile para Docker:
app.localhost {
tls internal
reverse_proxy node-app:3000
}
admin.localhost {
tls internal
reverse_proxy react-app:5173
}
7. Resolução de problemas comuns
Certificados não confiáveis no navegador:
- Verifique se a CA raiz do Caddy foi importada corretamente
- Em navegadores Chrome/Edge, digite thisisunsafe na tela de aviso para acesso temporário
- Firefox permite adicionar exceção permanente
Conflitos de porta:
- Verifique se nenhum outro serviço está usando as portas 80/443
- Use sudo lsof -i :80 (Linux/macOS) para identificar processos
- Configure portas alternativas: app.localhost:8080 { ... }
Erros de proxy reverso:
- Confirme se o serviço de destino está rodando e acessível
- Verifique nomes de containers no Docker: use o nome do serviço, não localhost
- Aumente timeouts: reverse_proxy localhost:3000 { transport http { read_timeout 30s } }
8. Boas práticas e próximos passos
Automatize a inicialização:
- Adicione um script start-dev.sh que executa caddy run junto com outros serviços
- Use caddy start para rodar em background e caddy stop para encerrar
Versionamento do Caddyfile:
- Mantenha o Caddyfile no repositório do projeto
- Use variáveis de ambiente para configurações sensíveis: {$DOMAIN} no Caddyfile
Comparação com alternativas:
- Traefik: mais complexo, mas excelente para orquestração com Docker Swarm/Kubernetes
- ngrok: ideal para expor servidor local temporariamente, mas não substitui HTTPS local persistente
- mkcert: útil para certificados locais, mas exige configuração manual em cada projeto
Caddy oferece o melhor equilíbrio entre simplicidade e potência para desenvolvimento local com HTTPS. Comece com configurações básicas e evolua conforme seu projeto cresce.
Referências
- Documentação oficial do Caddy — Guia completo de instalação, configuração e todas as diretivas do Caddyfile
- Caddy Academy - Getting Started — Tutorial interativo passo a passo para iniciantes em Caddy
- Configurando HTTPS local com Caddy e Docker — Tutorial prático da DigitalOcean sobre proxy reverso com Caddy em containers
- Caddy com certificados internos para desenvolvimento — Seção da documentação oficial sobre HTTPS local e certificados autoassinados
- Comparação entre Caddy, nginx e Traefik para desenvolvimento — Artigo no Dev.to analisando as diferenças entre as principais ferramentas de proxy
- Segurança em desenvolvimento com HTTPS local — Guia do Web.dev sobre mixed content e por que HTTPS local é importante