Identity & NIP-05

Using a custom domain for your Nostr identity: step-by-step

Host your own NIP-05 on a domain you control. Why you might want to, how to set it up in minutes, and what it gives you that a managed service does not.

byEgor7 min read

Using your own domain for Nostr identity is a legitimate choice. It takes more setup than a managed service but gives you permanent control over the identifier. This guide covers when it is worth it and how to do it.

TL;DR. Register a domain, put a JSON file at https://yourdomain.com/.well-known/nostr.json with your pubkey, set yourname@yourdomain.com as your NIP-05 in your Nostr profile. Total setup: about 30 minutes. Annual cost: just the domain registration. Works identically to a managed NIP-05 service from the clients' perspective.

When you're ready, grab your @nostr.blog address

Why a custom domain matters

Three reasons users choose this path.

Full ownership. A custom domain is yours as long as you renew it. No third party (including a NIP-05 service) can take it away. If nostr.blog went out of business tomorrow, your alice@nostr.blog identity would stop resolving. Your alice@alicedomain.com would not, because the domain is yours.

Uniqueness. alice@nostr.blog signals "Alice, on the nostr.blog service." alice@alicedomain.com signals "Alice, at Alice's own place." For public figures, creators, or anyone building a personal brand, the self-hosted identifier carries more branding weight.

Control. You decide the policies for your domain. You can have multiple names (alice@alicedomain.com, alice-work@alicedomain.com) without separate registrations. You can change the backing pubkey without involving a service.

When a custom domain is not worth it

Honest counter-list.

You are new to Nostr. First-time users should use a managed service to get set up quickly. Switch to custom later if you want.

You are not comfortable with web servers. The setup requires editing server configurations. Not hard, but not beginner-friendly.

You will not renew the domain. A lapsed domain loses your NIP-05. If you are uncertain about keeping the domain for years, a managed service is more reliable for you.

The domain is branded for something else. If you already own alicejewelry.com for a jewelry business, running NIP-05 on it ties your Nostr identity to that business. Sometimes desirable; sometimes not.

Prerequisites

Three things you need.

  1. A domain you control. Registering at Namecheap, Cloudflare, or similar. $10-15/year for most TLDs.
  2. A way to host a static file at /.well-known/nostr.json. Most cheapest-possible paths: GitHub Pages, Cloudflare Pages, Netlify, a VPS with Caddy, or any existing web hosting you have.
  3. Your Nostr public key in hex form. 64 characters, lowercase a-f and 0-9. Your client's account settings show it.

Setup: the fast path (Cloudflare Pages)

