Seu cliente digita app.seucliente.com no navegador e espera. Por trás desses três segundos de carregamento, sua infraestrutura está orquestrando uma consulta DNS, validando um certificado curinga, roteando através de seu proxy reverso e servindo seu dashboard com marca própria — tudo sem eles saberem seu IP de servidor real. Implementei esse padrão de domínio personalizado quatro vezes em diferentes stacks, e cada implementação revelou armadilhas que nunca apareceram na especificação do produto: limites de taxa do Let's Encrypt que bloqueiam sua décima onboarding de cliente, comportamento de CNAME flattening que quebra em provedores DNS específicos, atrasos de propagação que geram tickets de suporte durante a semana de lançamento. Você arquitetará isso uma vez pensando que é um projeto de dois sprints — antes de descobrir os edge cases que transformam automação SSL em um fim de semana de debug de API Cloudflare e validação de cadeia de certificados.

Este artigo é o playbook que gostaria de ter tido. Vamos cobrir subdomínios curinga para aplicativos multi-tenant, provisionamento automatizado de SSL com Let's Encrypt e alternativas, domínios de vaidade personalizados onde clientes trazem seus próprios, e as preocupações operacionais que vão morder você às 2 da manhã se não planejar para elas.

Sumário

Domínios Personalizados para SaaS: Subdomínios Curinga e SSL Automático

Por que Domínios Personalizados Importam para SaaS

Domínios personalizados não são apenas um recurso de vaidade. Eles são um sinal de confiança. Quando o cliente do seu cliente visita portal.acmecorp.com em vez de acmecorp.seu-saas.io, isso reforça a marca do cliente. Remove fricção. E para muitos acordos corporativos, é um requisito obrigatório — a equipe de procurement não aprovará software que force funcionários para um domínio de terceiros.

Há também um ângulo de SEO. Se você está construindo um SaaS que envolve páginas públicas (pense em lojas Shopify, construtores de landing pages, bases de conhecimento ou portais de clientes), clientes precisam de seus próprios domínios para construir autoridade de domínio. Você não consegue fazer isso em um subdomínio de plataforma de alguém. Bem, você consegue, mas não é ideal.

Os três padrões mais comuns que vejo:

  1. Subdomínios de plataformacliente.seu-app.com (mais fácil)
  2. Subdomínios personalizadosapp.cliente.com (complexidade média)
  3. Domínios personalizados de apexcliente.com (mais difícil, porque registros CNAME não funcionam no apex)

A maioria dos produtos SaaS maduros acaba suportando os três.

Visão Geral da Arquitetura: Três Abordagens

Antes de entrar em detalhes de implementação, vejamos as três principais abordagens arquitetônicas e quando cada uma faz sentido.

Abordagem Complexidade Melhor Para Método SSL Requisito DNS
Subdomínio curinga Baixa Subdomínios controlados pela plataforma Certificado curinga único Registro DNS curinga A/AAAA
Proxy reverso com SNI Média Domínios personalizados em escala moderada Certificado por domínio via ACME CNAME ou registro A do cliente
CDN/Edge com domínios personalizados Baixa-Média Escala alta, distribuição global Gerenciado pelo provedor CDN CNAME ou registro A do cliente
Load balancer dedicado por tenant Alta Requisitos de isolamento corporativo Certificado por tenant Delegação DNS do cliente

Para a maioria dos aplicativos SaaS, você começará com subdomínios curinga e eventualmente adicionará suporte de domínio personalizado baseado em proxy reverso. Vamos detalhar cada um.

Subdomínios Curinga para Multi-Tenancy

Este é seu ponto de partida. Cada tenant obtém {slug}.seuapp.com. Aqui está como configurar adequadamente.

Configuração DNS

Você precisa de um registro DNS curinga:

*.seuapp.com.  300  IN  A      203.0.113.10
*.seuapp.com.  300  IN  AAAA   2001:db8::1

