Domínios & SSL

sh0 usa Caddy como proxy reverso, o que significa que cada domínio recebe HTTPS automático via Let's Encrypt. Sem gerenciamento manual de certificados, sem cron jobs, sem arquivos de configuração — simplesmente funciona.

Como Domínios Funcionam

Quando você atribui um domínio a um app, sh0 configura automaticamente o Caddy para:

  1. Escutar requisições de entrada nesse domínio (portas 80 e 443).
  2. Obter e instalar um certificado SSL do Let's Encrypt.
  3. Redirecionar todo o tráfego HTTP para HTTPS.
  4. Fazer proxy reverso do tráfego HTTPS para o container Docker correto.
  5. Renovar automaticamente o certificado antes de expirar.
Flow diagram showing: Internet request to domain.com goes to Caddy (ports 80/443), which terminates SSL and proxies to the Docker container on its internal port
Caddy handles SSL termination and proxying

Todo esse processo é automático. Depois que você adiciona um domínio e aponta seu DNS para seu servidor, todo o resto é automático.

Subdomínios Padrão

Todo app implantado no sh0 Cloud recebe um subdomínio gratuito em *.sh0.app. Isso é útil para:

  • Testes rápidos sem configurar DNS
  • Ambientes de staging
  • Deploys de preview para pull requests

O subdomínio é baseado no nome do seu app: se seu app se chama my-api, ele será acessível em my-api.sh0.app.

Note
Subdomínios padrão são totalmente funcionais com SSL. São ótimos para desenvolvimento e testes. Para produção, você normalmente vai querer usar seu próprio domínio personalizado.

Desativar *.sh0.app

Ao iniciar, o sh0 se registra no proxy em nuvem do sh0 (proxy.sh0.app) — seu identificador, seu endereço IP público e sua versão — para obter os endereços *.sh0.app. Para manter seu servidor fora do proxy, defina SH0_CLOUD_REGISTRATION=off no ambiente do serviço sh0 antes da primeira inicialização.

Em um servidor novo, o instalador faz isso por você:

New server
curl -fsSL https://get.sh0.dev | bash -s -- --no-cloud

Em um servidor já instalado, adicione um drop-in do systemd e reinicie o sh0:

Existing server
mkdir -p /etc/systemd/system/sh0.service.d
printf '[Service]\nEnvironment=SH0_CLOUD_REGISTRATION=off\n' \
  > /etc/systemd/system/sh0.service.d/cloud-registration.conf
systemctl daemon-reload && systemctl restart sh0

Em seguida, execute sh0 doctor: a linha de registro em nuvem deve indicar “disabled”. Os valores off, 0, false e no são aceitos.

Warning
Desativar o registro interrompe o heartbeat, mas ainda não remove do proxy um endereço obtido antes. Seus apps passam a ser acessados apenas pelos seus próprios domínios.

Adicionando um Domínio Personalizado

Para adicionar um domínio personalizado ao seu app:

  1. Navegue até seu app e abra a aba Domains.
  2. Clique em Add Domain.
  3. Insira seu nome de domínio (ex.: app.example.com ou example.com).
  4. Salve e configure seu DNS (veja abaixo).
Add Domain dialog showing a text input for the domain name, with examples of valid formats: 'example.com', 'app.example.com', 'api.example.com'
Adding a custom domain

Você pode adicionar múltiplos domínios a um único app. Todos servirão a mesma aplicação. Isso é útil para:

  • Servir tanto example.com quanto www.example.com
  • Suportar múltiplos nomes de domínio que apontam para o mesmo serviço
  • Manter o subdomínio padrão como fallback junto ao seu domínio personalizado

Configuração DNS

Aponte seu domínio para seu servidor sh0 adicionando registros DNS no seu registrador ou provedor DNS:

TipoNomeValorCaso de Uso
A@IP do seu servidorDomínio raiz (example.com)
AappIP do seu servidorSubdomínio (app.example.com)
CNAMEwwwexample.comRedirecionamento www
Example DNS Records
# For app.example.com
Type: A
Name: app
Value: 203.0.113.50
TTL: 300

# For example.com (root domain)
Type: A
Name: @
Value: 203.0.113.50
TTL: 300
Propagação DNS
Alterações DNS geralmente propagam em minutos, mas podem levar até 24 horas. Você pode verificar se seu DNS está corretamente configurado usando dig app.example.com ou nslookup app.example.com.

