{"id":49923703,"url":"https://github.com/redlemonbe/runbound","last_synced_at":"2026-06-14T04:01:00.344Z","repository":{"id":358333433,"uuid":"1240800752","full_name":"redlemonbe/Runbound","owner":"redlemonbe","description":"High-performance DNS server in Rust · drop-in Unbound replacement · AF/XDP fast path · REST API · DoT/DoH · static binaries for x86_64 \u0026 ARM","archived":false,"fork":false,"pushed_at":"2026-06-13T08:12:52.000Z","size":589935,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T08:13:45.193Z","etag":null,"topics":["af-xdp","dns","dns-server","dnssec","doh","dot","ebpf","rust","unbound","xdp"],"latest_commit_sha":null,"homepage":"https://www.runasm.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/redlemonbe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":"THREAT_MODEL.md","audit":"audit.toml","citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":"CLA.md"},"funding":{"github":"redlemonbe","custom":["https://github.com/sponsors/redlemonbe"]}},"created_at":"2026-05-16T15:31:39.000Z","updated_at":"2026-06-13T08:12:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/redlemonbe/Runbound","commit_stats":null,"previous_names":["redlemonbe/runbound"],"tags_count":164,"template":false,"template_full_name":null,"purl":"pkg:github/redlemonbe/Runbound","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redlemonbe%2FRunbound","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redlemonbe%2FRunbound/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redlemonbe%2FRunbound/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redlemonbe%2FRunbound/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redlemonbe","download_url":"https://codeload.github.com/redlemonbe/Runbound/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redlemonbe%2FRunbound/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34308622,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["af-xdp","dns","dns-server","dnssec","doh","dot","ebpf","rust","unbound","xdp"],"created_at":"2026-05-16T22:09:42.082Z","updated_at":"2026-06-14T04:01:00.338Z","avatar_url":"https://github.com/redlemonbe.png","language":"Rust","funding_links":["https://github.com/sponsors/redlemonbe"],"categories":[],"sub_categories":[],"readme":"# Runbound\n\n## ASM-accelerated, Unbound-compatible DNS server — live REST API + XDP fast path\n\n**Unbound-compatible DNS server — REST API, XDP kernel-bypass, no restart ever.**\n\n[![CI](https://github.com/redlemonbe/Runbound/actions/workflows/ci.yml/badge.svg)](https://github.com/redlemonbe/Runbound/actions/workflows/ci.yml) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![Commercial License](https://img.shields.io/badge/license-commercial-green.svg)](COMMERCIAL_LICENSE.md)\n[![GitHub release](https://img.shields.io/github/v/release/redlemonbe/Runbound)](https://github.com/redlemonbe/Runbound/releases/latest)\n[![cargo audit](https://img.shields.io/badge/cargo_audit-clean-brightgreen.svg)](docs/audit.md) [![GitHub Sponsors](https://img.shields.io/github/sponsors/redlemonbe?style=flat\u0026logo=github\u0026label=Sponsor)](https://github.com/sponsors/redlemonbe)\n\n\u003e ⚠️ **Status: Experimental** — Runbound is under active development and has not yet undergone external human security audit. Not yet recommended for production deployments handling sensitive traffic. See [METHODOLOGY.md](METHODOLOGY.md) for the development approach.\n\nMost existing `unbound.conf` files work as-is. Non-standard or exotic directives are ignored gracefully — see [Unbound compatibility](docs/unbound-migration.md). Runbound adds a live REST API, AF_XDP kernel-bypass, and a browser dashboard on top.\n\n---\n\n## What you get\n\n| | BIND9 | Unbound | Runbound |\n|---|:---:|:---:|:---:|\n| Drop-in Unbound config | ❌ | ✅ | ✅ |\n| UDP / TCP / DoT / DoH | ✅ | ✅ | ✅ |\n| Add / block domains live | ⚠️ | ❌ restart | ✅ API |\n| Block-list feed subscriptions | ⚠️ | ❌ manual | ✅ API |\n| Real-time stats + Prometheus | ✅ statistics channel (XML/JSON) | ❌ | ✅ |\n| Master/slave replication | ✅ | ❌ | ✅ built-in*¹ |\n| Automatic TLS (Let's Encrypt) | ❌ | ❌ | ✅ ACME |\n| Anycast deployment (built-in BGP announcer) | ❌ | ❌ | ✅ v0.19.0 |\n| AF/XDP kernel-bypass fast path | ❌ | ❌ | ✅ |\n| XDP ICMP echo responder (rate-limited) | ❌ | ❌ | ✅ |\n| Embedded browser dashboard | ❌ | ❌ | ✅ no nginx needed |\n| Linear scaling (no lock contention) | ❌ | ❌ | ✅ |\n| Static binary, no dependencies | ❌ | ❌ | ✅ musl |\n| Split-horizon DNS (per-subnet answers) | ❌ | ⚠️ views | ✅ v0.9.63 |\n| RBAC (read/dns/operator/admin roles) | ❌ | ❌ | ✅ v0.9.62 |\n| Webhook notifications (Slack/Discord/ntfy) | ❌ | ❌ | ✅ v0.9.58 |\n| Multi-user API with zone isolation | ❌ | ❌ | ✅ v0.9.51 |\n| White-label UI branding | ❌ | ❌ | ✅ v0.9.61 |\n| Hot backup / restore | ❌ | ❌ | ✅ API |\n\n*¹ Runbound ships both REST API-driven replication and standard AXFR/IXFR zone transfers (RFC 5936, v0.9.13+). AXFR requires explicit ACL configuration — see [docs/configuration.md](docs/configuration.md).\n\n---\n\n## Install\n\n### Requirements\n\n- Linux x86\\_64 or arm64\n- systemd\n- Port 53 available (stop `unbound`, `bind9`, `dnsmasq` or `systemd-resolved` first if running)\n- `curl` or `wget`\n- Root access (`sudo`)\n\n### One-line install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/redlemonbe/Runbound/main/install.sh | sudo bash\n```\n\nThat's it. The script:\n1. Downloads the latest binary for your architecture\n2. Creates a `runbound` system user\n3. Writes a default config to `/etc/runbound/runbound.conf`\n4. Generates a random API key in `/etc/runbound/env`\n5. Installs and starts the systemd service\n\nSee **[docs/INSTALL.md](docs/INSTALL.md)** for every option (`--uninstall`, `--purge`, `--help`), integrity verification (SHA256 + minisign), file locations and troubleshooting.\n\nAt the end you'll see:\n\n```\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n Version:  runbound \u003cversion\u003e\n API key:  a1b2c3d4...   ← save this\n Config:   /etc/runbound/runbound.conf\n Logs:     journalctl -u runbound -f\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n```\n\n**Save the API key** — you'll need it to use the dashboard and the REST API.\n\n### Verify it works\n\n```bash\n# DNS is responding\ndig @127.0.0.1 google.com\n\n# Service status\nsudo systemctl status runbound\n\n# API is up\ncurl -s http://127.0.0.1:8080/api/stats \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" | python3 -m json.tool\n```\n\n### Stop conflicting services first (if needed)\n\nIf port 53 is already taken:\n\n```bash\n# Check what's using port 53\nsudo ss -tlnp | grep :53\n\n# Common culprits\nsudo systemctl stop unbound        # Unbound\nsudo systemctl stop bind9          # BIND9\nsudo systemctl stop dnsmasq        # dnsmasq\nsudo systemctl disable systemd-resolved \u0026\u0026 sudo systemctl stop systemd-resolved  # systemd-resolved\n```\n\nThen re-run the install command.\n\n### Uninstall\n\n```bash\n# Remove Runbound, keep your config and data\ncurl -fsSL https://raw.githubusercontent.com/redlemonbe/Runbound/main/install.sh | sudo bash -s -- --uninstall\n\n# Remove everything: config, data, and the runbound user/group\ncurl -fsSL https://raw.githubusercontent.com/redlemonbe/Runbound/main/install.sh | sudo bash -s -- --purge\n```\n\n`--uninstall` keeps your config and data in `/etc/runbound` and `/var/lib/runbound`; `--purge` deletes them (and the `runbound` system user/group) as well.\n\n---\n\n## Dashboard (Web UI)\n\nRunbound embeds the dashboard — no nginx needed. Enable it in your config:\n\n```\nserver:\n    ui-enabled: yes\n    ui-port:    8091\n```\n\nRestart the service, then open `https://YOUR_SERVER_IP:8091`.\n\nOn first access your browser will warn about the self-signed certificate. Download the Runbound CA at `https://YOUR_SERVER_IP:8091/webui/ca.crt` and install it once — no more warnings on any device on your network.\n\nEnter your API key and click **Connect**. Full setup guide: [docs/web-ui.md](docs/web-ui.md).\n\n---\n\n## Manage DNS without touching a file\n\n```bash\nTOKEN=\"your-api-key\"\n\n# Add a local DNS entry — live, no restart\ncurl -s -X POST http://localhost:8080/api/dns \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"nas.home.\",\"type\":\"A\",\"value\":\"192.168.1.10\",\"ttl\":300}'\n\n# Block a domain\ncurl -s -X POST http://localhost:8080/api/blacklist \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\":\"ads.example.com\"}'\n\n# Subscribe to a block-list feed (auto-refreshed)\ncurl -s -X POST http://localhost:8080/api/feeds \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"urlhaus\",\"url\":\"https://urlhaus.abuse.ch/downloads/hostfile/\"}'\n```\n\n---\n\n## Performance\n\nBenchmarked under a documented, reproducible methodology — **the truth is the receiver\nNIC hardware counters** (`tx_packets`), warm cache, governor pinned, flow-control off,\nnever the generator's self-report. Full per-run reports: [docs/benchmark/](docs/benchmark/).\nRig (2026-06-13): AMD Threadripper PRO 5995WX receiver, dual Xeon E5-2690 v2 generator\n(dnsmark), direct 10 GbE DACs (Intel X710/i40e + X510/ixgbe).\n\n| Runbound v0.18.1 | Served (receiver NIC) | Receiver CPU | Limited by |\n|---|---|---|---|\n| `xdp: yes` — **dual-link** (X510 + X710) | **~20.28 M qps** | ~24 % | the two 10 G links — **server not saturated** |\n| `xdp: yes` — single link (X710) | ~10.1 M qps | ~11 % | 10 G link (response direction) |\n| `xdp: no` — kernel slow path (X710) | ~3.71 M qps | ~19 % | kernel-UDP RX + generator |\n\nIn no run did Runbound reach its own CPU ceiling (≤24 %); the limit is always the link, the\nNIC RX path, or the generator. Same-rig kernel-UDP reference resolvers: **unbound 1.22.0\n~2.09 M**, **BIND 9.20.23 ~1.84 M** — Runbound's slow path ~2×, its fast path ~5–6×, at\nlower CPU and lower latency. ~20.28 M qps ≈ **1.75 trillion queries/day** on a single node,\nthe order of a large public resolver's average load. Latency, the generator-bound\ndual-X710 run, and full context: [docs/benchmark/INDEX.md](docs/benchmark/INDEX.md).\n\nThe fast path is **self-configuring**: AF_XDP ring sizes are derived from the NIC\nhardware, huge pages are self-provisioned, and NIC queues scale to the CPU\nautomatically (kept at the driver default on bus-bound Xeon v2 + X520). The\narchitecture targets linear scaling — `SO_REUSEPORT`, `ArcSwap` lock-free config,\nper-core affinity, and a single-lookup ASM hot path (CRC32c + SIMD).\n\n## AF/XDP Fast Path\n\nAn eBPF XDP program attaches to the NIC at startup. UDP/53 packets for local zones and cache hits are answered in user space at driver level — zero syscalls on the hot path. All other queries pass through to the normal resolver via `XDP_PASS`.\n\nNegative answers (`NODATA` / `NXDOMAIN`) are cached on the fast path too (RFC 2308). AF_XDP ring sizes, huge pages, and NIC queue counts are **configured automatically** at startup — see [docs/xdp.md](docs/xdp.md).\n\n```bash\n# Verify XDP is active\njournalctl -u runbound | grep XDP\n```\n\nDisable without editing config: `RUNBOUND_DISABLE_XDP=1` — useful if the host becomes unreachable after an XDP attach. Details: [docs/xdp.md](docs/xdp.md).\n\n---\n\n## Documentation\n\nFull index: **[docs/index.md](docs/index.md)**\n\nQuick links: [Quick Start](docs/quick-start.md) · [Configuration](docs/configuration.md) · [REST API](docs/api.md) · [XDP](docs/xdp.md) · [Internals](docs/internals.md) · [Systemd](docs/systemd.md) · [Security Audit](docs/security-audit/SECURITY-AUDIT.md) · [Building \u0026 Verifying](docs/BUILD.md) · [Security Policy](SECURITY.md) · [Threat Model](THREAT_MODEL.md)\n\n---\n\n## Contributing\n\nCI (`.github/workflows/ci.yml`) runs on every push to `main` and every pull request — build, clippy and tests must all be green:\n\n```bash\ncargo build --release                       # xdp is in the default feature set\ncargo clippy --all-targets -- -D warnings   # must be warning-free\ncargo test                                  # all tests must pass\n```\n\nPull requests welcome. By submitting a PR you agree to the [CLA](CLA.md).\n\n---\n\n*Not affiliated with the NLnet Labs Unbound project.*\n\n---\n\n## Support the project\n\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/redlemonbe?style=flat\u0026logo=github\u0026label=Sponsor%20on%20GitHub)](https://github.com/sponsors/redlemonbe)\n\n**Bitcoin** — `3FP8hkkiu4kwCD1PDFgAv2oq1ZTyXwy3yy`  \n**Ethereum** — `0xB5eEAf89edA4204Aa9305B068b37A93439cBb680`\n\n---\n\n## License\n\nAGPL v3 — see [LICENSE](LICENSE). Commercial license available for organizations that need to deploy without AGPL obligations: [COMMERCIAL_LICENSE.md](COMMERCIAL_LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredlemonbe%2Frunbound","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredlemonbe%2Frunbound","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredlemonbe%2Frunbound/lists"}