sagittarius 0.1.0

A fast, self-hosted DNS sinkhole in a single Rust binary
Documentation

Sagittarius

A fast, self-hosted DNS sinkhole in a single Rust binary.

Sagittarius is an open-source, network-wide DNS sinkhole — it blocks ads, trackers, and malicious domains for every device on your network, in the spirit of Pi-hole and AdGuard Home. Everything — the DNS engine, storage, and web admin interface — ships in one self-contained binary.

It is named after Sagittarius A*, the supermassive black hole at the centre of the Milky Way: a fitting namesake for something whose job is to make unwanted traffic disappear.

⚠️ Early development. Sagittarius is pre-1.0 and not yet ready for general use. The design is described in SPEC.md; interfaces and features are still changing.


Goals

  • Single binary — no external services, interpreters, or web server to set up.
  • Fast — a hand-written DNS codec and a tokio/tower request pipeline keep the hot path lean.
  • Light — runs comfortably on small home servers, routers, and SBCs.
  • Operable — a clean, authenticated web UI for configuration, live query inspection, and statistics.

Planned features (v0.1)

  • 🛡️ DNS blocking via subscribable blocklists (hosts / domain-list formats) plus manual allow/deny lists. Exact-domain matching in v0.1.
  • 📊 Live query log and dashboard — block ratio, top domains, top clients, and a live query log streamed over SSE, with one-click allow/deny straight from the log.
  • 🔒 Encrypted upstreams — forward to resolvers over DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT).
  • 🏠 Local DNS records — define names for your own network, including wildcards (e.g. *.home.lan).

See the roadmap for what's planned beyond the first milestone.

Architecture at a glance

Layer Technology
Async runtime tokio
Service middleware (rate limiting, backpressure) tower
DNS wire format Custom lazy parser/serializer over bytes — shallow parse + raw passthrough
Upstream transport hickory — UDP/TCP/DoT/DoH
Persistent storage SQLite via sqlx — compile-time-checked queries, embedded migrations (config only, no query history yet)
Logging tracing to stdout; live log streamed to the UI over SSE
CLI / config clap flags (bind addresses, db path) with sane defaults
Hot-path state HashSet blacklist/allowlist/blocklist + HashMap local records, hot-swapped via arc-swap; moka cache with per-entry TTL
Web server axum
Templating / UI askama + Datastar (SSE) + Pico CSS
Frontend assets Vendored and embedded via include_str! / include_bytes! — no CDN, no Node build

The full design is documented in SPEC.md.

Install

Pick whichever fits; all three give the same single binary.

Prebuilt binary. Download a Linux x86_64 or aarch64 tarball from the latest release, verify its .sha256, unpack, and run ./sagittarius.

From crates.io.

cargo install sagittarius

Docker (multi-arch amd64 / arm64, published to GHCR):

docker run -d --name sagittarius \
  -p 53:53/udp -p 53:53/tcp \
  -p 127.0.0.1:8080:8080 \
  -v sagittarius-data:/data \
  ghcr.io/lhelge/sagittarius:latest

The admin UI is published on loopback above; front it with a reverse proxy for remote access. A ready-made Compose file is at deploy/docker-compose.yml.

Building

Requires a recent Rust toolchain (edition 2024).

git clone https://github.com/LHelge/sagittarius.git
cd sagittarius
cargo build --release

The resulting binary is at target/release/sagittarius.

Running

# all flags shown with their defaults — `sagittarius` alone works too
sagittarius --dns-addr 0.0.0.0:53 --admin-addr 127.0.0.1:8080 --db-path sagittarius.db --session-cookie-secure auto

On first run, open the admin interface and complete the one-step wizard to create the initial admin user. Everything else is pre-seeded to working defaults (e.g. Cloudflare 1.1.1.1 / 1.0.0.1 upstreams), so the resolver is functional immediately. All state lives in the single SQLite file at --db-path.

Notes:

  • Binding port 53 usually needs elevated privileges or the CAP_NET_BIND_SERVICE capability.
  • The admin interface serves plain HTTP and defaults to loopback. Put it behind a reverse proxy (Caddy, Traefik, nginx) for TLS / remote access.
  • --session-cookie-secure auto uses secure admin cookies when the browser-facing request is HTTPS, and allows direct local HTTP while testing.

Deployment

The deploy/ directory has ready-to-adapt examples:

  • deploy/sagittarius.service — a hardened systemd unit that runs Sagittarius as a dedicated unprivileged user with CAP_NET_BIND_SERVICE for port 53, the database under /var/lib/sagittarius, and graceful SIGTERM shutdown.
  • deploy/Caddyfile — a reverse-proxy snippet that terminates TLS (automatic certificates) in front of the loopback admin UI.

Bind the admin interface to loopback or a trusted network and reach it only through the proxy; the forwarded scheme/host headers it sets are trusted for secure-cookie and CSRF origin decisions.

Detailed installation and configuration docs will be added as the project stabilizes.

Contributing

Sagittarius is in early development and contributions, ideas, and feedback are welcome. Please read CONTRIBUTING.md for the quality gate, branch/PR workflow, and how to set up the local git hooks.

Enable the hooks with a single command after cloning:

git config core.hooksPath .githooks

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as below, without any additional terms or conditions.

License

Licensed under either of

at your option.