> For the complete documentation index, see [llms.txt](https://docs.nf.domains/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nf.domains/platform/manage/native-dns-for-nfds.md).

# Native DNS for NFDs

## Introduction

With the release of DNS support in NFD on Algorand, you can now bind globally-resolvable DNS records to your .algo name—served directly from the Algorand blockchain. Through integration with the `.algo.xyz` TLD, names like `somedapp.algo` become `somedapp.algo.xyz`—and can be accessed via any DNS client, browser, or application worldwide.

**Your NFD becomes a real, working domain:**

* `patrick.algo.xyz` - accessible via standard DNS

This means you can point your NFD to a website, receive email, configure SSL certificates, and more—all with records you control on-chain.

This creates a true **Web3 DNS system** using **native DNS protocol standards**, while retaining:

* On-chain data control
* Self-custodial ownership
* Trustless resolution

***

## How It Works

```
1. You configure DNS records in your NFD (stored on Algorand blockchain)
        ↓
2. The NFD DNS service reads your on-chain data
        ↓
3. Standard DNS queries resolve your NFD as a normal domain
```

When someone queries `patrick.algo.xyz`, the NFD DNS service fetches your records from the blockchain and returns a standard DNS response. No special software needed—it just works with any browser or application.

***

## Background: DNS and RR Types

DNS (Domain Name System) maps human-readable names to machine-usable data using **resource records (RRs)**. Common RR types include:

| Type    | Purpose                                        |
| ------- | ---------------------------------------------- |
| `A`     | IPv4 address of a host                         |
| `AAAA`  | IPv6 address                                   |
| `TXT`   | Free-form text (often used for verification)   |
| `MX`    | Mail server settings                           |
| `CNAME` | Canonical alias (points one domain to another) |
| `SRV`   | Advanced service routing                       |
| `CAA`   | Certification authority authorization          |

Traditionally, these records are stored and managed via centralized registrars or DNS providers. In contrast, NFDs allow **you** to define these records on-chain.

***

## Architecture

### Storage

Each NFD stores its DNS records in a `dns` property—structured JSON stored on-chain inside its associated Algorand smart contract. This property is:

* Versioned (requires NFD v3+)
* User-editable via the NFD Manager
* Strictly owned/controlled by the NFD's controlling account

### Ownership & Security

Ownership of DNS records is cryptographically enforced by the Algorand blockchain:

* You can use single-signature wallets, multisig accounts, or smart contract wallets to own NFDs.
* No third-party registrar required.
* Record changes are signed transactions.

This enables advanced workflows like:

* Smart contracts updating DNS records automatically.
* DAOs owning service domains like `community.algo`.
* Multisig-controlled dApp endpoints (e.g., `swap.algo.xyz`).

***

## DNS Record Format

DNS records are stored as JSON in your NFD. Each record has these fields:

| Field    | Required | Description                                        |
| -------- | -------- | -------------------------------------------------- |
| `name`   | Yes      | Where the record applies (use `@` for your domain) |
| `type`   | Yes      | Record type: A, AAAA, CNAME, MX, TXT, SRV, CAA     |
| `rrData` | Yes      | Array of record values                             |
| `ttl`    | No       | Cache time in seconds (default: 300)               |

### Name Field

* `@` — Your domain itself (e.g., `patrick.algo.xyz`)
* `www` — A subdomain (becomes `www.patrick.algo.xyz`)
* `mail` — Another subdomain (becomes `mail.patrick.algo.xyz`)
* `grafana` — A subdomain (becomes `grafana.patrick.algo.xyz`)
* `_dmarc` — Special subdomain for DMARC records

#### Accepted name forms

All of the following are accepted and resolve to the same place under your NFD (`patrick.algo`):

| You write              | It serves                 |
| ---------------------- | ------------------------- |
| `@`                    | `patrick.algo.xyz` (apex) |
| `www`                  | `www.patrick.algo.xyz`    |
| `www.@`                | `www.patrick.algo.xyz`    |
| `www.patrick.algo`     | `www.patrick.algo.xyz`    |
| `www.patrick.algo.`    | `www.patrick.algo.xyz`    |
| `www.patrick.algo.xyz` | `www.patrick.algo.xyz`    |

The `.@` suffix (e.g. `www.@`, `_dmarc.@`, `_http._tcp.@`) is the explicit canonical form—it states "this is a subname of my NFD." Bare labels like `www` work identically.

{% hint style="warning" %}
**Scope: every record name is rooted under your NFD.** You have DNS authority only over your own NFD and its subnames, so any `name` you store is interpreted as something *inside* your NFD's subtree.

A trailing dot in a standard DNS zone file means "fully qualified—don't append the origin." In NFD context that's almost always a mistake. To avoid this footgun, any name that isn't already inside your NFD's zone is **re-rooted** under it:

* `_test._tcp.` (trailing-dot, no NFD) → serves as `_test._tcp.patrick.algo.xyz`
* `evil.someone-else.algo.` (a *different* NFD) → serves as `evil.someone-else.algo.patrick.algo.xyz` (you do **not** gain authority over `someone-else.algo`)

When in doubt, use the `.@` suffix—it makes your intent explicit and is never re-rooted unexpectedly.
{% endhint %}

### TTL (Time to Live)

* **Minimum:** 60 seconds
* **Maximum:** 86,400 seconds (24 hours)
* **Default:** 300 seconds (5 minutes)

Lower TTL = faster updates, but more DNS queries. Higher TTL = better caching, but slower propagation of changes.

***

## Managing DNS Records in Your NFD

### Editing via UI

To add or modify DNS records:

1. Open the NFD Manager and select an NFD (version 3+).
2. Click **DNS Editor**.
3. Use "Add DNS Record":
   * **Type**: Choose one of the supported types (`A`, `AAAA`, `TXT`, etc.)
   * **Name**: Use `@` to represent the root of the NFD (e.g. `patrick.algo`)
   * **TTL**: Set time-to-live in seconds
   * **Value**: A string or list, depending on type (e.g. multiple IPs for an `A` record)

***

## How `.algo.xyz` Resolution Works

The `.algo.xyz` TLD is backed by [**nfd-coredns**](https://github.com/TxnLab/nfd-coredns), an open-source [CoreDNS](https://coredns.io/) plugin that resolves DNS queries for Algorand NFDs by reading on-chain data directly from the blockchain. When a DNS query arrives for a domain like `patrick.algo.xyz`, the plugin:

* Strips the `.xyz` suffix
* Checks a local cache for previously fetched records
* Queries the Algorand blockchain if needed
* Converts on-chain JSON data to standard DNS resource records
* Returns the response as a normal DNS reply

The resolver supports all NFD DNS record types (A, AAAA, CNAME, MX, TXT, SRV, CAA, NS, SOA, CERT) and honors TTL values.

### Run Your Own Resolver

Anyone can run their own NFD DNS resolver using the Docker image:

```bash
docker pull txnlab/nfd-dns:latest
```

See the [nfd-coredns GitHub repository](https://github.com/TxnLab/nfd-coredns) for configuration details and setup instructions.

### Live Resolvers

* `algo.xyz` zone is currently served by:
  * [TxnLab Resolver](https://txnlab.dev)
  * [Nodely Resolver](https://nodely.io)

***

## Subdomain and Delegation Model

Unlike traditional DNS, the NFD subdomain model **preserves segment ownership**. A *segment* (e.g. `api.patrick.algo`) is its own NFD with its own owner, and it **always serves its own DNS records**—regardless of who owns the root NFD. How a segment combines with the root depends on ownership. There are three cases:

1. **No segment NFD is minted** — the root NFD serves the subname directly. A record stored on `patrick.algo` with name `api` answers `api.patrick.algo.xyz`.
2. **Segment owned by the same account as the root** — the segment is **merged** with the root. The root can define sub-records that fall inside the segment, and **root records win** if both define the same name + type. This lets you manage a root NFD and the segments you own as one zone.
3. **Segment owned by a different account** — the segment alone is **authoritative** for its own subtree (`api.patrick.algo` and everything under it). The root NFD owner has no DNS authority inside it, and any root records pointing into the segment's subtree are **ignored**. This mirrors how segments are sold and operated independently.

This prevents parent domains from hijacking subdomain content they do not own.

{% hint style="info" %}
"Authoritative" here describes the *NFD-ownership* boundary, not a DNS delegation. The plugin still answers these names directly—there is no NS referral and no delegated subzone (NFD subdomains never have NS records; see [Limitations](#limitations) below).
{% endhint %}

### Resolution examples

The tables below assume a root NFD of `patrick.algo`. "Resolves to" is what a DNS query actually returns.

**Scenario A — no `api.patrick.algo` segment is minted (root serves the subname):**

| Query                    | Record on `patrick.algo` | Resolves to                         |
| ------------------------ | ------------------------ | ----------------------------------- |
| `patrick.algo.xyz` A     | `@` → `203.0.113.1`      | `203.0.113.1`                       |
| `www.patrick.algo.xyz` A | `www` → `203.0.113.2`    | `203.0.113.2`                       |
| `api.patrick.algo.xyz` A | `api` → `203.0.113.3`    | `203.0.113.3` (root serves subname) |
| `api.patrick.algo.xyz` A | *(no `api` record)*      | placeholder / NODATA                |

**Scenario B — `api.patrick.algo` is a segment owned by the&#x20;*****same*****&#x20;account as the root:**

| Query                        | `patrick.algo` defines | `api.patrick.algo` defines | Resolves to                            |
| ---------------------------- | ---------------------- | -------------------------- | -------------------------------------- |
| `api.patrick.algo.xyz` A     | `api` → `1.1.1.1`      | `@` → `2.2.2.2`            | `1.1.1.1` (root wins the conflict)     |
| `api.patrick.algo.xyz` AAAA  | *(none)*               | `@` → `2001:db8::1`        | `2001:db8::1` (segment merged in)      |
| `key.api.patrick.algo.xyz` A | *(none)*               | `key` → `3.3.3.3`          | `3.3.3.3` (segment serves its subname) |

**Scenario C — `api.patrick.algo` is a segment owned by a&#x20;*****different*****&#x20;account:**

| Query                        | `patrick.algo` defines | `api.patrick.algo` defines | Resolves to                                      |
| ---------------------------- | ---------------------- | -------------------------- | ------------------------------------------------ |
| `api.patrick.algo.xyz` A     | `api` → `1.1.1.1`      | `@` → `2.2.2.2`            | `2.2.2.2` (segment authoritative; root ignored)  |
| `key.api.patrick.algo.xyz` A | `key.api` → `1.1.1.1`  | `key` → `3.3.3.3`          | `3.3.3.3` (root has no authority inside segment) |
| `api.patrick.algo.xyz` A     | `api` → `1.1.1.1`      | *(no records)*             | placeholder (segment exists but empty)           |

***

## Bluesky Integration

If you've verified your Bluesky account with your NFD, a TXT record for `_atproto` is **automatically added**. You don't need to configure this manually.

The system creates:

```
_atproto.patrick.algo.xyz. TXT "did=did:plc:abc123..."
```

This enables your NFD to serve as your Bluesky handle.

***

## Decentralized Websites (IPFS via DNSLink)

You can point your NFD at content stored on IPFS — the same idea as ENS's on-chain `contenthash`, but done with a standard DNS record, so it works with existing IPFS gateways and needs no special support.

Add a TXT record at `_dnslink.@` whose value is a DNSLink path:

* `dnslink=/ipfs/<CID>` — an immutable snapshot (the content for that exact CID)
* `dnslink=/ipns/<name>` — a mutable pointer you can update without changing DNS

```json
{
  "name": "_dnslink.@",
  "type": "TXT",
  "rrData": ["\"dnslink=/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi\""],
  "ttl": 300
}
```

This serves:

```
_dnslink.patrick.algo.xyz. TXT "dnslink=/ipfs/bafybei..."
```

**Viewing it:** any IPFS gateway resolves it, e.g. `https://ipfs.io/ipns/patrick.algo.xyz/` or `https://dweb.link/ipns/patrick.algo.xyz/`. For direct browser access at `patrick.algo.xyz`, point your `@` record (A/CNAME) at a DNSLink-aware gateway (e.g. a self-hosted Kubo DNSLink gateway or Cloudflare's web3 gateway); the gateway reads the `_dnslink` record by Host header and serves the IPFS content.

**Why this works:** unlike ENS — where `contenthash` lives on-chain and a gateway/browser must read the chain to translate it — the NFD DNS service answers DNS directly, so the standard DNSLink TXT convention is all you need. The `_dnslink` label is handled like any other underscore-prefixed name (the same mechanism behind `_dmarc` and `_atproto`).

***

## Limitations

1. **Segment depth**: The `.algo` name may have at most **4 labels**, *not counting* leading `_`-prefixed service labels. So `key.segment.patrick.algo` (4 labels) resolves, but `a.key.segment.patrick.algo` (5 labels) is rejected. Underscore service labels are exempt, so `_http._tcp.segment.patrick.algo` still works.
2. **No NS records for subdomains**: Your NFD subdomains are not delegated zones. NS records only work at the zone apex (`algo.xyz` itself).
3. **Record types**: The following types are supported: A, AAAA, CNAME, MX, TXT, SRV, CAA, NS, SOA, CERT
4. **Expiration**: If your NFD registration expires, DNS records will return a default placeholder until renewed.

***

## Benefits Summary

| Feature                     | Traditional DNS | NFD DNS |
| --------------------------- | --------------- | ------- |
| Registrar Required          | Yes             | No      |
| On-chain ownership          | No              | Yes     |
| Smart contract control      | No              | Yes     |
| Multisig/domain DAO control | No              | Yes     |
| Trustless resolution        | No              | Yes     |
| Global compatibility        | Yes             | Yes     |

***

## Next Steps

* [DNS Record Types](/platform/manage/native-dns-for-nfds/dns-record-types.md) — Complete reference for all supported record types with examples
* [Testing & Troubleshooting](/platform/manage/native-dns-for-nfds/testing-and-troubleshooting.md) — Verify your DNS configuration and debug common issues

***

## Conclusion

The `.algo.xyz` DNS bridge transforms your Algorand NFD into a global, resolvable domain using native internet infrastructure. This is a powerful blend of decentralization, security, and real-world interoperability—and it's available now.

**Your domain. Your keys. Your records.** Accessible from anywhere.