Isso significa que qualquer subdomínio de seuapp.com resolve para seu servidor. Seu aplicativo então lê o header Host para determinar qual tenant servir.

Roteamento em Nível de Aplicação

Em um aplicativo Next.js (que construímos muito na Social Animal), você trataria isso em middleware:

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const hostname = request.headers.get('host') || '';
  const subdomain = hostname.split('.')[0];
  
  // Pule para domínio principal e subdomínios conhecidos
  if (['www', 'app', 'api'].includes(subdomain)) {
    return NextResponse.next();
  }
  
  // Reescreva para caminho específico de tenant
  const url = request.nextUrl.clone();
  url.pathname = `/tenant/${subdomain}${url.pathname}`;
  return NextResponse.rewrite(url);
}

export const config = {
  matcher: ['/((?!_next|api|static).*)']
};

Para sites baseados em Astro (outro framework que usamos muito), você trataria isso em seu middleware de servidor ou na edge.

Certificado SSL Curinga

Um certificado curinga único cobre todos os subdomínios:

certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d 'seuapp.com' \
  -d '*.seuapp.com'

Nota: certificados curinga do Let's Encrypt requerem validação de desafio DNS-01. Você não consegue usar HTTP-01 para curingas. Isso significa que você precisa de acesso à API do seu provedor DNS. Certbot tem plugins para Cloudflare, Route53, Google Cloud DNS e a maioria dos provedores principais.

Certificados curinga do Let's Encrypt são válidos por 90 dias, então automatize essa renovação. Sério. Configure um alerta de monitoramento se a renovação falhar — não seja a pessoa que derruba sites de 500 clientes porque um certificado expirou.

Domínios Personalizados para SaaS: Subdomínios Curinga e SSL Automático - arquitetura

SSL Automatizado com Let's Encrypt

Quando clientes trazem seus próprios domínios, você precisa de certificados por domínio. É aqui que as coisas ficam interessantes.

O Protocolo ACME

Let's Encrypt usa o protocolo ACME (Automatic Certificate Management Environment). Os dois desafios com os quais você se importará:

  • HTTP-01: Você prova a propriedade do domínio servindo um arquivo específico em http://seudominio.com/.well-known/acme-challenge/{token}. Mais fácil de automatizar, funciona para domínios individuais.
  • DNS-01: Você prova a propriedade criando um registro TXT específico. Necessário para curingas, mais difícil de automatizar para domínios de clientes (você não controla seu DNS).

Para domínios personalizados, você quase sempre usará HTTP-01. O fluxo é assim:

  1. Cliente adiciona um CNAME apontando seu domínio para sua plataforma
  2. Seu sistema detecta que o DNS está resolvendo corretamente
  3. Você inicia uma solicitação de certificado ACME
  4. Let's Encrypt envia um desafio HTTP-01
  5. Seu servidor responde com o token de desafio correto
  6. Certificado é emitido e armazenado
  7. Seu proxy reverso começa a servir HTTPS para esse domínio

Caddy: A Opção Preguiçosa (Inteligente)

Honestamente, se você não estiver já comprometido com nginx, apenas use Caddy. Ele trata HTTPS automático pronto para uso, incluindo TLS sob demanda para domínios desconhecidos:

{
  on_demand_tls {
    ask http://localhost:5555/check-domain
    interval 2m
    burst 5
  }
}

https:// {
  tls {
    on_demand
  }
  reverse_proxy localhost:3000
}

O endpoint ask é crítico — é onde Caddy verifica com seu aplicativo se um domínio é realmente um domínio de cliente válido antes de solicitar um certificado. Sem isso, qualquer pessoa poderia apontar seu domínio para seu IP e desencadear solicitações de certificado, potencialmente queimando os limites de taxa do Let's Encrypt.

// endpoint /check-domain
app.get('/check-domain', async (req, res) => {
  const domain = req.query.domain;
  const isValid = await db.customDomains.findOne({ 
    domain, 
    verified: true,
    active: true 
  });
  
  if (isValid) {
    res.status(200).send('OK');
  } else {
    res.status(404).send('Not found');
  }
});

Abordagem Nginx + Certbot

Se você já está executando nginx, você pode usar certbot com o plugin webroot:

certbot certonly --webroot -w /var/www/certbot \
  -d dominio-cliente.com \
  --non-interactive --agree-tos \
  --email ssl@seuapp.com

Você precisará atualizar dinamicamente configs nginx e recarregar:

server {
    listen 443 ssl;
    server_name dominio-cliente.com;
    
    ssl_certificate /etc/letsencrypt/live/dominio-cliente.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dominio-cliente.com/privkey.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Isso funciona mas é doloroso gerenciar em escala. Cada novo domínio significa gerar uma config, solicitar um certificado e recarregar nginx. Você vai querer construir automação ao redor disso, e honestamente TLS sob demanda de Caddy é apenas mais fácil.

Limites do Let's Encrypt (2025)

Eles importam e você precisa planejar em torno deles:

Limite Valor Notas
Certificados por Domínio Registrado 50/semana Por seu domínio raiz
Certificado Duplicado 5/semana Mesmo conjunto exato de hostnames
Validações Falhadas 5/hora por conta por hostname Pode bloquear você rápido
Novos Pedidos 300/3 horas Conta inteira
Autorizações Pendentes 300/conta Limpe as antigas

Em 50 certs por semana, se você está onboarding mais de ~7 domínios personalizados por dia, você precisa pensar sobre isso. Opções:

  • Use uma CA ACME diferente (ZeroSSL, BuyPass) como fallback
  • Solicite um aumento de limite de taxa do Let's Encrypt (eles concedem esses para casos de uso SaaS legítimos)
  • Pré-valide DNS antes de tentar emissão de certificado
  • Implemente lógica de retry com backoff exponencial

Domínios de Vaidade Personalizados: O Fluxo Completo

Aqui está a jornada do usuário completa que recomendo, tendo construído esse fluxo várias vezes.

Passo 1: Cliente Entra Domínio em Seu Dashboard

Forneça instruções claras. Mostre a eles exatamente qual registro DNS criar:

Tipo: CNAME
Host: portal (ou qualquer subdomínio que queiram)
Valor: custom.seuapp.com
TTL: 300

Para domínios de apex (bare cliente.com), eles precisam de um registro A apontando para seu IP, ou precisam de um provedor DNS que suporte CNAME flattening (Cloudflare, registros ALIAS Route53, etc.).

Passo 2: Verificação DNS

Não verifique apenas uma vez. A propagação DNS pode levar minutos a horas. Implemente um mecanismo de polling:

async function verifyDomain(domain: string, expectedTarget: string): Promise<boolean> {
  try {
    const records = await dns.promises.resolveCname(domain);
    return records.some(r => r === expectedTarget);
  } catch (err) {
    // Para registros A (domínios de apex)
    try {
      const aRecords = await dns.promises.resolve4(domain);
      return aRecords.some(r => EXPECTED_IPS.includes(r));
    } catch {
      return false;
    }
  }
}

// Poll a cada 30 segundos por até 24 horas
async function waitForDNS(domain: string) {
  const maxAttempts = 2880; // 24 horas em intervalos de 30s
  for (let i = 0; i < maxAttempts; i++) {
    if (await verifyDomain(domain, 'custom.seuapp.com')) {
      return true;
    }
    await sleep(30000);
  }
  return false;
}

Passo 3: Provisionamento de Certificado

Uma vez que DNS é verificado, solicite o certificado. Com Caddy, isso acontece automaticamente na primeira solicitação. Com nginx/certbot, desencadeie programaticamente.

Passo 4: Monitoramento Contínuo

Domínios podem quebrar. Clientes mudam registros DNS acidentalmente. Certificados expiram se a renovação falhar. Você precisa monitorar:

  • Resolução DNS ainda aponta para você (verifique diariamente)
  • Datas de expiração de certificado (alerte em 14 dias, crítico em 7)
  • Sucesso do handshake SSL (monitoramento sintético)
  • Códigos de resposta HTTP em domínios de clientes

Padrões de Infraestrutura por Plataforma

A abordagem varia significativamente dependendo de onde você está hospedando.

Vercel

Vercel tem suporte de domínio personalizado integrado. Para um aplicativo Next.js multi-tenant, você usaria sua API de Domínios:

curl -X POST "https://api.vercel.com/v10/projects/{projectId}/domains" \
  -H "Authorization: Bearer $VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "portal.cliente.com"}'

Vercel trata SSL automaticamente. A principal limitação: você está sujeito ao seu pricing. No plano Pro ($20/membro de time/mês), você obtém 50 domínios por projeto. Enterprise oferece mais. Se você tiver milhares de clientes com domínios personalizados, o custo se acumula.

Cloudflare for SaaS (SSL for SaaS)

Esta é provavelmente a melhor opção para escala em 2025. O produto Cloudflare for SaaS (anteriormente chamado Custom Hostnames) trata tudo:

  • Emissão automática de certificado e renovação
  • CDN global e proteção DDoS
  • Verificação de domínio integrada
  • API para gerenciamento programático
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_hostnames" \
  -H "Authorization: Bearer $CF_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "portal.cliente.com",
    "ssl": {
      "method": "http",
      "type": "dv"
    }
  }'

Pricing: $0.10/hostname customizado/mês depois dos primeiros 100 (que são gratuitos no plano Enterprise). Para um SaaS com 1.000 domínios personalizados, isso é cerca de $90/mês. Muito razoável.

AWS (ALB + ACM + Route53)

Se você está na AWS, pode usar:

  • ALB para roteamento com seleção de certificado baseada em SNI
  • ACM (AWS Certificate Manager) para certificados gratuitos
  • Route53 para verificação DNS

O catch: certificados ACM são apenas usáveis com serviços AWS (ALB, CloudFront, API Gateway). E ALB tem um limite de 25 certificados por load balancer por padrão (pode ser aumentado para 100). Para escala séria, você colocaria CloudFront na frente com seu limite de 100 certificados por distribuição.

Isso fica caro e complexo. Honestamente recomendaria Cloudflare for SaaS sobre essa abordagem a menos que você tenha requisitos específicos de AWS.

Fly.io

Fly.io tem um comando fly certs add agradável e API para adicionar domínios personalizados:

fly certs add portal.cliente.com

Trata Let's Encrypt automaticamente. Funciona bem para escala pequena a média.

Configuração DNS e Verificação

A parte DNS deixa mais times confusos do que qualquer outra parte desse recurso. Aqui está o que você precisa saber.

O Problema CNAME-em-Apex

Clientes inevitavelmente quererão usar seu domínio bare (cliente.com, sem subdomínio). A especificação DNS não permite registros CNAME no apex de uma zona porque registros CNAME devem ser exclusivos — eles não conseguem coexistir com outros tipos de registro, e o apex sempre tem registros SOA e NS.

Soluções:

  1. CNAME flattening (Cloudflare) — resolve o CNAME no nível DNS, retorna um registro A
  2. ALIAS records (Route53, DNSimple) — tipo de registro proprietário que funciona como CNAME no apex
  3. ANAME records (alguns provedores) — similar a ALIAS
  4. Registro A — apenas forneça aos clientes seu endereço IP

Opção 4 (registros A) é a mais universal mas a menos flexível. Se você ever mudar o IP do seu servidor, cada cliente usando um registro A precisa atualizar seu DNS. Com um CNAME, você apenas atualiza o que seu alvo CNAME resolve.

Minha recomendação: suporte ambos. Diga aos clientes para usar CNAME para subdomínios e um registro A (ou ALIAS/ANAME se seu provedor suportar) para domínios de apex.

Verificação de Propriedade