SSL Automático

Certificados SSL são gerenciados inteiramente pelo Caddy. Não há nada para configurar, nenhum certificado para fazer upload e nenhum script de renovação para manter.

Como o Let's Encrypt Funciona

Quando você adiciona um domínio, o seguinte acontece automaticamente:

  1. Desafio -- Caddy inicia um desafio ACME HTTP-01 para provar a propriedade do domínio.
  2. Emissão -- Let's Encrypt verifica o desafio e emite um certificado (geralmente em segundos).
  3. Instalação -- Caddy instala o certificado e começa a servir tráfego HTTPS.
  4. Renovação -- Caddy renova automaticamente o certificado 30 dias antes da expiração.
A Porta 80 Deve Estar Aberta
O desafio HTTP-01 requer que a porta 80 esteja acessível pela internet. Se a porta 80 estiver bloqueada por um firewall, o Caddy não consegue obter certificados. Certifique-se de que ufw allow 80/tcp (ou equivalente) está configurado.
Domain list showing three domains with their SSL status: 'app.example.com' with a green lock icon and 'Valid until Dec 2026', 'api.example.com' with a green lock, and 'staging.example.com' with a yellow pending icon
SSL certificate status for each domain

Domínios Wildcard

Domínios wildcard (ex.: *.example.com) permitem que qualquer subdomínio roteie para seu app. Isso é útil para:

  • Aplicações multi-tenant onde cada tenant recebe um subdomínio
  • Deploys de preview com subdomínios únicos por branch
  • Roteamento baseado em geografia ou idioma
SSL Wildcard Requer Desafio DNS
Certificados wildcard requerem um desafio DNS-01 em vez de HTTP-01. Isso significa que você precisa configurar uma chave API do provedor DNS nas configurações do sh0 para que o Caddy possa criar registros TXT para verificação. Provedores suportados incluem Cloudflare, Route53, DigitalOcean e mais.
Configure DNS Provider for Wildcards
# In sh0 Settings > SSL, configure your DNS provider
# Example for Cloudflare:
DNS_PROVIDER=cloudflare
CLOUDFLARE_API_TOKEN=your-api-token

Status do Certificado SSL

A seção Domínios de cada app mostra o status SSL para cada domínio configurado:

StatusSignificado
AtivoCertificado é válido e servindo tráfego HTTPS.
PendenteAinda sem certificado. Desde a v1.6.25 a emissão é sob demanda: o certificado é pedido no primeiro aperto de mão TLS do domínio, por isso um domínio fica Pendente até alguém se ligar de facto. Passe o cursor sobre o selo para ler porque continua pendente.
RenovandoCertificado está sendo renovado (30 dias antes da expiração).
FalhouProvisionamento do certificado falhou. Verifique as configurações de DNS e firewall.

Duas regras a mais desde a v1.6.25. Um domínio Ativo cujo certificado desaparece do disco volta a Pendente após duas verificações consecutivas, nunca por uma única leitura. E a data de expiração do certificado é agora lida do próprio certificado, para que os alertas de expiração tenham finalmente um valor com que trabalhar.

Solução de Problemas

Se seu domínio não está funcionando ou o certificado SSL falha ao provisionar, verifique estes problemas comuns:

DNS não está apontando para seu servidor

Execute dig +short your-domain.com e verifique se retorna o endereço IP do seu servidor. Se não retornar, atualize seus registros DNS e aguarde a propagação.

A porta 80 está bloqueada

Let's Encrypt precisa da porta 80 para verificar a propriedade do domínio. Certifique-se de que seu firewall permite tráfego TCP de entrada na porta 80. Verifique com sudo ufw status.

Outro serviço está usando a porta 80/443

Se Nginx, Apache ou outro servidor web estiver rodando, pode conflitar com o Caddy. Pare o outro serviço: sudo systemctl stop nginx.

Limite de taxa excedido

Let's Encrypt tem limites de taxa (50 certificados por domínio por semana). Se atingir o limite, aguarde ou use o ambiente de staging para testes. Os logs do Caddy indicarão erros de limite de taxa.

Debugging Commands
# Check if DNS resolves correctly
dig +short app.example.com

# Test if port 80 is accessible from outside
curl -I http://app.example.com

# Check Caddy logs for certificate errors
journalctl -u sh0 | grep -i "certificate\|tls\|acme"