Serviço Próprio de DNS Autoritativo
Uma arquitetura prática para criar um serviço independente de DNS autoritativo com PowerDNS, PostgreSQL, painel web, API, receitas DNS, ACME, backup e monitoramento.
Serviço próprio de DNS autoritativo
Este documento organiza a ideia de criar um serviço próprio de DNS autoritativo: nameservers próprios, painel simples, API de automação, receitas prontas e operação segura.
A proposta é bonita, útil e tecnicamente viável. Mas o ponto central é simples: DNS é infraestrutura crítica. Se for feito com preguiça, não vira independência; vira uma máquina elegante de derrubar os próprios serviços.
Resumo rápido
| Campo | Decisão recomendada |
|---|---|
| Tipo de serviço | DNS autoritativo, não resolver recursivo |
| Software DNS | PowerDNS Authoritative |
| Banco | PostgreSQL |
| Nameservers | ns1 e ns2 em VPS diferentes |
| Painel | Web simples, com validações fortes |
| Automação | API própria + tokens com escopo |
| Certificados | DNS-01 para wildcard via Certbot/Caddy |
| Monitoramento | Uptime Kuma, Prometheus, Grafana e exporters |
| MVP | Domínio laboratório, nunca domínio crítico |
DNS próprio é liberdade, mas também responsabilidade operacional. O MVP precisa provar estabilidade antes de tocar em domínio importante.
Para que serve este projeto
Este projeto serve para criar um serviço próprio de hospedagem DNS autoritativa.
Na prática, ele permite que uma pessoa, empresa, comunidade ou projeto controle diretamente os registros DNS dos seus domínios usando nameservers próprios, em vez de depender totalmente de provedores externos para responder oficialmente por esses registros.
Exemplo com domínio fictício:
krikri.zone
Em um provedor DNS comum, os nameservers de krikri.zone poderiam ser algo como:
ns1.provedor.example
ns2.provedor.example
Neste projeto, a ideia é ter nameservers próprios:
ns1.krikri.zone
ns2.krikri.zone
ou, em uma arquitetura mais separada:
ns1.dns.krikri.zone
ns2.dns.krikri.zone
A partir daí, esses servidores passam a responder oficialmente por registros como:
krikri.zone. A 203.0.113.10
www.krikri.zone. CNAME krikri.zone.
mail.krikri.zone. A 203.0.113.20
krikri.zone. MX 10 mail.krikri.zone.
_acme-challenge.krikri.zone. TXT "token-de-validacao"
O serviço não é um resolver público como 1.1.1.1, 8.8.8.8 ou 9.9.9.9.
Ele é um servidor DNS autoritativo, ou seja, responde oficialmente pelas zonas delegadas a ele.
Em termos simples:
Resolver público:
usado por pessoas e computadores para perguntar "qual é o IP deste domínio?"
Servidor autoritativo:
usado pela internet para descobrir a resposta oficial de um domínio.
Este projeto quer resolver o segundo caso.
Objetivo do projeto
O objetivo é construir uma plataforma própria de DNS autoritativo com:
- nameservers próprios;
- painel web simples;
- API para automação;
- suporte a zonas DNS;
- criação, edição e remoção de registros;
- receitas DNS prontas;
- integração com certificados TLS via DNS-01;
- logs de auditoria;
- backup e rollback;
- monitoramento dos nameservers.
O diferencial não deve ser apenas “ter DNS próprio”. Isso, sozinho, não é produto.
O diferencial real deve ser:
- simplicidade;
- controle;
- independência;
- receitas prontas;
- interface humana;
- automação segura;
- integração com fediverse, e-mail, certificados, sites indie e infraestrutura pessoal;
- explicação clara de erros DNS;
- operação suficientemente robusta para não derrubar os próprios domínios.
Conceito central
A versão mínima do projeto deve permitir:
- cadastrar domínios/zonas;
- criar, editar e remover registros DNS;
- hospedar zonas em nameservers próprios;
- gerar API tokens;
- permitir automação ACME/DNS-01 para certificados wildcard;
- aplicar receitas DNS prontas;
- registrar logs de auditoria;
- monitorar saúde dos nameservers;
- fazer backup das zonas;
- evitar erros clássicos de configuração DNS.
Exemplo de uso com krikri.zone:
1. O domínio krikri.zone é registrado normalmente em um registrador.
2. No registrador, são criados glue records para ns1.krikri.zone e ns2.krikri.zone.
3. Os nameservers do domínio são alterados para ns1.krikri.zone e ns2.krikri.zone.
4. O painel do serviço passa a controlar a zona krikri.zone.
5. Registros A, AAAA, CNAME, MX, TXT, CAA e outros são gerenciados pelo painel/API.
6. Certificados wildcard podem ser emitidos automaticamente com desafio DNS-01.
Público-alvo possível
Inicialmente, o público-alvo deve ser o próprio operador do serviço.
Ou seja: primeiro construir para uso pessoal, em domínios não críticos.
Depois, se o serviço ficar estável, poderia atender:
- administradores de homelab;
- donos de pequenos sites;
- projetos indie web;
- usuários de fediverse;
- operadores de e-mail próprio;
- pequenos provedores;
- comunidades como pubnix;
- pessoas que querem fugir de painéis DNS inchados;
- pessoas que querem receitas prontas para configurar domínios.
Para uso comercial amplo, o nível de responsabilidade sobe muito. DNS é infraestrutura crítica. Um erro pode derrubar sites, e-mails, certificados e serviços federados.
Para o exemplo krikri.zone, o projeto deve começar como ferramenta interna/laboratório. Só depois de estabilidade real, backup testado, monitoramento e rollback funcional faria sentido pensar em uso por terceiros.
Nomes possíveis
Algumas ideias de nome:
Krikri DNS
Zone Garden
DNS Garden
Krikri Zones
Krikri Zonekeeper
A estética pode seguir uma linha:
- indie web;
- old web;
- terminal;
- pubnix;
- “cozinha” de receitas DNS;
- jardim de zonas;
- laboratório DNS;
- personagem assistente explicando erros.
Uma boa direção seria algo como:
Zone Garden — um jardim de zonas DNS com receitas prontas, automação segura e painel simples.
Ou:
Krikri DNS — DNS hosting autoritativo para projetos indie, fediverse, e-mail próprio e certificados wildcard.
Conceitos técnicos fundamentais
1 DNS autoritativo
Um servidor DNS autoritativo é aquele que responde oficialmente por uma zona.
Exemplo:
krikri.zone
Se o domínio estiver delegado para:
ns1.krikri.zone
ns2.krikri.zone
então esses nameservers respondem oficialmente por registros como:
www.krikri.zone
mail.krikri.zone
_acme-challenge.krikri.zone
2 Resolver recursivo
Não confundir com resolver recursivo.
Resolvers como:
1.1.1.1
8.8.8.8
9.9.9.9
são usados por clientes para consultar a internet. Eles perguntam aos servidores autoritativos e devolvem a resposta ao usuário.
Este projeto não é sobre criar um resolver público. É sobre hospedar DNS autoritativo.
3 Nameserver próprio
Exemplo:
ns1.krikri.zone
ns2.krikri.zone
Esses hosts precisam apontar para IPs públicos de servidores que rodam software DNS autoritativo.
4 Glue records
Se o nameserver está dentro do próprio domínio que ele ajuda a resolver, é preciso criar glue records no registrador.
Exemplo:
krikri.zone
Nameservers:
ns1.krikri.zone
ns2.krikri.zone
Problema circular:
Para saber o IP de
ns1.krikri.zone, eu preciso consultarkrikri.zone. Mas para consultarkrikri.zone, eu preciso saber onde estáns1.krikri.zone.
Solução: no registrador do domínio, cadastrar hosts de nameserver:
ns1.krikri.zone → IP_DA_VPS_1
ns2.krikri.zone → IP_DA_VPS_2
Isso são os glue records.
5 Zona DNS
Uma zona é o conjunto de registros de um domínio.
Exemplo de zona:
$ORIGIN krikri.zone.
$TTL 3600
@ IN SOA ns1.krikri.zone. hostmaster.krikri.zone. (
2026062701 ; serial
3600 ; refresh
900 ; retry
1209600 ; expire
3600 ; minimum
)
@ IN NS ns1.krikri.zone.
@ IN NS ns2.krikri.zone.
@ IN A 203.0.113.10
www IN CNAME krikri.zone.
mail IN A 203.0.113.20
@ IN MX 10 mail.krikri.zone.
BIND 9 vs PowerDNS
Existem duas rotas principais.
1 Rota A: BIND 9
BIND 9 é uma opção clássica para servidores DNS autoritativos. Ele trabalha muito bem com arquivos de zona e é excelente para aprendizado profundo de DNS.
Vantagens:
- tradicional;
- muito documentado;
- estável;
- arquivos de zona legíveis;
- ótimo para aprendizado profundo de DNS;
- compatível com praticamente tudo.
Desvantagens:
- menos confortável para virar produto web;
- edição concorrente de arquivos de zona exige cuidado;
- reload/reconfiguração precisa ser bem controlado;
- automação de DNSSEC pode ficar mais delicada;
- painel próprio exige mais cola operacional;
- auditoria e histórico exigem implementação adicional.
BIND pode ser usado com dynamic update via RFC 2136, mas a experiência de construir um painel e uma API completos em cima dele é menos direta do que com PowerDNS.
2 Rota B: PowerDNS Authoritative
Para este projeto, a recomendação principal é usar PowerDNS Authoritative com PostgreSQL.
Vantagens:
- tem API HTTP/JSON oficial;
- trabalha muito bem com banco SQL;
- é mais amigável para painel web;
- facilita auditoria;
- facilita automação;
- facilita replicação;
- facilita integração com backend próprio;
- suporta DNSSEC;
- é mais adequado para produto.
Desvantagens:
- menos “old-school” que BIND;
- exige banco de dados;
- exige entender bem o modelo de dados;
- painel próprio precisa validar regras DNS corretamente.
Recomendação honesta:
Para um serviço próprio com painel web, API, receitas e automação, PowerDNS + PostgreSQL é a melhor escolha inicial.
Arquitetura recomendada
Arquitetura inicial:
┌───────────────────────────┐
│ app.dns.krikri.zone │
│ Painel Web + API própria │
└────────────┬──────────────┘
│
▼
┌───────────────────────────┐
│ PostgreSQL │
│ users/zones/records/logs │
└────────────┬──────────────┘
│
▼
┌─────────────────────────────────────────┐
│ PowerDNS Authoritative │
│ ns1 + ns2 lendo banco/replicação │
└─────────────────────────────────────────┘
│
▼
Internet DNS
Arquitetura com dois servidores:
┌──────────────────────────────────────┐
│ VPS 1 │
│ │
│ ns1.krikri.zone │
│ PowerDNS Authoritative │
│ PostgreSQL primary │
│ API/painel opcional │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ VPS 2 │
│ │
│ ns2.krikri.zone │
│ PowerDNS Authoritative │
│ PostgreSQL replica ou AXFR │
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│ VPS 3 opcional │
│ │
│ painel web │
│ worker de receitas │
│ backups │
│ monitoramento │
└──────────────────────────────────────┘
Não usar ns1 e ns2 no mesmo servidor. Isso só simula redundância, mas não entrega redundância real.
Errado:
ns1.krikri.zone → 203.0.113.10
ns2.krikri.zone → 203.0.113.10
Correto:
ns1.krikri.zone → 203.0.113.10
ns2.krikri.zone → 198.51.100.20
Ideal:
ns1.krikri.zone → VPS A / provedor A / região A
ns2.krikri.zone → VPS B / provedor B / região B
Componentes do sistema
1 Nameservers
Responsáveis por responder consultas DNS autoritativas.
Sugestão:
ns1.krikri.zone
ns2.krikri.zone
Software recomendado:
PowerDNS Authoritative
Alternativa:
BIND 9
2 Banco de dados
Recomendado:
PostgreSQL
Funções:
- armazenar zonas;
- armazenar registros;
- armazenar usuários;
- armazenar tokens de API;
- armazenar logs;
- armazenar receitas aplicadas;
- armazenar histórico de alterações.
3 Painel web
Funções:
- login;
- listagem de zonas;
- criação de zona;
- listagem de registros;
- editor de registros;
- aplicação de receitas;
- gerenciamento de API keys;
- visualização de logs;
- verificação de propagação DNS;
- tela de ajuda contextual.
4 API própria
Funções:
- criar zonas;
- listar zonas;
- criar registros;
- editar registros;
- apagar registros;
- aplicar receitas;
- criar/remover TXT de desafio ACME;
- consultar logs.
5 Worker de automação
Responsável por tarefas assíncronas:
- aplicar receitas complexas;
- validar propagação;
- rodar checagens periódicas;
- renovar estados;
- gerar backups;
- atualizar serial de zonas, se necessário;
- verificar integridade dos nameservers.
6 Monitoramento
Monitorar:
- porta 53 UDP;
- porta 53 TCP;
- resposta SOA;
- resposta NS;
- latência de consulta;
- divergência entre ns1 e ns2;
- erros de API;
- falhas de replicação;
- expiração de zonas secundárias;
- status do PostgreSQL;
- uso de disco;
- uso de memória;
- carga do servidor.
Ferramentas possíveis:
Uptime Kuma
Prometheus
Grafana
node_exporter
blackbox_exporter
PowerDNS exporter
7 Backups
Backup obrigatório de:
- banco PostgreSQL;
- configuração do PowerDNS;
- secrets/API tokens com hash;
- arquivos de configuração;
- snapshots das zonas;
- logs importantes.
Política recomendada:
backup diário local
backup diário remoto
retenção de 7 dias
retenção semanal de 4 semanas
retenção mensal de 6 meses
Modelo de dados sugerido
Se usar PowerDNS, parte do modelo de dados vem do próprio schema do PowerDNS. Mesmo assim, o painel próprio deve ter tabelas de aplicação.
1 Usuários
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
name TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
2 Zonas da aplicação
CREATE TABLE app_zones (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
name TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'active',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
3 Tokens de API
CREATE TABLE api_tokens (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
zone_id BIGINT REFERENCES app_zones(id),
name TEXT NOT NULL,
token_hash TEXT NOT NULL,
scopes JSONB NOT NULL DEFAULT '[]',
allowed_names JSONB NOT NULL DEFAULT '[]',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_used_at TIMESTAMPTZ
);
4 Logs de auditoria
CREATE TABLE audit_logs (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id),
zone_id BIGINT REFERENCES app_zones(id),
action TEXT NOT NULL,
old_value JSONB,
new_value JSONB,
ip INET,
user_agent TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
5 Receitas aplicadas
CREATE TABLE applied_recipes (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id),
zone_id BIGINT NOT NULL REFERENCES app_zones(id),
recipe_name TEXT NOT NULL,
recipe_version TEXT NOT NULL,
applied_records JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
API mínima
1 Zonas
GET /api/zones
POST /api/zones
GET /api/zones/:zone
DELETE /api/zones/:zone
2 Registros
GET /api/zones/:zone/records
POST /api/zones/:zone/records
PUT /api/zones/:zone/records/:id
DELETE /api/zones/:zone/records/:id
3 Receitas
GET /api/recipes
GET /api/recipes/:recipe
POST /api/zones/:zone/apply-recipe
4 Tokens
GET /api/tokens
POST /api/tokens
DELETE /api/tokens/:id
5 ACME / LEGO
POST /api/lego/present
POST /api/lego/cleanup
Payload para present:
{
"fqdn": "_acme-challenge.krikri.zone.",
"value": "token-do-letsencrypt",
"ttl": 120
}
Payload para cleanup:
{
"fqdn": "_acme-challenge.krikri.zone.",
"value": "token-do-letsencrypt"
}
Autenticação:
Authorization: Bearer TOKEN
Regras obrigatórias:
- token precisa pertencer ao usuário;
- token precisa ter escopo ACME;
- token precisa estar limitado à zona correta;
- token não deve conseguir editar registros fora de
_acme-challenge; - token não deve conseguir apagar registros não criados por ele, salvo regra explícita;
- todas as ações devem gerar log.
Integração com certificados TLS
Uma das funções mais úteis do serviço é permitir emissão de certificados wildcard via DNS-01.
Exemplo:
*.krikri.zone
Fluxo:
Caddy/Certbot pede certificado wildcard
↓
Let's Encrypt exige TXT em _acme-challenge.dominio.com
↓
Caddy/Certbot chama API do serviço DNS
↓
Serviço cria TXT no PowerDNS
↓
Let's Encrypt consulta o TXT
↓
Certificado é emitido
↓
Serviço remove o TXT
1 Hook Certbot: auth
Exemplo conceitual:
#!/usr/bin/env bash
set -euo pipefail
: "${KRIKRIDNS_API_BASE:?Missing KRIKRIDNS_API_BASE}"
: "${KRIKRIDNS_API_TOKEN:?Missing KRIKRIDNS_API_TOKEN}"
domain="${CERTBOT_DOMAIN:?Missing CERTBOT_DOMAIN}"
value="${CERTBOT_VALIDATION:?Missing CERTBOT_VALIDATION}"
fqdn="_acme-challenge.${domain}"
fqdn="${fqdn%.}."
curl -fsS \
-H "Authorization: Bearer ${KRIKRIDNS_API_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"fqdn\":\"${fqdn}\",\"value\":\"${value}\",\"ttl\":120}" \
"${KRIKRIDNS_API_BASE%/}/api/lego/present"
2 Hook Certbot: cleanup
#!/usr/bin/env bash
set -euo pipefail
: "${KRIKRIDNS_API_BASE:?Missing KRIKRIDNS_API_BASE}"
: "${KRIKRIDNS_API_TOKEN:?Missing KRIKRIDNS_API_TOKEN}"
domain="${CERTBOT_DOMAIN:?Missing CERTBOT_DOMAIN}"
value="${CERTBOT_VALIDATION:?Missing CERTBOT_VALIDATION}"
fqdn="_acme-challenge.${domain}"
fqdn="${fqdn%.}."
curl -fsS \
-H "Authorization: Bearer ${KRIKRIDNS_API_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"fqdn\":\"${fqdn}\",\"value\":\"${value}\"}" \
"${KRIKRIDNS_API_BASE%/}/api/lego/cleanup"
3 Caddy provider futuro
Mais tarde, pode ser criado um provider libdns.
Exemplo de configuração desejada no Caddy:
{
acme_dns krikridns {
api_base_url https://dns.krikri.zone/api/lego/
api_token {$KRIKRIDNS_API_TOKEN}
ttl 120
}
}
*.krikri.zone {
tls {
dns krikridns
}
reverse_proxy 127.0.0.1:8080
}
Receitas DNS
As receitas são o grande diferencial do produto.
Em vez de exigir que o usuário saiba exatamente quais registros criar, o sistema oferece ações prontas.
1 Receita: domínio que não envia nem recebe e-mail
Objetivo: impedir abuso de spoofing em um domínio sem e-mail.
Registros:
@ MX 0 .
@ TXT "v=spf1 -all"
*._domainkey TXT "v=DKIM1; p="
_dmarc TXT "v=DMARC1; p=reject; adkim=s; aspf=s;"
2 Receita: proteção básica de e-mail
Registros:
@ TXT "v=spf1 include:provedor.example -all"
_dmarc TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@krikri.zone"
DKIM dependeria do provedor.
3 Receita: Google Workspace
Criar MX padrão do Google:
@ MX 1 ASPMX.L.GOOGLE.COM.
@ MX 5 ALT1.ASPMX.L.GOOGLE.COM.
@ MX 5 ALT2.ASPMX.L.GOOGLE.COM.
@ MX 10 ALT3.ASPMX.L.GOOGLE.COM.
@ MX 10 ALT4.ASPMX.L.GOOGLE.COM.
Também preparar SPF:
@ TXT "v=spf1 include:_spf.google.com -all"
4 Receita: Fastmail
Criar os registros necessários para Fastmail, incluindo MX, SPF, DKIM e DMARC, conforme valores fornecidos pela conta do usuário.
5 Receita: Resend
Criar registros de envio transacional:
SPF
DKIM
DMARC
CNAME de tracking, se aplicável
Os valores devem ser preenchidos com base no painel do Resend.
6 Receita: GoToSocial / Fediverse
Criar registros comuns:
@ A IP_DO_SERVIDOR
www CNAME @
Opcionalmente, documentar uso de WebFinger, ActivityPub e proxies.
7 Receita: Ghost
Criar registros:
@ A IP_DO_SERVIDOR
www CNAME @
Ou, se hospedagem externa exigir:
www CNAME host-do-provedor.example.
8 Receita: Bluesky handle
Criar TXT para handle do Bluesky:
_atproto TXT "did=did:plc:..."
9 Receita: Matrix
Criar registros .well-known não é DNS puro, mas DNS pode ajudar com delegation via SRV, dependendo do modelo usado.
Possível receita:
_matrix._tcp.krikri.zone SRV 10 5 8448 matrix.krikri.zone.
10 Receita: CAA para Let's Encrypt
@ CAA 0 issue "letsencrypt.org"
@ CAA 0 iodef "mailto:admin@krikri.zone"
11 Receita: wildcard ACME
Criar API token limitado a:
_acme-challenge.krikri.zone
Escopo:
acme:dns01
Permissões:
create TXT
delete own TXT
Validações obrigatórias
DNS tem regras chatas. O painel deve proteger o usuário de erros comuns.
1 CNAME não pode coexistir com outros registros
Inválido:
blog A 203.0.113.10
blog CNAME krikri.zone.
Também inválido:
blog CNAME krikri.zone.
blog TXT "teste"
Se um hostname tem CNAME, ele não deve ter outros tipos de registro.
2 MX precisa de prioridade
Inválido:
@ MX mail.krikri.zone.
Correto:
@ MX 10 mail.krikri.zone.
3 SRV precisa de formato correto
Formato:
_service._proto.name TTL IN SRV priority weight port target
Exemplo:
_matrix._tcp.krikri.zone. 3600 IN SRV 10 5 8448 matrix.krikri.zone.
4 CAA precisa ser validado
Exemplo:
@ CAA 0 issue "letsencrypt.org"
5 TXT pode precisar de chunking
TXT muito grande pode precisar ser dividido em múltiplas strings dentro do mesmo registro.
6 Impedir edição fora da zona
Se o usuário controla:
krikri.zone
A API não pode aceitar:
_acme-challenge.outrodominio.com
7 TTL mínimo e máximo
Definir limites:
TTL mínimo: 60 ou 120 segundos
TTL padrão: 3600 segundos
TTL máximo: 86400 ou 604800 segundos
8 Proteção de SOA e NS
O usuário comum não deve conseguir apagar acidentalmente:
SOA
NS principais
A edição desses registros precisa ser controlada.
Segurança
1 API tokens com escopo
Nunca usar token global para tudo.
Tipos de token:
read-only
zone-admin
record-editor
acme-dns01
recipe-runner
Token ACME deve ser extremamente limitado.
Exemplo:
{
"scope": "acme:dns01",
"zone": "krikri.zone",
"allowed_names": [
"_acme-challenge.krikri.zone."
],
"allowed_types": ["TXT"]
}
2 Hash de tokens
Nunca armazenar token puro.
Guardar apenas hash:
sha256/token hash com salt adequado
Mostrar o token ao usuário apenas uma vez.
3 Logs de auditoria
Registrar:
- usuário;
- IP;
- user-agent;
- ação;
- zona;
- registro anterior;
- registro novo;
- horário.
4 Rate limiting
Aplicar limite em:
- login;
- criação de registros;
- chamadas ACME;
- criação de tokens;
- endpoints públicos.
5 2FA
Para qualquer serviço DNS com painel web, 2FA é recomendável.
Mínimo:
TOTP
6 Backups e rollback
Toda alteração de zona deve poder ser revertida.
Ideal:
histórico de versões da zona
botão “restaurar versão anterior”
exportação BIND zone file
DNSSEC
DNSSEC é útil, mas adiciona complexidade.
Recomendação:
- não ativar DNSSEC no MVP;
- implementar DNSSEC depois que o básico estiver estável;
- automatizar rotação de chaves;
- documentar claramente DS records no registrador;
- criar alertas para erro de validação.
Erro em DNSSEC pode deixar o domínio aparentemente “fora do ar” para resolvers validadores.
DNSSEC mal operado é pior do que DNS sem DNSSEC.
UX do painel
Telas mínimas:
Dashboard
Zonas
Registros
Receitas
API Keys
Logs
Verificador DNS
Configurações
Ajuda
1 Dashboard
Mostrar:
- quantidade de zonas;
- total de registros;
- status de ns1;
- status de ns2;
- últimos logs;
- alertas;
- receitas sugeridas.
2 Tela de zona
Exemplo:
Zona: krikri.zone
Status: ativa
Nameservers esperados:
- ns1.krikri.zone
- ns2.krikri.zone
Delegação detectada:
- ns1.krikri.zone
- ns2.krikri.zone
SOA serial: 2026062701
Última alteração: 2026-06-27 14:32
3 Editor de registros
Tabela:
Nome | Tipo | Valor | TTL | Prioridade | Ações
4 Explicação de erros
Exemplo de erro útil:
Você tentou criar um CNAME em blog.krikri.zone, mas esse nome já possui um registro A.
DNS não permite CNAME coexistindo com outros registros no mesmo hostname.
Escolha uma opção:
1. apagar o registro A e criar CNAME;
2. manter o A;
3. criar o CNAME em outro subdomínio.
Isso é muito melhor do que:
Invalid record
5 Receitas com prévia
Antes de aplicar uma receita, mostrar exatamente o que será criado:
Esta receita criará:
@ MX 0 .
@ TXT "v=spf1 -all"
*._domainkey TXT "v=DKIM1; p="
_dmarc TXT "v=DMARC1; p=reject; adkim=s; aspf=s;"
Botões:
[Aplicar]
[Cancelar]
Stack sugerida
1 DNS
PowerDNS Authoritative
2 Banco
PostgreSQL
3 Backend
Boas opções:
Go
Python/FastAPI
Node.js/NestJS
PHP/Laravel
Escolha recomendada:
Python/FastAPI ou Go
Para produtividade rápida:
Python/FastAPI
Para binário simples e performance:
Go
4 Frontend
Opções:
HTML server-side simples
SvelteKit
Next.js
Django templates
Laravel Blade
Recomendação pragmática:
SvelteKit ou templates server-side simples
Não precisa virar uma SPA monstruosa.
5 Proxy
Caddy
ou:
Nginx
6 Monitoramento
Uptime Kuma
Prometheus
Grafana
7 Deploy
Opções:
Docker Compose
Systemd direto
Ansible
Para MVP:
Docker Compose
Para produção mais controlada:
Ansible + systemd + backups
Estrutura de repositório sugerida
krikri-dns/
├── README.md
├── docs/
│ ├── architecture.md
│ ├── api.md
│ ├── recipes.md
│ ├── security.md
│ └── operations.md
├── backend/
│ ├── app/
│ ├── migrations/
│ ├── tests/
│ └── pyproject.toml
├── frontend/
│ ├── src/
│ └── package.json
├── deploy/
│ ├── docker-compose.yml
│ ├── pdns/
│ ├── postgres/
│ └── caddy/
├── scripts/
│ ├── certbot-auth.sh
│ ├── certbot-cleanup.sh
│ ├── backup.sh
│ └── healthcheck.sh
└── recipes/
├── no-email-domain.yml
├── google-workspace.yml
├── resend.yml
├── gotosocial.yml
├── ghost.yml
└── letsencrypt-caa.yml
Formato de receita
Exemplo em YAML:
id: no-email-domain
name: Domínio sem e-mail
version: "1.0"
description: Protege um domínio que não envia nem recebe e-mail.
records:
- name: "@"
type: "MX"
priority: 0
content: "."
ttl: 3600
- name: "@"
type: "TXT"
content: "v=spf1 -all"
ttl: 3600
- name: "*._domainkey"
type: "TXT"
content: "v=DKIM1; p="
ttl: 3600
- name: "_dmarc"
type: "TXT"
content: "v=DMARC1; p=reject; adkim=s; aspf=s;"
ttl: 3600
warnings:
- "Use esta receita apenas se o domínio realmente não envia nem recebe e-mail."
Receita com variáveis:
id: resend
name: Resend
version: "1.0"
description: Configura registros básicos para envio via Resend.
variables:
- id: dkim_name
label: Nome do DKIM
required: true
- id: dkim_value
label: Valor do DKIM
required: true
records:
- name: "@"
type: "TXT"
content: "v=spf1 include:amazonses.com -all"
ttl: 3600
- name: "{{ dkim_name }}"
type: "TXT"
content: "{{ dkim_value }}"
ttl: 3600
- name: "_dmarc"
type: "TXT"
content: "v=DMARC1; p=quarantine;"
ttl: 3600
Plano de implementação
Fase 0: decisão de domínio
Escolher domínio base para nameservers.
Sugestões:
krikri.zone
krikri.zone
runv.club
Evitar usar domínio crítico no começo.
Não começar com:
portalidea.com.br
krikri.zone
murad.social
Fase 1: laboratório DNS
Objetivo: rodar PowerDNS Authoritative em uma VPS.
Entregáveis:
- PowerDNS instalado;
- PostgreSQL instalado;
- zona de teste criada;
- registros A/TXT/CNAME funcionando;
- consulta via
digfuncionando.
Exemplo de teste:
dig @IP_DA_VPS krikri.zone SOA
dig @IP_DA_VPS www.krikri.zone A
dig @IP_DA_VPS krikri.zone TXT
Fase 2: segundo nameserver
Objetivo: ter ns1 e ns2 reais.
Entregáveis:
- VPS 2 configurada;
- PowerDNS no segundo servidor;
- replicação ou AXFR funcionando;
- glue records no registrador;
- domínio de teste delegado.
Fase 3: painel mínimo
Objetivo: CRUD básico de zonas e registros.
Entregáveis:
- login;
- listar zonas;
- criar zona;
- listar registros;
- criar registro;
- editar registro;
- apagar registro;
- log básico.
Fase 4: API ACME
Objetivo: permitir DNS-01 automático.
Entregáveis:
- criação de API token;
- endpoint
/api/lego/present; - endpoint
/api/lego/cleanup; - hook Certbot;
- teste com certificado wildcard;
- logs.
Fase 5: receitas
Objetivo: transformar DNS em ações prontas.
Entregáveis:
- receita domínio sem e-mail;
- receita Google Workspace;
- receita Resend;
- receita CAA Let's Encrypt;
- receita GoToSocial;
- receita Ghost;
- prévia antes de aplicar;
- log de aplicação.
Fase 6: monitoramento
Objetivo: tratar DNS como infraestrutura crítica.
Entregáveis:
- Uptime Kuma monitorando porta 53 UDP/TCP;
- checagem de SOA em ns1 e ns2;
- alerta de divergência;
- backup diário;
- dashboard básico.
Fase 7: uso real controlado
Objetivo: colocar domínio não crítico em produção.
Entregáveis:
- domínio secundário usando nameservers próprios;
- registros reais;
- certificado wildcard via API;
- monitoramento por 30 dias;
- teste de restore.
Fase 8: expansão
Objetivo: avaliar abertura para terceiros.
Entregáveis:
- multiusuário seguro;
- 2FA;
- limites por usuário;
- billing, se comercial;
- termos de uso;
- documentação pública;
- status page.
Comandos úteis de teste
Consultar SOA
dig @ns1.krikri.zone krikri.zone SOA +short
Consultar NS
dig krikri.zone NS +short
Consultar contra nameserver específico
dig @ns1.krikri.zone www.krikri.zone A
Ver caminho de delegação
dig krikri.zone +trace
Testar TXT ACME
dig _acme-challenge.krikri.zone TXT +short
Comparar ns1 e ns2
dig @ns1.krikri.zone krikri.zone SOA +short
dig @ns2.krikri.zone krikri.zone SOA +short
Testar porta 53 TCP
dig @ns1.krikri.zone krikri.zone SOA +tcp
Riscos
1 Derrubar domínios próprios
Se nameservers falham, os domínios ficam inacessíveis.
Impacto:
- sites fora;
- e-mails falhando;
- certificados não renovando;
- fediverse quebrado;
- serviços internos indisponíveis.
2 Erro de zona
Um registro errado pode quebrar serviço crítico.
Mitigação:
- validação forte;
- histórico;
- rollback;
- preview antes de aplicar receitas.
3 Falha de replicação
ns1 e ns2 podem responder dados diferentes.
Mitigação:
- monitorar SOA serial;
- alertar divergência;
- testar AXFR/replicação.
4 Token vazado
Token API vazado pode permitir alteração de DNS.
Mitigação:
- escopos mínimos;
- token ACME limitado;
- hash de tokens;
- rotação;
- logs;
- rate limit.
5 DNSSEC mal configurado
DNSSEC quebrado pode fazer o domínio sumir para resolvers validadores.
Mitigação:
- não ativar DNSSEC no MVP;
- implementar só depois;
- automatizar DS/KSK/ZSK com cuidado.
O que não fazer
Não fazer:
usar uma VPS só para ns1 e ns2
colocar domínios críticos no primeiro teste
ativar DNSSEC cedo demais
não ter backup
não ter monitoramento
não ter rollback
não validar CNAME/MX/SRV/CAA
usar token global para ACME
armazenar API token puro
editar zona sem log
Não migrar inicialmente:
portalidea.com.br
krikri.zone
murad.social
serviços com e-mail crítico
Usar primeiro:
domínio laboratório
domínio descartável
subdomínio experimental
MVP recomendado
O MVP mais sensato:
PowerDNS Authoritative
PostgreSQL
2 VPS
ns1/ns2 reais
painel simples
API ACME
receitas básicas
monitoramento
backup
Escopo do MVP:
- login simples;
- uma conta admin;
- criação manual de zonas;
- CRUD de registros;
- API token ACME;
- Certbot hook;
- receita “domínio sem e-mail”;
- receita “CAA Let's Encrypt”;
- checagem ns1/ns2;
- exportação de zona.
Não incluir no MVP:
- billing;
- DNSSEC;
- multiusuário público;
- marketplace de receitas;
- Caddy plugin próprio;
- interface ultra sofisticada;
- suporte a todos os tipos obscuros de DNS.
Roadmap sugerido
Versão 0.1
- PowerDNS + PostgreSQL;
- uma zona de teste;
- CRUD via painel/admin;
- deploy em uma VPS.
Versão 0.2
- segundo nameserver;
- delegação real;
- monitoramento básico;
- backup.
Versão 0.3
- API ACME;
- Certbot hooks;
- wildcard funcionando.
Versão 0.4
- receitas YAML;
- receita domínio sem e-mail;
- receita CAA;
- preview de alterações.
Versão 0.5
- logs de auditoria;
- rollback;
- validações fortes.
Versão 0.6
- UI melhor;
- documentação pública;
- verificador DNS;
- onboarding de domínio.
Versão 1.0
- multiusuário seguro;
- 2FA;
- tokens com escopo;
- backups testados;
- status page;
- pronto para domínios próprios não críticos.
Pós-1.0
- DNSSEC;
- Caddy provider;
- billing;
- convites;
- abertura para terceiros;
- marketplace de receitas;
- assistente explicativo.
Ideia de posicionamento
Descrição curta:
Um serviço de DNS autoritativo simples e independente, com receitas prontas para e-mail, certificados, fediverse e projetos indie.
Descrição mais longa:
Um painel DNS autoritativo para pessoas que querem controlar seus próprios domínios sem depender totalmente de provedores grandes. Ele combina nameservers próprios, API, automação de certificados wildcard, receitas DNS prontas e explicações claras para evitar erros comuns.
Tom do produto:
simples
indie
técnico
humano
sem firula corporativa
com personalidade
Frase possível:
DNS sem drama para gente que hospeda coisas estranhas na internet.
Outra:
Um jardim de zonas DNS para projetos indie, fediverse, e-mail próprio e certificados wildcard.
Veredito final
A ideia é boa, mas deve ser tratada como infraestrutura crítica.
Construir um serviço desses é totalmente viável. A parte técnica não é absurda. O perigo está na operação: DNS é silencioso, mas quando falha, derruba tudo que depende dele.
A melhor estratégia é:
- começar com domínio laboratório;
- usar PowerDNS + PostgreSQL;
- ter dois nameservers reais;
- criar painel mínimo;
- implementar API ACME;
- adicionar receitas;
- monitorar tudo;
- testar backup e rollback;
- só depois pensar em terceiros.
A arquitetura recomendada é:
PowerDNS Authoritative
PostgreSQL
API própria
Painel web simples
Receitas YAML
Tokens com escopo
Integração Certbot/Caddy
2 VPS reais para ns1/ns2
Monitoramento e backup
O erro seria tentar transformar isso imediatamente em SaaS público.
O caminho inteligente é fazer primeiro como ferramenta própria, usar em domínios secundários, endurecer a operação e só então decidir se vale oferecer para outras pessoas.
DNS próprio é bonito, elegante e poderoso. Mas também é uma maneira sofisticada de derrubar os próprios serviços se for feito com preguiça.
Referências úteis
Links técnicos e documentação
- Caddy DNS providers / libdns: https://github.com/libdns
- PowerDNS Authoritative Server: https://doc.powerdns.com/authoritative/
- PowerDNS HTTP API: https://doc.powerdns.com/authoritative/http-api/index.html
- PowerDNS PostgreSQL backend: https://doc.powerdns.com/authoritative/backends/generic-postgresql.html
- BIND 9 documentation: https://bind9.readthedocs.io/
- Certbot manual hooks: https://eff-certbot.readthedocs.io/
- Let's Encrypt DNS-01 challenge: https://letsencrypt.org/docs/challenge-types/