Além de confirmar que o domínio resolve para sua infraestrutura, você pode querer verificar que a pessoa configurando o domínio em seu SaaS realmente o controla. Uma abordagem comum é exigir um registro TXT:

_verification.cliente.com  TXT  "seuapp-verify=abc123unique"

Isso previne que alguém aponte um domínio que não possui para sua plataforma e o reivindique como pertencente à sua conta.

Endurecimento em Produção e Monitoramento

Esta seção é a diferença entre uma demo e um sistema em produção.

Armazenamento de Certificado

Não armazene certificados em disco se você estiver executando múltiplas instâncias. Use um store distribuído:

  • Caddy: suporta backends de armazenamento para Redis, Consul, S3, PostgreSQL
  • Custom: armazene certs em um banco de dados criptografado ou gerenciador de segredos (AWS Secrets Manager, HashiCorp Vault)

Fallback Gracioso

O que acontece quando o domínio de um cliente está mal configurado? Não mostre um erro SSL. Em vez disso:

  1. Detecte o handshake SSL falhado
  2. Redirecione para uma página de status explicando o problema
  3. Envie uma notificação para o cliente
  4. Retentar provisionamento de certificado automaticamente

Health Checks

Construa um job de background que regularmente verifique cada domínio personalizado:

async function healthCheckDomains() {
  const domains = await db.customDomains.find({ active: true });
  
  for (const domain of domains) {
    const checks = {
      dnsResolves: await checkDNS(domain.hostname),
      sslValid: await checkSSL(domain.hostname),
      httpOk: await checkHTTP(domain.hostname),
    };
    
    if (!checks.dnsResolves) {
      await alertCustomer(domain, 'DNS não aponta mais para nossa plataforma');
      await markDomain(domain, 'dns_error');
    } else if (!checks.sslValid) {
      await triggerCertRenewal(domain);
    }
    
    await db.domainHealthChecks.insert({
      domainId: domain.id,
      ...checks,
      checkedAt: new Date(),
    });
  }
}

Execute isso a cada hora. Em 10.000 domínios, as verificações completam em alguns minutos se você paralelizar adequadamente.

Análise de Custo em Escala

Vamos falar números reais para pricing 2025.

Solução 100 Domínios 1.000 Domínios 10.000 Domínios Notas
Caddy + Let's Encrypt (auto-gerenciado) ~$50/mês servidor ~$200/mês servidores ~$1.000/mês servidores Seu fardo de ops
Cloudflare for SaaS Gratuito (Enterprise) ~$90/mês ~$990/mês Melhor valor em escala
Vercel (Pro) Incluído $0 extra Precisa Enterprise Limitado a 50/projeto em Pro
AWS CloudFront + ACM ~$100/mês ~$300/mês ~$2.000/mês Inclui custos de transferência CDN
Fastly ~$150/mês ~$500/mês Pricing customizado Bom se já usa Fastly

Para a maioria dos produtos SaaS, Cloudflare for SaaS acerta o ponto doce. Você obtém CDN global, proteção DDoS e certificados automatizados por cerca de um dime por domínio por mês. Difícil vencer isso.

Se você está construindo em uma arquitetura de CMS headless — algo que fazemos muito — Cloudflare for SaaS combina particularmente bem já que você está já lidando com frontends desacoplados que se beneficiam do caching de edge.

FAQ

Quanto tempo leva para um domínio personalizado se tornar ativo após configuração DNS?

A propagação DNS normalmente leva 5-30 minutos, embora em casos raros possa levar até 48 horas. Provisionamento de certificado com Let's Encrypt adiciona mais 30-60 segundos uma vez que DNS está resolvendo corretamente. Na prática, a maioria dos domínios personalizados está totalmente ativa dentro de 15 minutos. Recomendo fazer polling de DNS a cada 30 segundos e desencadear provisionamento de certificado imediatamente quando a resolução for bem-sucedida.

Consigo usar Let's Encrypt para milhares de domínios personalizados em meu SaaS?

Sim, mas você precisa planejar em torno de limites de taxa. A principal restrição é 50 certificados por domínio registrado por semana (para seus próprios subdomínios de plataforma) e 300 novos pedidos por 3 horas. Para domínios personalizados de clientes, cada domínio é um domínio registrado separado, então o limite por domínio não se aplica da mesma forma. Você também pode solicitar ao Let's Encrypt um aumento de limite de taxa se puder demonstrar necessidade legítima. ZeroSSL é um provedor ACME fallback sólido.

Qual é a diferença entre subdomínios curinga e domínios personalizados?

Subdomínios curinga (*.seuapp.com) são controlados inteiramente por você — um registro DNS, um certificado SSL, roteamento simples. Domínios personalizados (portal.cliente.com) são domínios controlados pelos seus clientes, exigindo que eles configurem DNS e você provisione certificados individuais. A maioria dos produtos SaaS começa com subdomínios curinga e adiciona suporte de domínio personalizado depois como recurso premium.

Como trato domínios de apex (bare) personalizados?

Domínios de apex (cliente.com sem www) não conseguem usar registros CNAME per a especificação DNS. Suas opções são: ter clientes criar registros A apontando para seu IP, usar provedores DNS que suportam registros ALIAS/ANAME, ou recomendar provedores com CNAME flattening como Cloudflare. Sempre suporte ambas configurações de apex e subdomínio — clientes quererão ambas.

Devo usar Caddy ou nginx para SSL automatizado?

Se você está começando do zero, use Caddy. Seu recurso de TLS sob demanda foi literalmente construído para o caso de uso de domínio personalizado multi-tenant. Nginx é bom se você já tem isso em seu stack, mas você precisará construir mais automação ao redor de certbot para gerenciamento de ciclo de vida de certificado. Caddy trata emissão, renovação, armazenamento e OCSP stapling automaticamente.

Como previno abuso do meu recurso de domínio personalizado?

Três camadas: Primeiro, verifique a propriedade do domínio com um registro TXT antes de aceitar um domínio personalizado. Segundo, implemente um endpoint "ask" (como o ask on_demand_tls de Caddy) que valida domínios antes de solicitar certificados. Terceiro, limite adições de domínio por conta. Sem esses, alguém poderia apontar milhares de domínios para seu IP e queimar seus limites de taxa de certificado ou usar sua infraestrutura para domain fronting.

O que acontece se um cliente remove seu registro DNS?

Sua plataforma deve detectar isso dentro de horas através de health checks regulares. Quando DNS para de resolver para sua infraestrutura, marque o domínio como insalubre, notifique o cliente e pare de tentar renovar certificado. Não delete a configuração do domínio imediatamente — clientes às vezes quebram DNS temporariamente durante migrações. Recomendo um período de carência de 30 dias antes de desativar completamente um domínio personalizado.

Cloudflare for SaaS vale a pena comparado a auto-gerenciar certificados?

Para a maioria dos produtos SaaS, sim. Em $0.10/hostname/mês, o custo é trivial comparado ao tempo de engenharia que você gastaria construindo e mantendo automação de certificado, tratando edge cases, monitorando renovações e lidando com limites de taxa. Você também obtém um CDN global e proteção DDoS inclusos. A principal razão para auto-gerenciar é se você precisar de controle total sobre sua infraestrutura ou tenha requisitos de compliance específicos que previnam usar um proxy de terceiros. Se quiser discutir a abordagem correta para seu produto específico, nos contate — implementamos ambos os padrões.

Domínios personalizados são um desses recursos SaaS onde o diabo realmente está nos detalhes. O caminho feliz é direto, mas prontidão em produção significa tratar atrasos de propagação DNS, falhas de certificado, configuração incorreta de cliente e monitoramento em escala. Comece com subdomínios curinga, adicione suporte de domínio personalizado quando clientes pedirem por isso (e peçam), e não tente construir tudo do zero quando ferramentas como Caddy e Cloudflare for SaaS existem. Seu futuro eu de on-call vai agradecer.