LowEndBox - Cheap VPS, Hosting and Dedicated Server Deals

Own a Domain? Roll Your Own Dynamic DNS With the Porkbun API

PorkbunIf you want to connect to your home or serve something from home, you probably run into the fact that your home IP can change at any time.  Mine is static for months and months, but can change at a moment’s notice.

There are various dynamic DNS services where you have a client running on your router or PC, but that’s not the DIY way.  Let’s use the Porkbun API instead,.

To do this, you need:

  • A domain hosted at Porkbun
  • DNS service hosted at Porkbun

The Porkbun API

Login to Porkbun and from your account dropdown in the upper right, select API Access.

Porkbun API

Under API Keys, enter a name for your API key and click Create API Key.

Porkbun API Create Key

Note the API Key and Secret Key.  Copy/paste them into a text editor – we’re going to come back to them in just a sec.

Two more things.  First, you need to make sure that API access is turned on for the domain you want to use.

Go back to the dropdown menu and click Domain Management.  Then for the domain you want to use, click Details on the right.  Scroll down and make sure API Access is turned on:

Porkbun API Access

Finally, go to the Porkbun API documentation and note the Base URL:

Porkbun Base URL

You’re all set.

My Script

Here’s an easy to use Python script you can use to update your IP.  It doesn’t use anything except what’s in the Python standard library.  Let me share it with you and then we’ll talk about a couple points.

#!/usr/bin/env python3

import os
import json
import urllib.request
import urllib.error
import ssl
import sys

PORKBUN_API = "https://api.porkbun.com/api/json/v3"
DOMAIN = "example.com"
SUBDOMAIN = "home" # so home.example.com will be updated
RECORD_TYPE = "A"
TTL = "300"

APIKEY="pk1_<the rest of your key>"
SECRET="sk1_<the rest of your key>"

def get_public_ip() -> str:
    # Simple external check. You can swap this to your preferred service.
    with urllib.request.urlopen("https://api.ipify.org", timeout=10) as r:
        return r.read().decode().strip()

def porkbun_edit(ip: str) -> None:
    url = f"{PORKBUN_API}/dns/editByNameType/{DOMAIN}/{RECORD_TYPE}/{SUBDOMAIN}"
    payload = json.dumps({
        "apikey": APIKEY,
        "secretapikey": SECRET,
        "content": ip,
        "ttl": TTL
    }).encode()

    req = urllib.request.Request(url, data=payload, headers={"Content-Type": "application/json"})
    ctx = ssl.create_default_context()

    with urllib.request.urlopen(req, context=ctx, timeout=15) as r:
        resp = json.loads(r.read().decode())

    if resp.get("status") != "SUCCESS":
        raise RuntimeError(resp)

def main():
    ip = get_public_ip()
    porkbun_edit(ip)
    print(f"Updated {SUBDOMAIN}.{DOMAIN} -> {ip}")

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"ERROR: {e}", file=sys.stderr)
        sys.exit(1)

Let’s try it:

$ ./update_porkbun_home_ip.py 
Updated home.lowend.party -> x.x.x.x

Perfect.

Of course, update your domain and creds in the script.

I run this out of cron every 15 mins, with stdout directed to a log file.  You could make it much more significant to get your IP, query the API to see if it’s changed, etc. but it’s simplest to just constantly push a current change.

I run every 15 minutes.  You could run it a little more often, but keep in mind the minimum TTL is 600 seconds, so there’s there’s no point in running it more than every 5 minutes.

Enjoy!
 

No Comments

    Leave a Reply

    Some notes on commenting on LowEndBox:

    • Do not use LowEndBox for support issues. Go to your hosting provider and issue a ticket there. Coming here saying "my VPS is down, what do I do?!" will only have your comments removed.
    • Akismet is used for spam detection. Some comments may be held temporarily for manual approval.
    • Use <pre>...</pre> to quote the output from your terminal/console, or consider using a pastebin service.

    Your email address will not be published. Required fields are marked *