northstar

module
v1.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: AGPL-3.0

README

Northstar

Fast, lightweight authoritative DNS server built for infrastructure you own.

Northstar is a production-grade DNS server written in Go that gives you full control over your DNS infrastructure — no third-party API, no vendor dashboard, no per-query pricing. Define your zones in simple TOML files, store them on disk or in any S3-compatible object store, and let Northstar handle the rest.

It speaks UDP, TCP, and DNS-over-TLS (DoT), responds in ~160 microseconds, and fits in a single static binary. Whether you're running a handful of domains on a VPS or powering service discovery across a distributed cluster, Northstar is designed to stay out of your way and just work.

Why Northstar?
  • Self-hosted DNS done right — Run your own authoritative nameserver without the operational complexity of BIND or PowerDNS. Zone files are human-readable TOML, configuration is environment variables, and the whole thing deploys as a single container.
  • S3-native zone management — Store zone files in AWS S3, Predastore, MinIO, or any S3-compatible backend. Northstar syncs automatically, so you can manage DNS records through the same object storage pipeline as the rest of your infrastructure.
  • Built for Spinifex — Northstar serves as the DNS backbone for Spinifex, an open-source AWS alternative. It handles both internal service discovery (SRV records for NATS, gateways, and other cluster services) and public-facing authoritative DNS, all from the same instance.
  • Plays nice with public resolvers — Full RFC compliance means Cloudflare (1.1.1.1), Google (8.8.8.8), and every other recursive resolver can properly resolve your domains. TCP fallback, EDNS0, correct NXDOMAIN/NODATA semantics, proper authority sections — the things that matter when your DNS needs to actually work on the real internet.

Features

  • UDP + TCP + DNS-over-TLS on configurable ports
  • EDNS0 support for modern resolver compatibility
  • 10 record types — A, AAAA, CNAME, MX, NS, TXT, SOA, SRV, CAA, PTR
  • Wildcard records with exact-match priority
  • In-memory hashmap for O(1) lookups (~160µs per query)
  • Zone files in TOML format, loaded from local filesystem or S3
  • Live reload — filesystem watch (fsnotify) or periodic S3 sync
  • S3-compatible backends — works with AWS S3, Predastore, MinIO, etc.
  • Correct RFC semantics — NXDOMAIN, NODATA, REFUSED, NS authority section, zone-based SOA serial
  • Configurable upstream resolvers with TLS and failover for CNAME chasing
  • Graceful shutdown on SIGTERM/SIGINT
  • Container-first — multi-arch Docker images, single binary

Quick Start

git clone https://github.com/mulgadc/northstar
cd northstar
make build
ZONE_DIR="./config/domains" ./bin/northstar

Verify it works:

dig @127.0.0.1 hello_a.net A
dig @127.0.0.1 hello_a.net MX
dig @127.0.0.1 hello_a.net TXT
dig @127.0.0.1 hello_a.net A +tcp      # TCP query
dig @127.0.0.1 hello_a.net A +edns=0   # EDNS0 query

Configuration

All configuration is via environment variables.

Core
Variable Default Description
ZONE_DIR config/domains/ Path to zone files or s3://bucket-name
HOST 0.0.0.0 Listen address
PORT 53 Listen port (UDP + TCP)
NORTHSTAR_LOG_IGNORE Suppress all logging
NORTHSTAR_LOG_DEBUG Enable debug logging
DNS-over-TLS
Variable Default Description
NORTHSTAR_TLS_CERT Path to TLS certificate (PEM)
NORTHSTAR_TLS_KEY Path to TLS private key
DOT_PORT 853 DoT listener port
S3 / S3-Compatible Storage
Variable Default Description
AWS_ACCESS_KEY AWS access key ID
AWS_SECRET_ACCESS_KEY AWS secret access key
AWS_REGION AWS region
NORTHSTAR_S3_ENDPOINT Custom S3 endpoint URL (for Predastore, MinIO, etc.)
NORTHSTAR_S3_INSECURE Standalone environment mode only: skip S3 TLS certificate verification
S3_SYNC_RETRY 60 S3 sync interval in seconds
Upstream Resolvers
Variable Default Description
NORTHSTAR_UPSTREAM tls://1.1.1.1:853,tls://8.8.8.8:853,1.1.1.1:53 Comma-separated upstream servers for CNAME chasing. Prefix with tls:// for DNS-over-TLS.

Zone File Format

Zone files use TOML. Each file represents one zone and is named <domain>.toml.

version = 1.0

[domain]
domain = "example.com"
soa = "ns1.example.com."
created = 2024-01-01T00:00:00Z
modified = 2024-06-15T12:00:00Z
verified = true
active = true
ownerid = 1

[defaults]
ttl = 3600
type = 1    # A record
class = 1   # IN

# A records
[[records]]
domain = ""
address = "203.100.1.1"

[[records]]
domain = "www."
address = "203.100.1.1"

# Wildcard — matches any subdomain without an explicit record
[[records]]
domain = "*."
address = "203.100.1.99"

# NS records
[[records]]
domain = ""
type = 2
address = "ns1.example.com."

[[records]]
domain = ""
type = 2
address = "ns2.example.com."

# MX records
[[records]]
domain = ""
type = 15
preference = 10
address = "mail.example.com."

# TXT records (SPF, DKIM, verification, etc.)
[[records]]
domain = ""
type = 16
address = "v=spf1 mx a -all"

