Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
bindcar
Project Status
CI/CD Status
Code Quality
Technology & Compatibility
Security & Compliance
Community & Support
A lightweight HTTP REST API server for managing BIND9 zones via rndc commands.
Overview
bindcar runs as a sidecar container alongside BIND9, providing a REST interface for zone management operations. It executes rndc commands locally and manages zone files on a shared volume.
Features
- Zone management via REST API (create, delete, reload, status, modify)
- Individual DNS record management (add, update, remove records dynamically via nsupdate)
- DNSSEC support with BIND9 9.16+ policy integration and automatic inline signing
- IP-based rate limiting with configurable thresholds (GCRA algorithm)
- Kubernetes ServiceAccount token authentication with optional TokenReview validation
- Fine-grained access control (audience validation, namespace/SA allowlists)
- Health and readiness endpoints
- Prometheus metrics for monitoring
- Structured JSON logging
- Runs as non-root user with minimal permissions
Quick Start
Using Docker
Using Kubernetes
apiVersion: v1
kind: Pod
metadata:
name: bind9
spec:
containers:
- name: bind9
image: bind9:latest
volumeMounts:
- name: zones
mountPath: /var/cache/bind
- name: bindcar
image: ghcr.io/firestoned/bindcar:latest
ports:
- containerPort: 8080
volumeMounts:
- name: zones
mountPath: /var/cache/bind
volumes:
- name: zones
emptyDir:
Configuration
Environment variables:
BIND_ZONE_DIR- Directory for zone files (default:/var/cache/bind)API_PORT- API server port (default:8080)RNDC_SERVER- RNDC server address (default:127.0.0.1:953, or from/etc/bind/rndc.conf)RNDC_ALGORITHM- HMAC algorithm (default:sha256, or from/etc/bind/rndc.conf)RNDC_SECRET- Base64-encoded RNDC secret key (required if not using rndc.conf)NSUPDATE_SERVER- DNS server for nsupdate (default:127.0.0.1)NSUPDATE_PORT- DNS server port for nsupdate (default:53)NSUPDATE_KEY_NAME- TSIG key name for nsupdate (defaults to RNDC key)NSUPDATE_ALGORITHM- HMAC algorithm for nsupdate (defaults toRNDC_ALGORITHM)NSUPDATE_SECRET- Base64-encoded TSIG secret for nsupdate (defaults toRNDC_SECRET)RUST_LOG- Log level (default:info)BIND_API_ADDRESS- Interface to bind the API to (default:0.0.0.0)BIND_API_TOKEN- Shared secret; when set, the Bearer token must match it (constant-time)DISABLE_AUTH- Disable authentication (default:false)BINDCAR_ALLOW_INSECURE_AUTH- Override the startup guard for non-loopback weak/disabled auth (default:false)RATE_LIMIT_ENABLED- Enable rate limiting (default:true)RATE_LIMIT_REQUESTS- Max requests per period (default:100)RATE_LIMIT_PERIOD_SECS- Rate limit period in seconds (default:60)RATE_LIMIT_BURST- Burst size for rate limiting (default:10)
Note: rate limits are keyed on the real TCP peer IP, not the
X-Forwarded-For/X-Real-IP/Forwardedheaders (which a client can forge to evade the limit or exhaust another client's bucket). bindcar is reached directly by the operator's pods, so it must not run behind an untrusted proxy that rewrites the peer address.
RNDC Configuration
bindcar can be configured in two ways:
Option 1: Environment Variables
Option 2: Using rndc.conf
If RNDC_SECRET is not set, bindcar will automatically parse /etc/bind/rndc.conf or /etc/rndc.conf:
# /etc/bind/rndc.conf
key "rndc-key" {
algorithm hmac-sha256;
secret "dGVzdC1zZWNyZXQtaGVyZQ==";
};
options {
default-key "rndc-key";
default-server 127.0.0.1;
default-port 953;
};
The configuration also supports include directives for security-sensitive environments:
# /etc/bind/rndc.conf
include "/etc/bind/rndc.key";
options {
default-key "rndc-key";
default-server 127.0.0.1;
};
Authentication
By default, authentication is enabled and requires Bearer token authentication for all API endpoints except /health and /ready.
Authentication modes:
- Basic Mode (presence-only) - Validates token format only. ⚠️ This is not real authentication and bindcar will refuse to start in this mode on a non-loopback interface (see Startup guard below).
- Shared-secret Mode - Set
BIND_API_TOKEN; every request's Bearer token must equal it (compared in constant time). Real authentication without a Kubernetes API connection — suitable fordrone/bare-metal deployments. - TokenReview Mode (optional) - Full token validation with Kubernetes TokenReview API.
Startup guard (B-4)
bindcar refuses to start when the API is bound to a non-loopback interface without real
authentication, so a privileged API is never silently exposed. To start on 0.0.0.0 you must
satisfy one of:
- a real authenticator is configured —
BIND_API_TOKENis set, or the binary was built with thek8s-token-reviewfeature; or - the API is bound to loopback (
BIND_API_ADDRESS=127.0.0.1); or - the operator explicitly accepts the risk via
--i-know-this-is-insecure(orBINDCAR_ALLOW_INSECURE_AUTH=true).
TokenReview Mode provides enhanced security:
- Validates token signatures
- Checks token expiration
- Validates token audience
- Restricts to specific namespaces/ServiceAccounts
Enable TokenReview mode by building with the k8s-token-review feature and configuring environment variables:
env:
- name: BIND_TOKEN_AUDIENCES
value: "bindcar" # Required audience
- name: BIND_ALLOWED_NAMESPACES
value: "dns-system" # Allowed namespaces (empty = all)
- name: BIND_ALLOWED_SERVICE_ACCOUNTS
value: "system:serviceaccount:dns-system:external-dns" # Allowed SAs (empty = all)
To disable authentication (e.g., when using a service mesh like Linkerd):
# Docker
# Kubernetes
WARNING: Disabling authentication should ONLY be done in trusted environments where authentication is handled by infrastructure (Linkerd service mesh, API gateway, etc.). Never disable authentication in production without proper network-level security controls.
Because of the startup guard, DISABLE_AUTH=true on a non-loopback bind also requires
--i-know-this-is-insecure (or BINDCAR_ALLOW_INSECURE_AUTH=true) — an explicit
acknowledgement that you are relying on infrastructure-level controls.
For defense-in-depth, the deploy/ directory ships:
deploy/networkpolicy.yaml— restricts the API (ingress) to the bindy operator.deploy/rbac.yaml— least-privilege RBAC (onlysystem:auth-delegatorfor TokenReview).deploy/pod-hardening.yaml— pod/containersecurityContextreference (drop all caps, read-only rootfs, non-root, no token auto-mount) plus an egress NetworkPolicy.
See Kubernetes TokenReview Validation for detailed configuration.
API Endpoints
Health & Metrics
GET /api/v1/health- Health checkGET /api/v1/ready- Readiness checkGET /metrics- Prometheus metrics (no auth required)
Server Status
GET /api/v1/server/status- BIND9 server status
Zone Management
POST /api/v1/zones- Create zoneGET /api/v1/zones- List zonesGET /api/v1/zones/{name}- Get zone infoDELETE /api/v1/zones/{name}- Delete zonePOST /api/v1/zones/{name}/reload- Reload zoneGET /api/v1/zones/{name}/status- Zone statusPOST /api/v1/zones/{name}/freeze- Freeze zonePOST /api/v1/zones/{name}/thaw- Thaw zonePOST /api/v1/zones/{name}/notify- Notify secondaries
DNS Record Management
POST /api/v1/zones/{name}/records- Add individual recordDELETE /api/v1/zones/{name}/records- Remove individual recordPUT /api/v1/zones/{name}/records- Update individual record
Documentation
Full documentation is available at: https://firestoned.github.io/bindcar
- Getting Started
- API Reference
- Managing DNS Records
- Record Endpoints API
- Configuration Guide
- Deployment
Or build locally:
Development
# Build
# Test
# Run locally
RUST_LOG=debug
# Build docs
License
MIT - Copyright (c) 2025 Erick Bourgeois, firestoned