Feature blog image

New DNS registrar

5 min read

Recently, I was listening to episode #632 of the Syntax.fm podcast. In this episode, Scott and Wes were talking about domain registrars. That prompted me to take a closer look at my own domains. Over the years, I've registered a few domains with three different providers (STRATO, united-domains, and GoDaddy). I wasn't happy with any of those providers, so I decided to look for a new one.

Looking for a new provider

I don't require much from a DNS registrar. I need support for .org, .de, and .dev top-level domains (TLDs). Additionally, I require an API for automation, and it must be possible to create Let's Encrypt wildcard certificates. Scott and Wes mentioned in the episode that they both use Cloudflare. However, at the time I was searching for a new provider, Cloudflare did not support .dev TLDs.

info

Cloudflare now offers .dev. Please have a look at Cloudflare TLD Policies.

But they mentioned Porkbun as a surprisingly cheap alternative. I've never heard of Porkbun, so I decided to take a closer look at it.

Porkbun

The first impression wasn't really good after I visited their website. The site itself looks like a Bootstrap 2 demo application, and the name and logo do not look professional at all. But holy shit, the prices are really cheap.

DomainSTRATOunited-domainsGoDaddyPorkbun
de$13.17$20.85$11.89$4.07
org$19.76$27.44$27.57$10.72
dev$26.34$31.83$24.00$10.79

Prices from August 2023. STRATO and united-domains prices are converted from Euro (€).

And they offer a simple-looking API. So I decided to go down the road and move one of my domains over to Porkbun.

Good to know

You don't need to wait for the domain subscription to expire before changing the domain registrar. When you transfer the domain to a new registrar, you will need to pay for one year of registration at the new registrar. However, this year will be added to the remaining duration of your current subscription. The domain transfer process usually takes a few hours or days, depending on the registrars.

The transfer from GoDaddy to Porkbun went smoothly. So i want to try the API.

API

First, we need to enable the API for our domain, and then we have to create a key pair for authentication. The Getting started with the Porkbun API entry of the knowledge base of Porkbun explains this process very well. Let's review the documentation and begin with a shell script.

Shell script


curl --header "Content-Type: application/json" \
--request POST \
--data '{
"apikey" : "pk1_...",
"secretapikey" : "sk1_...",
"name" : "example",
"type" : "A",
"content" : "1.2.3.4",
"ttl" : "600"
}' \
https://porkbun.com/api/json/v3/dns/create/sdorra.dev

That was not to complicated lets try TypeScript.

TypeScript


const response = await fetch("https://porkbun.com/api/json/v3/dns/create/sdorra.dev", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
apikey: "pk1_...",
secretapikey: "sk1_...",
name: "example",
type: "A",
content: "1.2.3.4",
ttl: "600",
}),
});
if (!response.ok) {
throw new Error("Failed to create dns record");
}

This was also easy. Next, ansible.

Ansible


- name: Set record name and ip
set_fact:
domain: "sdorra.dev"
porkbun_apikey: "pk1_..."
porkbun_secretapikey: "sk1_..."
record_name: "example"
record_ip: "1.2.3.4"
- name: Get status of record from porkbun
uri:
url: "https://porkbun.com/api/json/v3/dns/retrieveByNameType/{{domain}}/A/{{ record_name }}"
method: POST
body_format: json
body:
apikey: "{{ porkbun_apikey }}"
secretapikey: "{{ porkbun_secretapikey }}"
register: result
- name: Create porkbun record
uri:
url: "https://porkbun.com/api/json/v3/dns/create/{{domain}}"
method: POST
body_format: json
body:
apikey: "{{ porkbun_apikey }}"
secretapikey: "{{ porkbun_secretapikey }}"
name: "{{ record_name }}"
type: "A"
content: "{{ record_ip }}"
ttl: "600"
when: result.json.records is not defined or result.json.records | length == 0
- name: Update porkbun record
uri:
url: https://porkbun.com/api/json/v3/dns/editByNameType/{{domain}}/A/{{ record_name }}
method: POST
body_format: json
body:
apikey: "{{ porkbun_apikey }}"
secretapikey: "{{ porkbun_secretapikey }}"
name: "{{ record_name }}"
type: "A"
content: "{{ record_ip }}"
ttl: "600"
when: result.json.records is defined and result.json.records | length > 0 and result.json.records[0].content != record_ip

This was more complicated, but it is not the fault of the API; it lies in the nature of Ansible. Ansible is a declarative tool, while the API is imperative. Therefore, we need to check if the record exists and if the IP is correct. If the record does not exist, we need to create it, and if the IP is wrong, we need to update it.

So far, so good. But what about Let's Encrypt wildcard certificates?

Let's Encrypt


docker run --rm \
-v certificates:/var/lib/lego/certificates \
-v lego_accounts:/var/lib/lego/accounts \
-e PORKBUN_API_KEY="pk1_..." \
-e PORKBUN_SECRET_API_KEY="sk1_..." \
goacme/lego:v4.12.3 \
--accept-tos \
--email="email.for.letsencrypt.account@example.com" \
--dns="porkbun" \
--domains="*.sdorra.dev" \
--domains="sdorra.dev" \
--path="/var/lib/lego" \
run

We use the LEGO tool, running in a Docker container, to create the certificates. That works like a charm.

Conclusion

Now, I have tested everything I need for my domains. Even if Porkbun does not look professional, the service offers everything I need, and the prices are really cheap. There are no more excuses not to move all my domains to Porkbun.

Posted in: dns, node, ansible, lets-encrypt