Decentralized Blog on Handshake and Skynet

Sia and Namebase teams partnered together for the Own the Internet Hackathon — a 3-week hackathon from July 29th to Aug 19th to build decentralized applications that are censorship-resistant and truly in your control. There were more than $8000 SC and HNS in prizes, and every participant got a free Own the Internet T-shirt!

Setup

You can still use our GUI DNS management interface if you don't want to use the API.

Get Namebase API key

Login to your Namebase account and go to https://namebase.io/pro/keys.

Click NEW API KEY in the top right.

Record the Access Key and Secret Key.

To authenticate your API calls, you’ll need to create an authentication header to send with the HTTP request. Here’s what the steps look like in javascript:

const credentials = Buffer.from(`${ACCESS_KEY}:${SECRET_KEY}`);
const encodedCredentials = credentials.toString('base64');
const authorization = `Basic ${encodedCredentials}`;

Then add Authorization: authorization as a header.

Here’s a script that simplifies the HTTP requests into a command line interface. To set it up, set the ACCESS_KEY and SECRET_KEY with the keys you recorded earlier. The full documentation on the API can be found here (https://github.com/namebasehq/api-documentation).

const fetch = require('node-fetch');
const ACCESS_KEY = '';
const SECRET_KEY = '';
const credentials = Buffer.from(`${ACCESS_KEY}:${SECRET_KEY}`);
const encodedCredentials = credentials.toString('base64');
const authorization = `Basic ${encodedCredentials}`;
async function get(endpoint, body = null) {
const options = {
method: 'GET',
headers: {
Authorization: authorization,
Accept: 'application/json',
'Content-Type': 'application/json',
},
};
const url = `https://namebase.io${endpoint}`;
return fetch(url, options)
.then(res => res.json())
.catch(err => err);
}
async function put(endpoint, body) {
const options = {
method: 'PUT',
body: body,
headers: {
Authorization: authorization,
Accept: 'application/json',
'Content-Type': 'application/json',
},
};
const url = `https://namebase.io${endpoint}`;
return fetch(url, options)
.then(res => res.json())
.catch(err => err);
}
async function main() {
const args = process.argv.slice(2);
let func, path, data;
const domain = args[2];
if (args[0] === 'get') {
func = get;
} else if (args[0] === 'put') {
func = put;
if (args.length < 4) throw new Error('Put requires 4 arguments');
data = args[3];
} else {
throw new Error("Method should be either 'get' or 'put'");
}
if (args[1] === 'blockchain') {
path = `/api/v0/dns/domains/${domain}`;
} else if (args[1] === 'blockchain-advanced') {
path = `/api/v0/dns/domains/${domain}/advanced`;
} else if (args[1] === 'nameserver') {
path = `/api/v0/dns/domains/${domain}/nameserver`;
} else {
throw new Error("Service should be 'blockchain', 'blockchain-advanced' or 'nameserver'");
}
return func(path, data);
}
main().then(res => {
console.log(res);
});

Using the Script

Now that your API calls are authenticated, you can test out the queries. The script call looks like:

node ./namebaseApi.js METHOD SERVICE DOMAIN RECORD_DATA

where

METHOD = get (retrieving records) or put (adding/updating records)

SERVICE = which DNS settings you want to add, the three options are:

  1. blockchain — for Handshake records that are ‘DS’, ‘TXT’, or ‘NS’

  2. blockchain-advanced — Handshake accepts some additional record types, in order to send these create a Handshake resource record and send the hex as the RECORD_DATA (more documentation can be found here https://hsd-dev.org/guides/resource-records.html )

  3. nameserver — Namebase’s own nameservers which enables users to set ‘A’, ‘CNAME’, ‘ALIAS’, ‘NS’, ‘DS’, and ‘TXT’ records either on the root or a subdomain. All names won on Namebase should have this connected by default. There’s an explanation on how to check if this is configured below.

DOMAIN = your Handshake domain

RECORD_DATA = only necessary for METHOD=’put’; the json format varies slightly based on the SERVICE, be sure to double check with the full documentation.

Keep in mind that the blockchain endpoints will replace all existing records with the new json that is sent. So, if you only want to add another record, you have to get the current records and send them along with the new one. For deleting, you would need to resend all the current records except for the one you want to delete.

The nameserver records are slightly different. It will only replace records if a record with the same type and host is specified. For example, if I have a TXT record set on foo.example, adding another TXT record on bar.example will not replace it.

Connecting Handshake to Skynet

Upload Your Content

Uploading your blog to Skynet is incredibly easy, just use the command below.

curl -X POST ‘https://siasky.net/skynet/skyfile’ -F file=@FILE_NAME

This can also be done through the Sia UI.

Both methods will return the Skylink to your file. If you used the UI, the Skylink is the 46 characters at the end of the link. Record this because you’ll need it later to connect it to Handshake.

For an extended tutorial on connecting and resolving your Skynet site via Sia's Skynet Portal, see their Skynet 🤝 Handshake blog post where they explain how to set your Handshake DNS records through Namebase’s UI in order to access your content through the portal at "https://siasky.net/hns/YOUR_DOMAIN". For resolving your site using your Handshake domain and its subdomains, Namebase has created a Skynet gateway.

Namebase currently hosts a public gateway for anyone to use. However, keep in mind this is experimental and won’t be thoroughly maintained. If you want to create a more reliable site, hosting your own gateway is recommended.

Running Your Own Gateway

Clone Namebase’s Skynet gateway repo

First, run npm install to download the dependencies, then open .env and use the instructions below to make sure the gateway is configured properly.

Unless you want to open your resolver to the internet to allow other servers to resolve off of your gateway, leave LOCAL_GATEWAY as ‘true’. Make a directory to store the Skynet content of the sites you visit — it will act as a cache and will only store as many sites as CACHE is set to. Set LOCAL_SERVER_DIRECTORY to the full path of this directory. Finally, set HNS_NAMESERVER_HOST and HNS_NAMESERVER_PORT to the address and port of a Handshake resolver — the default is set to NextDNS’s nameservers. Finally, run sudo npm run start to run the gateway.

Setting Gateway Records

For setting up the Skynet gateway, you’ll need to set a TXT record with the Skylink for your app and an A record pointing to the gateway. The following will explain how to set these records using the Namebase API, however, this can all be done through the Namebase UI as well.

If your hosting your own gateway, then set GATEWAY_IP to your server’s public ip, otherwise, set it to 52.36.16.31 to use Namebase’s.

For hosting the site on the root name:

node namebaseApi.js put nameserver YOUR_DOMAIN ‘{ “records”: [{ “type”: “TXT”, “host”: “@”, “value”: “skylink=YOUR_SKYLINK”, “ttl”: 0 }, { “type”: “A”, “host”: “@”, “value”: “GATEWAY_IP”, “ttl”: 0 }] }’

This calls the PUT /api/v0/dns/domains/YOUR_DOMAIN/nameserver endpoint.

For hosting the site on a subdomain:

node namebaseApi.js put nameserver YOUR_DOMAIN ‘{ “records”: [{ “type”: “TXT”, “host”: “SUBDOMAIN”, “value”: “skylink=YOUR_SKYLINK”, “ttl”: 0 }, { “type”: “A”, “host”: “SUBDOMAIN”, “value”: “GATEWAY_IP”, “ttl”: 0 }] }’

This calls the PUT /api/v0/dns/domains/YOUR_DOMAIN/nameserver endpoint.

If you want to update the Skylink for your site, simply upload the new file to Skynet and use the following command:

node namebaseApi.js put nameserver YOUR_DOMAIN ‘{ “records”: [{ “type”: “TXT”, “host”: “SUBDOMAIN”, “value”: “skylink=YOUR_NEW_SKYLINK”, “ttl”: 0 }}] }’

Now as long as your device can resolve Handshake names, you can go to a web browser and view your blog at http://YOUR_DOMAIN or http://SUBDOMAIN.YOUR_DOMAIN!