A lightweight REST API for managing static DHCP/DNS entries on a dnsmasq server.
Instead of hand-editing dnsmasq configuration files, dnsmasq-manager exposes a simple HTTP API so that other tools, scripts, or dashboards can manage static leases programmatically — no SSH required.
- Manage static DHCP host reservations — add, list, update, and delete
- Query hosts by MAC address or IP address
- JWT authentication with multiple algorithm support (ECDSA, RSA, HMAC)
- Role-scoped authorization (
dhcp:read,dhcp:add,dhcp:change,dhcp:admin) - Interactive OpenAPI / Swagger UI included out of the box
- Structured JSON or plain-text logging with configurable severity level
- Systemd service unit with a hardened security profile
- Multi-architecture Linux packages:
.deb,.rpm,.apk, ArchLinux
- Linux system with systemd
- dnsmasq installed and managing
/etc/dnsmasq.d/ - Go 1.24+ (source builds only)
Download the package for your distribution from the latest release.
Debian / Ubuntu
wget https://github.com/gringolito/dnsmasq-manager/releases/latest/download/dnsmasq-manager_<version>_amd64.deb
sudo dpkg -i dnsmasq-manager_<version>_amd64.debRHEL / Fedora
sudo rpm -i dnsmasq-manager_<version>_amd64.rpmAlpine
sudo apk add --allow-untrusted dnsmasq-manager_<version>_amd64.apkPackages for arm, arm64, armv5/6/7, and i386 are also available on the releases page.
wget https://github.com/gringolito/dnsmasq-manager/releases/latest/download/dnsmasq-manager_Linux_x86_64.tar.gz
tar -xzf dnsmasq-manager_Linux_x86_64.tar.gz
sudo mv dnsmasq-manager /usr/local/bin/git clone https://github.com/gringolito/dnsmasq-manager
cd dnsmasq-manager
go build -tags=release -o dnsmasq-manager .The configuration file is located at /etc/dnsmasq-manager/config.yaml (installed automatically by the package). A fully annotated template is provided at config.yaml.dist.
All settings have sensible defaults, so the service works out of the box with no changes required. Uncomment and adjust only what you need:
# /etc/dnsmasq-manager/config.yaml
# Path to the dnsmasq static DHCP leases file.
# Default: /etc/dnsmasq.d/04-dhcp-static-leases.conf
#
# host:
# static:
# file: /etc/dnsmasq.d/04-dhcp-static-leases.conf
# JWT-based authentication for API endpoints.
# Available methods: none, ecdsa-256, ecdsa-384, ecdsa-512,
# hmac-256, hmac-384, hmac-512,
# rsa-256, rsa-384, rsa-512
# The key can be a file path (ECDSA/RSA public key) or a plain-text secret (HMAC).
# Default: no authentication
#
# auth:
# method: ecdsa-512
# key: /etc/dnsmasq-manager/id_ecdsa.pub
# HTTP listening port.
# Default: 6904
#
# server:
# port: 6904
# Logging settings.
# Available levels: debug, info, warning, error
# Available formats: json, text
# Default: info / json / stdout
#
# log:
# level: info
# format: json
# file: /var/log/dnsmasq-manager.log
# source: falseEvery configuration key can be overridden with an environment variable using the DMM_ prefix and underscores for nesting:
| Variable | Default | Description |
|---|---|---|
DMM_SERVER_PORT |
6904 |
HTTP listening port |
DMM_AUTH_METHOD |
none |
JWT algorithm |
DMM_AUTH_KEY |
— | JWT key path or secret |
DMM_LOG_LEVEL |
info |
Log verbosity |
DMM_LOG_FORMAT |
json |
Log output format |
DMM_LOG_FILE |
— | Log file path (stdout if empty) |
The package ships with a key generation helper:
# Generate an ECDSA-512 key pair in the current directory
generate-jwt-keys ecdsa-512Point the auth.key config option at the generated public key file, then issue JWTs signed with the corresponding private key. Include the appropriate scope claim (dhcp:read, dhcp:add, dhcp:change, or dhcp:admin) to control what each token can do.
sudo systemctl enable --now dnsmasq-managerCheck the service status and logs:
sudo systemctl status dnsmasq-manager
sudo journalctl -u dnsmasq-manager -fList all static hosts
curl http://localhost:6904/api/v1/static/hostsWith JWT authentication
TOKEN="<your-jwt>"
curl -H "Authorization: Bearer $TOKEN" http://localhost:6904/api/v1/static/hostsGet a specific host by MAC address
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:6904/api/v1/static/host?mac=aa:bb:cc:dd:ee:ff"Add a static host
curl -X POST http://localhost:6904/api/v1/static/host \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"MacAddress":"aa:bb:cc:dd:ee:ff","IPAddress":"192.168.1.100","HostName":"mydevice"}'Update a static host
curl -X PUT http://localhost:6904/api/v1/static/host \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"MacAddress":"aa:bb:cc:dd:ee:ff","IPAddress":"192.168.1.101","HostName":"mydevice"}'Delete a host
curl -X DELETE -H "Authorization: Bearer $TOKEN" \
"http://localhost:6904/api/v1/static/host?mac=aa:bb:cc:dd:ee:ff"Full interactive API documentation is available at:
http://<host>:6904/openapi/swagger-ui
| Method | Path | Required scope | Description |
|---|---|---|---|
GET |
/api/v1/static/hosts |
dhcp:read |
List all static hosts |
GET |
/api/v1/static/host?mac= | ?ip= |
dhcp:read |
Get a host by MAC or IP |
POST |
/api/v1/static/host |
dhcp:add |
Add a new static host |
PUT |
/api/v1/static/host |
dhcp:change |
Update an existing host |
DELETE |
/api/v1/static/host?mac= | ?ip= |
dhcp:change |
Remove a host |
GET |
/metrics |
— | Server metrics |
The raw OpenAPI spec is served at /openapi/spec.
- Static DHCP host management (add, list, update, delete)
- JWT authentication and role-based authorization
- Configurable via YAML and environment variables
- Structured logging
- Systemd service with hardened security profile
- OpenAPI / Swagger documentation
- Unit tests
- Multi-architecture Linux packages (
.deb,.rpm,.apk, ArchLinux)
- Static DNS entry management
- CNAME alias management
Contributions are welcome and appreciated. Here are a few ways to get involved:
- Found a bug? Open an issue with as much detail as possible — steps to reproduce, expected vs. actual behavior, and your environment.
- Have a feature idea? Start a discussion via an issue before writing code, so we can align on the approach.
- Want to submit a fix or improvement? Fork the repo, make your changes, and open a pull request. Please include tests for any new behavior and keep the scope focused.
The Beer-Ware License — do whatever you want with this. If we ever meet and you think it was worth it, buy me a beer. 🍺