If you already have Cloudflare for DNS, this is the fastest.

  1. Create a new Cloudflare Pages project.
  2. Add a file at /.well-known/nostr.json with your name-to-pubkey mapping:
{
  "names": {
    "yourname": "your-hex-pubkey-here"
  }
}
  1. Deploy.
  2. Configure the Worker or Pages Function to set Access-Control-Allow-Origin: * header on the /.well-known/* path. Cloudflare's documentation covers this.
  3. Point your domain at the Pages project.
  4. Test: curl -i https://yourdomain.com/.well-known/nostr.json should return the JSON with the CORS header.
  5. In your Nostr client, set your NIP-05 to yourname@yourdomain.com. Save.
  6. Within a few minutes, the verification checkmark appears.

Total time: 20-30 minutes if you are familiar with Cloudflare.

Setup: Caddy on a VPS

For users who already run a VPS.

  1. Add to your Caddyfile:
yourdomain.com {
    header /.well-known/nostr.json {
        Access-Control-Allow-Origin "*"
        Content-Type "application/json"
    }
    file_server
}
  1. Create the JSON file at the server's webroot, path /.well-known/nostr.json:
{
  "names": {
    "yourname": "your-hex-pubkey-here"
  }
}
  1. Reload Caddy: sudo systemctl reload caddy.
  2. Verify with curl -i https://yourdomain.com/.well-known/nostr.json.
  3. Set NIP-05 in Nostr profile.

Caddy handles TLS automatically. Verification works once DNS resolves and the file serves cleanly.

Setup: GitHub Pages

Free, simplest for small use.

  1. Create a GitHub repository. Enable GitHub Pages on it with a custom domain (yourdomain.com).
  2. Add .well-known/nostr.json to the repo with your name/pubkey mapping.
  3. Push.
  4. Point your domain's DNS at GitHub Pages per their docs.

Complication: GitHub Pages does not let you set custom response headers. For CORS, you need to either proxy through Cloudflare, use a Cloudflare Worker to add the header, or accept that some browser-based clients will fail to verify your identity.

For desktop-only use, GitHub Pages without CORS works. For full support, Cloudflare in front of GitHub Pages is the common workaround.

Multiple identities on one domain

A custom domain can host multiple names. Example nostr.json:

{
  "names": {
    "alice": "pubkey-1...",
    "alice-work": "pubkey-2...",
    "the-journalist": "pubkey-3..."
  }
}

Each name resolves to a different pubkey. You can use these for multiple identities of yourself, or for family members, or for a small community you run.

Most users have only one entry; the option is there if you want it.

Updating your pubkey later

If you ever rotate your Nostr private key (due to a compromise or for any other reason), you update the JSON file to point your name at the new pubkey.

Process:

  1. Generate new key pair.
  2. Update /.well-known/nostr.json to use new hex pubkey.
  3. Wait for client-side caches to clear (up to 24 hours for some clients).
  4. Your identifier now points at the new identity.

Downside: followers who follow you by npub (the old one) do not automatically switch. They follow a specific pubkey. You lose the follower relationship even though the NIP-05 identifier survives.

Key rotation in 2026 is still not clean; NIP-26 delegations and NIP-41 proposals aim to improve this.

Optional: include relays in the JSON

NIP-05 allows you to publish preferred relays alongside your name:

{
  "names": {
    "alice": "your-pubkey-here"
  },
  "relays": {
    "your-pubkey-here": [
      "wss://relay.damus.io",
      "wss://nos.lol"
    ]
  }
}

Clients use this to automatically connect to your preferred relays when looking up your content. Improves cold-start performance for readers.

Optional. Works with or without.

What happens if your domain expires

The NIP-05 verification stops working. Your posts remain on Nostr; your readable identifier no longer resolves. Your underlying account (the pubkey) is unaffected.

Recovery: renew the domain, the verification starts working again. If someone else bought the domain during the lapse, they can claim any name on it including yours; in practice this is rare for personal domains but possible for valuable ones.

Protection: keep the domain on auto-renew, set up a backup payment method, and monitor expiration warnings.

Cost comparison

Over 5 years:

  • Custom domain: $50-75 (5 × $10-15 in domain renewals)
  • nostr.blog short 5-char name: $145 (5 × $29)
  • nostr.blog 8+ char name: $14.95 (5 × $2.99)
  • nostr.blog 1-char premium name: $4,995 (5 × $999)

For long names, nostr.blog is the cheaper option. For short premium names, custom domain is much cheaper. For personal domains you would buy anyway, custom is effectively free.

When custom domains are the right call

Specific user profiles where a custom domain makes obvious sense:

  • You already own a personal domain for other purposes
  • You run a company or organization and want you@company.com as your NIP-05
  • You want a short premium name and the managed service is expensive
  • You value long-term independence from all third-party services
  • You run multiple Nostr identities and want them all at the same domain

For everyone else, a managed service like nostr.blog is the easier default. Switching from managed to custom later is always possible; the only cost is the short period where the identifier changes.

Frequently asked questions

Is a custom domain better than nostr.blog for NIP-05?
Different. A custom domain gives you full independence and a unique identifier; nostr.blog gives you zero-setup convenience. Both produce the same verification checkmark. The choice is effort vs convenience.
How much does a custom Nostr domain cost?
Just the domain registration fee, usually $10-15 per year for a .com or similar. No additional fee beyond the domain. You can host the required JSON file on any web server you already have, including free options like GitHub Pages.
Can I use a subdomain for NIP-05?
Yes. nip-05.alice.xyz works the same as alice.xyz. Subdomains let you keep the main site at the root and put the NIP-05 on a separate path, which some users prefer for organization.
What web hosts work for self-hosting NIP-05?
Any host that can serve a static JSON file with custom CORS headers. Cloudflare Pages, Netlify, Vercel, GitHub Pages (with workarounds for CORS), Caddy on a VPS, or any traditional shared hosting. Static hosts are usually simpler than dynamic ones for this.
Does hosting NIP-05 myself affect zaps?
NIP-05 and zaps are separate systems. Your custom-domain NIP-05 does not interfere with zap-receive, which uses a separate Lightning address. Many users have `alice@alicedomain.com` as their NIP-05 and `wildfox123@walletofsatoshi.com` as their zap-receive address. Both work together.