# dns-update-lite
[](https://crates.io/crates/dns-update-lite)
[](https://docs.rs/dns-update-lite)
[](http://www.apache.org/licenses/LICENSE-2.0)
_dns-update-lite_ is an **Dynamic DNS update library** for Rust that supports updating DNS records using the [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136) protocol
and few cloud, registrar, and self-hosted DNS provider APIs. It was designed to be simple and easy to use, while providing a high level of flexibility and performance.
Based on [dns-update](https://github.com/stalwartlabs/dns-update), being trimmed down.
## Supported providers
| [RFC 2136](https://datatracker.ietf.org/doc/html/rfc2136) | `new_rfc2136_tsig` | TSIG authentication |
| [Bunny DNS](https://bunny.net/dns/) | `new_bunny` | |
| [Cloudflare](https://www.cloudflare.com/) | `new_cloudflare` | API token or X-Auth-* |
| [deSEC](https://desec.io/) | `new_desec` | |
| [DigitalOcean](https://www.digitalocean.com/products/networking/dns) | `new_digitalocean` | |
| [DNSimple](https://dnsimple.com/) | `new_dnsimple` | |
| [Google Cloud DNS](https://cloud.google.com/dns) | `new_google_cloud_dns` | Service account JWT |
| [OVH](https://www.ovh.com/) | `new_ovh` | |
| [Porkbun](https://porkbun.com/) | `new_porkbun` | |
| [AWS Route 53](https://aws.amazon.com/route53/) | `new_route53` | AWS Sigv4 |
| [Spaceship](https://www.spaceship.com/) | `new_spaceship` | |
## API
Every provider exposes three RRSet-oriented methods on `DnsUpdater`. All three operate on the full RRSet at `(name, type)` and are idempotent.
```rust,ignore
async fn set_rrset(name, type, ttl, records: Vec<DnsRecord>, origin) -> Result<()>
async fn add_to_rrset(name, type, ttl, records: Vec<DnsRecord>, origin) -> Result<()>
async fn remove_from_rrset(name, type, records: Vec<DnsRecord>, origin) -> Result<()>
```
- `set_rrset` replaces the RRSet at `(name, type)` with exactly `records`.
An empty `Vec` deletes the RRSet. Other types at the same owner are
never touched.
- `add_to_rrset` ensures `records` are present at the owner without
removing anything else.
- `remove_from_rrset` removes only the listed values; other values at the
same owner are preserved.
## Usage Example
Publishing a TXT record using RFC 2136 over TSIG:
```rust,ignore
let client = DnsUpdater::new_rfc2136_tsig(
"tcp://127.0.0.1:53",
"<KEY_NAME>",
STANDARD.decode("<TSIG_KEY>").unwrap(),
TsigAlgorithm::HmacSha512,
)
.unwrap();
// Publish the entire RRSet at this owner in one atomic operation. Empty
// Vec deletes the RRSet. Rerunning with the same input is a no-op.
client
.set_rrset(
"test._domainkey.example.org",
DnsRecordType::TXT,
300,
vec![DnsRecord::TXT("v=DKIM1; k=rsa; h=sha256; p=test".to_string())],
"example.org",
)
.await
.unwrap();
// Delete the RRSet.
client
.set_rrset(
"test._domainkey.example.org",
DnsRecordType::TXT,
0,
vec![],
"example.org",
)
.await
.unwrap();
```
`add_to_rrset` is for "publish this value alongside whatever else is there"
(e.g. an ACME challenge token that should coexist with the user's DKIM/SPF
TXTs at the same owner):
```rust,ignore
client
.add_to_rrset(
"_acme-challenge.example.org",
DnsRecordType::TXT,
60,
vec![DnsRecord::TXT("challenge-token".to_string())],
"example.org",
)
.await
.unwrap();
client
.remove_from_rrset(
"_acme-challenge.example.org",
DnsRecordType::TXT,
vec![DnsRecord::TXT("challenge-token".to_string())],
"example.org",
)
.await
.unwrap();
```
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Copyright
Copyright (C) 2020, Stalwart Labs LLC
Copyright (C) 2026, Ferron