# Environment Variables
Complete reference of all environment variables used by bindcar.
## Core Variables
### BIND_ZONE_DIR
- **Type**: String (path)
- **Default**: `/var/cache/bind`
- **Required**: No
- **Description**: Directory where BIND9 zone files are stored
```bash
BIND_ZONE_DIR=/var/cache/bind
```
Must be:
- Readable and writable by the bindcar user (UID 101)
- Shared between bindcar and BIND9 containers
- An existing directory
### API_PORT
- **Type**: Integer
- **Default**: `8080`
- **Required**: No
- **Description**: Port for the HTTP API server
```bash
API_PORT=8080
```
Valid range: 1-65535
### RNDC_SERVER
- **Type**: String (address:port)
- **Default**: `127.0.0.1:953` (or from `/etc/bind/rndc.conf`)
- **Required**: No
- **Description**: RNDC server address and port
```bash
RNDC_SERVER=127.0.0.1:953
```
### RNDC_ALGORITHM
- **Type**: String
- **Default**: `sha256` (or from `/etc/bind/rndc.conf`)
- **Required**: No
- **Description**: HMAC algorithm for RNDC authentication
```bash
RNDC_ALGORITHM=sha256
```
Valid values:
- `md5` (or `hmac-md5`)
- `sha1` (or `hmac-sha1`)
- `sha224` (or `hmac-sha224`)
- `sha256` (or `hmac-sha256`)
- `sha384` (or `hmac-sha384`)
- `sha512` (or `hmac-sha512`)
Both formats (with or without `hmac-` prefix) are accepted.
### RNDC_SECRET
- **Type**: String (base64-encoded)
- **Default**: None (read from `/etc/bind/rndc.conf` or `/etc/rndc.conf`)
- **Required**: Only if not using rndc.conf
- **Description**: Base64-encoded RNDC secret key
```bash
RNDC_SECRET=dGVzdC1zZWNyZXQtaGVyZQ==
```
**Note**: If `RNDC_SECRET` is not set, bindcar will automatically parse the RNDC configuration from `/etc/bind/rndc.conf` or `/etc/rndc.conf`, including any `include` directives for separate key files.
The secret must be:
- Base64-encoded
- Match the key configured in BIND9's `rndc.conf`
## nsupdate Variables
These variables configure the nsupdate executor for dynamic DNS record updates. If not set, bindcar automatically falls back to using RNDC credentials.
### NSUPDATE_KEY_NAME
- **Type**: String
- **Default**: Falls back to RNDC key name
- **Required**: No
- **Description**: TSIG key name for nsupdate authentication
```bash
NSUPDATE_KEY_NAME=update-key
```
This should match the key name in your zone's `allow-update` directive.
### NSUPDATE_ALGORITHM
- **Type**: String
- **Default**: Falls back to `RNDC_ALGORITHM`
- **Required**: No
- **Description**: HMAC algorithm for TSIG authentication
```bash
NSUPDATE_ALGORITHM=HMAC-SHA256
```
Valid values (same as RNDC):
- `md5` (or `hmac-md5` or `HMAC-MD5`)
- `sha1` (or `hmac-sha1` or `HMAC-SHA1`)
- `sha224` (or `hmac-sha224` or `HMAC-SHA224`)
- `sha256` (or `hmac-sha256` or `HMAC-SHA256`)
- `sha384` (or `hmac-sha384` or `HMAC-SHA384`)
- `sha512` (or `hmac-sha512` or `HMAC-SHA512`)
### NSUPDATE_SECRET
- **Type**: String (base64-encoded)
- **Default**: Falls back to `RNDC_SECRET`
- **Required**: No
- **Description**: Base64-encoded TSIG secret for nsupdate
```bash
NSUPDATE_SECRET=dGVzdC1zZWNyZXQtaGVyZQ==
```
Must be:
- Base64-encoded
- Match the key configured in BIND9's zone `allow-update` directive
### NSUPDATE_SERVER
- **Type**: String (IP address)
- **Default**: `127.0.0.1`
- **Required**: No
- **Description**: DNS server address for nsupdate commands
```bash
NSUPDATE_SERVER=127.0.0.1
```
Typically localhost when running as a sidecar.
### NSUPDATE_PORT
- **Type**: Integer
- **Default**: `53`
- **Required**: No
- **Description**: DNS server port for nsupdate commands
```bash
NSUPDATE_PORT=53
```
### Example Configurations
**Using separate keys (recommended for security)**:
```bash
# RNDC for zone management
RNDC_SECRET=rndc-key-secret-here
RNDC_ALGORITHM=sha256
# nsupdate for record updates (different key)
NSUPDATE_KEY_NAME=update-key
NSUPDATE_SECRET=update-key-secret-here
NSUPDATE_ALGORITHM=HMAC-SHA256
```
**Using same key (simpler setup)**:
```bash
# Set RNDC vars only - nsupdate automatically uses them
RNDC_SECRET=shared-key-secret-here
RNDC_ALGORITHM=sha256
# nsupdate will use RNDC credentials automatically
```
## Logging Variables
### RUST_LOG
- **Type**: String (log level)
- **Default**: `info`
- **Required**: No
- **Description**: Log level for the application
```bash
RUST_LOG=info
```
Valid values:
- `error` - Only error messages
- `warn` - Warnings and errors
- `info` - Informational messages, warnings, and errors
- `debug` - Debug information
- `trace` - Very detailed trace information
Can also be module-specific:
```bash
RUST_LOG=bindcar=debug,tower_http=info
```
## Security Variables
### DISABLE_AUTH
- **Type**: Boolean
- **Default**: `false`
- **Required**: No
- **Description**: Disable Bearer token authentication
```bash
DISABLE_AUTH=false
```
Valid values:
- `true` - Disable authentication (USE ONLY IN TRUSTED ENVIRONMENTS)
- `false` - Enable authentication (recommended)
**WARNING**: Setting this to `true` disables all authentication. Only use in environments where authentication is handled by infrastructure (Linkerd service mesh, API gateway, etc.).
### BIND_TOKEN_AUDIENCES
- **Type**: String (comma-separated)
- **Default**: `bindcar`
- **Required**: No (only when `k8s-token-review` feature enabled)
- **Description**: Expected token audiences for TokenReview validation
```bash
BIND_TOKEN_AUDIENCES=bindcar,https://bindcar.dns-system.svc.cluster.local
```
Prevents token reuse across different services. Tokens must be created with matching audience:
```bash
kubectl create token my-app --audience=bindcar
```
### BIND_ALLOWED_NAMESPACES
- **Type**: String (comma-separated)
- **Default**: None (allow all)
- **Required**: No (only when `k8s-token-review` feature enabled)
- **Description**: Allowed Kubernetes namespaces for token authentication
```bash
BIND_ALLOWED_NAMESPACES=dns-system,kube-system
```
Empty value allows all namespaces (default). When set, only tokens from specified namespaces are accepted.
### BIND_ALLOWED_SERVICE_ACCOUNTS
- **Type**: String (comma-separated)
- **Default**: None (allow all)
- **Required**: No (only when `k8s-token-review` feature enabled)
- **Description**: Allowed ServiceAccounts for token authentication
```bash
BIND_ALLOWED_SERVICE_ACCOUNTS=system:serviceaccount:dns-system:external-dns,system:serviceaccount:dns-system:cert-manager
```
Format: `system:serviceaccount:<namespace>:<name>`
Empty value allows all ServiceAccounts (default). When set, only specified ServiceAccounts are accepted.
## Rate Limiting Variables
### RATE_LIMIT_ENABLED
- **Type**: Boolean
- **Default**: `true`
- **Required**: No
- **Description**: Enable or disable rate limiting
```bash
RATE_LIMIT_ENABLED=true
```
Valid values:
- `true` - Enable rate limiting (recommended)
- `false` - Disable rate limiting (USE ONLY IN TRUSTED ENVIRONMENTS)
Rate limiting helps protect the API from abuse and ensures fair resource allocation across clients.
### RATE_LIMIT_REQUESTS
- **Type**: Integer
- **Default**: `100`
- **Required**: No
- **Description**: Maximum number of requests allowed per time period
```bash
RATE_LIMIT_REQUESTS=100
```
This value represents the total number of requests a client can make within the time period defined by `RATE_LIMIT_PERIOD_SECS`.
Valid range: 1-4,294,967,295 (must be greater than 0)
### RATE_LIMIT_PERIOD_SECS
- **Type**: Integer
- **Default**: `60`
- **Required**: No
- **Description**: Time period in seconds for rate limit calculation
```bash
RATE_LIMIT_PERIOD_SECS=60
```
Combined with `RATE_LIMIT_REQUESTS`, this defines the rate limit. For example:
- `RATE_LIMIT_REQUESTS=100` + `RATE_LIMIT_PERIOD_SECS=60` = 100 requests per minute
- `RATE_LIMIT_REQUESTS=1000` + `RATE_LIMIT_PERIOD_SECS=3600` = 1000 requests per hour
Valid range: 1-4,294,967,295 (must be greater than 0)
### RATE_LIMIT_BURST
- **Type**: Integer
- **Default**: `10`
- **Required**: No
- **Description**: Maximum burst size for rate limiting
```bash
RATE_LIMIT_BURST=10
```
The burst size allows clients to temporarily exceed the steady-state rate limit. This accommodates legitimate traffic spikes without penalizing normal usage patterns.
For example, with a burst of 10, a client can make 10 requests immediately, then must wait according to the rate limit before making more requests.
Valid range: 1-4,294,967,295 (must be greater than 0)
**How Rate Limiting Works**:
bindcar uses the Generic Cell Rate Algorithm (GCRA) via the `tower-governor` crate, which provides sophisticated rate limiting based on client IP addresses.
**Client IP Detection** (in order of precedence):
1. `X-Forwarded-For` header (first IP)
2. `X-Real-IP` header
3. Peer socket address
This ensures proper rate limiting when bindcar is deployed behind reverse proxies like Linkerd.
**Rate Limit Responses**:
When a client exceeds the rate limit:
- HTTP Status: `429 Too Many Requests`
- Response Body: `Rate limit exceeded. Please try again later.`
- Metrics: Tracked via `bindcar_rate_limit_requests_total{result="rejected"}`
**Example Configurations**:
Permissive (development):
```bash
RATE_LIMIT_REQUESTS=1000
RATE_LIMIT_PERIOD_SECS=60
RATE_LIMIT_BURST=50
```
Standard (production):
```bash
RATE_LIMIT_REQUESTS=100
RATE_LIMIT_PERIOD_SECS=60
RATE_LIMIT_BURST=10
```
Strict (high-security):
```bash
RATE_LIMIT_REQUESTS=30
RATE_LIMIT_PERIOD_SECS=60
RATE_LIMIT_BURST=5
```
Disabled (trusted environment only):
```bash
RATE_LIMIT_ENABLED=false
```
## Environment Variable Precedence
1. Explicit environment variables (highest priority)
2. Default values (lowest priority)
## Validation
bindcar validates all environment variables on startup:
- Path variables must point to existing, accessible locations
- Port numbers must be valid (1-65535)
- Log levels must be recognized values
Invalid configuration will cause bindcar to exit with an error message.
## Examples
### Development
```bash
export RUST_LOG=debug
export BIND_ZONE_DIR=./zones
export API_PORT=3000
export DISABLE_AUTH=true
```
### Production (Docker)
```bash
docker run -d \
-e BIND_ZONE_DIR=/var/cache/bind \
-e API_PORT=8080 \
-e RUST_LOG=info \
-e RNDC_SERVER=127.0.0.1:953 \
-e RNDC_ALGORITHM=sha256 \
-e RNDC_SECRET=dGVzdC1zZWNyZXQtaGVyZQ== \
-e DISABLE_AUTH=false \
ghcr.io/firestoned/bindcar:latest
```
### Kubernetes (Basic Auth)
```yaml
env:
- name: BIND_ZONE_DIR
value: "/var/cache/bind"
- name: API_PORT
value: "8080"
- name: RUST_LOG
value: "info"
- name: RNDC_SERVER
value: "127.0.0.1:953"
- name: RNDC_ALGORITHM
value: "sha256"
- name: RNDC_SECRET
valueFrom:
secretKeyRef:
name: rndc-secret
key: secret
- name: DISABLE_AUTH
value: "false"
```
### Kubernetes (TokenReview Mode - Production)
```yaml
env:
- name: BIND_ZONE_DIR
value: "/var/cache/bind"
- name: API_PORT
value: "8080"
- name: RUST_LOG
value: "info"
- name: RNDC_SERVER
value: "127.0.0.1:953"
- name: RNDC_ALGORITHM
value: "sha256"
- name: RNDC_SECRET
valueFrom:
secretKeyRef:
name: rndc-secret
key: secret
- name: DISABLE_AUTH
value: "false"
# TokenReview security configuration
- name: BIND_TOKEN_AUDIENCES
value: "bindcar,https://bindcar.dns-system.svc.cluster.local"
- name: BIND_ALLOWED_NAMESPACES
value: "dns-system"
- name: BIND_ALLOWED_SERVICE_ACCOUNTS
value: "system:serviceaccount:dns-system:external-dns"
```
## Best Practices
1. **Use defaults where possible** - Only override when necessary
2. **Store secrets securely** - Use Kubernetes Secrets or similar for sensitive values
3. **Use appropriate log levels** - `info` for production, `debug` for troubleshooting
4. **Don't disable authentication** - Unless absolutely necessary and in trusted environments
5. **Validate paths exist** - Ensure directories and binaries exist before starting
## Next Steps
- [Configuration](./configuration.md) - Configuration overview
- [Authentication](./authentication.md) - Authentication setup
- [Deployment](./deployment.md) - Deployment guides