# AAAA record
[[records]]
domain = ""
type = 28
address = "2001:db8::1"

# SRV record (service discovery)
[[records]]
domain = "_nats._tcp."
type = 33
priority = 10
weight = 0
port = 4222
address = "node1.example.com."

# CAA record (certificate authority authorization)
[[records]]
domain = ""
type = 257
caa_flag = 0
caa_tag = "issue"
address = "letsencrypt.org"

# PTR record (reverse DNS — in a separate zone file for in-addr.arpa)
# [[records]]
# domain = "1."
# type = 12
# address = "host-1.example.com."
Record Type Reference
Type Code Fields
A 1 address (IPv4)
NS 2 address (nameserver FQDN)
CNAME 5 address (target FQDN)
SOA 6 Auto-generated from [domain] section
PTR 12 address (target FQDN)
MX 15 address (mail server FQDN), preference
TXT 16 address (text value)
AAAA 28 address (IPv6)
SRV 33 address (target FQDN), priority, weight, port
CAA 257 address (CA domain), caa_flag, caa_tag

Spinifex Integration

Northstar serves as the DNS layer for Spinifex, providing both internal service discovery and public authoritative DNS.

Service discovery with SRV records:

# _nats._tcp.spinifex.spx3.net → node1.spinifex.spx3.net:4222
[[records]]
domain = "_nats._tcp.spinifex."
type = 33
priority = 10
weight = 0
port = 4222
address = "node1.spinifex.spx3.net."

# _awsgw._tcp.spinifex.spx3.net → node1.spinifex.spx3.net:9999
[[records]]
domain = "_awsgw._tcp.spinifex."
type = 33
priority = 10
weight = 0
port = 9999
address = "node1.spinifex.spx3.net."

Using Predastore as the zone file backend:

Mulga's S3-compatible storage (Predastore) can serve as the zone file backend, keeping DNS configuration alongside the rest of the Spinifex infrastructure. Northstar verifies the endpoint certificate using the system trust store; install a private CA there or provide it with SSL_CERT_FILE / SSL_CERT_DIR:

ZONE_DIR="s3://dns-zones" \
NORTHSTAR_S3_ENDPOINT="https://predastore.spinifex.spx3.net:8443" \
SSL_CERT_FILE="/path/to/spinifex-ca.pem" \
AWS_ACCESS_KEY="..." \
AWS_SECRET_ACCESS_KEY="..." \
AWS_REGION="us-west-1" \
./bin/northstar

Docker

Docker Compose (S3):

AWS_ACCESS_KEY="X" AWS_SECRET_ACCESS_KEY="Y" ZONE_DIR="s3://my-bucket" AWS_REGION="us-west-1" docker compose up -d

Standalone (filesystem):

docker run \
  --mount src=./config/domains,target=/config/domains,type=bind \
  -e ZONE_DIR="/config/domains" \
  -p 53:53/udp -p 53:53/tcp \
  calacode/northstar-dns

With DNS-over-TLS:

docker run \
  --mount src=./config/domains,target=/config/domains,type=bind \
  --mount src=./certs,target=/certs,type=bind \
  -e ZONE_DIR="/config/domains" \
  -e NORTHSTAR_TLS_CERT="/certs/server.pem" \
  -e NORTHSTAR_TLS_KEY="/certs/server.key" \
  -p 53:53/udp -p 53:53/tcp -p 853:853/tcp \
  calacode/northstar-dns

Testing

make test          # Unit tests
make test-race     # Unit tests with the race detector
make test-cover    # Unit tests with coverage (fails below threshold)
make lint          # golangci-lint (use `make fix` to auto-fix)
make govulncheck   # Dependency vulnerability scan
make bench         # Benchmarks
make e2e           # E2E tests via Docker (Predastore + Northstar)
make preflight     # lint + govulncheck + coverage + race

Benchmarking

make bench

Simulates 26 domains with ~255 subdomains each:

name           time/op
DNSQueryA-8     160µs ±12%
DNSQueryTXT-8   172µs ±19%
DNSQueryMX-8    162µs ±12%

name           alloc/op
DNSQueryA-8    3.09kB ± 0%
DNSQueryTXT-8  3.68kB ± 0%
DNSQueryMX-8   4.05kB ± 0%

Roadmap

See DEV.md for the full development plan.

  • DNS-over-HTTPS (DoH)
  • DNSSEC signing
  • Prometheus metrics endpoint
  • Rate limiting / DDoS protection
  • Dynamic record API (HTTP)
  • Split-horizon DNS (internal vs external views)
  • Health-aware DNS responses
  • Response caching

License

Northstar is licensed under the GNU Affero General Public License v3.0 (AGPLv3). See LICENSE for the full text.

Directories

Path Synopsis
cmd
northstar command
pkg
server
Package server provides an embeddable Northstar DNS server with an explicit configuration struct and a Start/Reload/Shutdown lifecycle, replacing the former blocking, env-driven backend.StartDaemon entrypoint.
Package server provides an embeddable Northstar DNS server with an explicit configuration struct and a Start/Reload/Shutdown lifecycle, replacing the former blocking, env-driven backend.StartDaemon entrypoint.
telemetry
Package telemetry configures OpenTelemetry tracing and metrics for northstar.
Package telemetry configures OpenTelemetry tracing and metrics for northstar.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL