To install from source:
git clone https://github.com/stacks-network/subdomain-registrar.git
npm i
You can run the registrar in place from its source directory, and you can specify your config file via the BSK_SUBDOMAIN_CONFIG
environment parameter.
BSK_SUBDOMAIN_CONFIG=/home/aaron/devel/subdomain-registrar/my-local-config.json npm run start
You can also install the subdomain registrar globally. It should install as the program blockstack-subdomain-registrar
.
To do so run this script in your terminal :
sudo npm i -g # or, "sudo npm link"
which blockstack-subdomain-registrar
You should receive the following output :
/usr/bin/blockstack-subdomain-registrar
The subdomain registrar functions roughly as follows --- you give the registrar a domain to register subdomains under, you fund a wallet to submit registrations with, it accepts registration requests, and then it periodically issues batches of name registrations.
- Set the
ADMIN_PASSWORD
environment var to strong password. ex:
Run this command in your terminal :
pwgen -c 64 1
You should receive very similar output to this :
raj5gohhai0ni3bah4chaa6keeCh4Oophongaikeichie2eirah8AjooyahZaifi
For example, if I want to register names like alice.people.id
or bob.people.id
, I have to:
- Already own
people.id
- Set the
BSK_SUBDOMAIN_OWNER_KEY
to the private key hex string which ownspeople.id
(this is a 64-character hex-string with01
appended if the address is compressed, which is usually the case) - Set the domain name property in the
config.json
topeople.id
Each batch of registrations is an update transaction -- the Bitcoin transaction fee for this must be paid by the registrar. This requires a payment-address. You must:
- Set the
BSK_SUBDOMAIN_PAYMENT_KEY
to a private key hex string (again, a 64-character hex string with01
appended if the address is compressed, which is usually the case). - Send Bitcoin funds to the address which corresponds to that private key.
When a batch is issued, it take 6-7 bitcoin blocks before the rest of the Blockstack network will pick up and process the transaction. This means that it is usually a little over an hour before the registrations within a given batch will appear on other services (e.g., the blockstack-browser, blockstack explorer, etc.).
You can deploy many different spam protection schemes via a front-end service, however, this subdomain registrar also supports performing some spam protection on its own. You can configure IP limiting (i.e., limiting the number of names registered by a given IP) and social proof verification.
Social proof verification performs the normal Blockstack JWT verification and social proof checks, provided by blockstack.js.
In order to support registration requests from "trusted sources", you can use the apiKeys
configuration option
to add an array of allowed api keys. Requests with an Authorization: bearer <apiKey>
header will then be able to
skip the spam countermeasures.
If you add a key to your config.json
file, you can whitelist IPs against your spam counter measures, e.g.:
{
...
"ipWhitelist": ["127.0.0.1"],
...
}
You can either store your private key hexes in your config.json, or pass them
in via environment variables BSK_SUBDOMAIN_OWNER_KEY
and BSK_SUBDOMAIN_PAYMENT_KEY
,
and then clear those after the process starts.
A common issue when configuring the subdomain registrar relates to private key formatting. A bare private key hex string is 64-characters (corresponding to a 32-byte ECDSA private key), for example:
9bffeccf649d21814ce6a605ad5cb1bdf1ac9ee44c53ef08a292af82875154df
Now -- this key actually corresponds to two different bitcoin addresses -- a compressed and an uncomprossed address. Most bitcoin addresses in use (and the kind used by the Blockstack Browser) are compressed. The standard way to denote that the corresponding public-key should be compressed is by appending 01
to the private key: this results in a 66-character hex string private key.
For example, these are the two different addresses for the above key:
var bsk = require('blockstack')
bsk.hexStringToECPair('9bffeccf649d21814ce6a605ad5cb1bdf1ac9ee44c53ef08a292af82875154df01').getAddress()
'1QJM5ESqzWKW6pF2Ho7BGBX7MpepmxedU2'
bsk.hexStringToECPair('9bffeccf649d21814ce6a605ad5cb1bdf1ac9ee44c53ef08a292af82875154df').getAddress()
'14K3MSHixgt9FSjPEgLD8YrMEk3ss5QyYN'
In most cases, you want to use the compressed key.
Per the design outlined here, the subdomain registrar can be configured so that blockstack indexer nodes will respond with HTTP 301 status codes for missing subdomains. The 301 redirect will send the name lookup request to a URI designated by the domain name. In a standard setup, this would allow nearly instantaneous resolution of subdomain names. (Note: these names will not have been committed to the blockchain yet, and therefore the response from the designated endpoint do not have the same security properties as committed names).
To support this, the subdomain registrar is capable of responding to /v1/names/foo.bar.id
style requests,
and can be configured to set the _resolver
URI entry in each zonefile that it publishes. To enable this
behavior, set the resolverUri
setting in your config.json
file to a public-facing URL for your registrar.
We recommend placing this GET /v1/names/
endpoint behind a caching layer of some kind.
You can configure a monitoring service for the subdomain registrar via adding a prometheus
field to the configuration file:
"prometheus": { "start": true, "port": 5941 }
Or by setting the environment variable BSK_SUBDOMAIN_PROMETHEUS_PORT
Queue a registration:
Run this command in your terminal :
curl -X POST -H 'Authorization: bearer API-KEY-IF-USED' -H 'Content-Type: application/json' --data '{"zonefile": "$ORIGIN spqr\n$TTL 3600\n_https._tcp URI 10 1
You should receive similar to the following output :
\"https://gaia.blockstack.org/hub/1HgW81v6MxGD76UwNbHXBi6Zre2fK8TwNi/profile.json\"\n", "name": "spqr", "owner_address": "1HgW81v6MxGD76UwNbHXBi6Zre2fK8TwNi"}' http://localhost:3000/register/
Force a batch:
curl http://localhost:3000/issue_batch -X POST -H 'Authorization: bearer PASSWORDHERE'
Force zonefile check:
curl http://localhost:3000/check_zonefile -X POST -H 'Authorization: bearer PASSWORDHERE'
Check subdomain status:
Run this command in your terminal :
curl http://localhost:3000/status/spqr | jq .
You should receive the following output :
{
"status": "Your subdomain was registered in transaction 6652bd350f048cd190ff04a5f0cdebbc166b13f3fd0e1126eacec8c600c25c6f -- it should propagate on the network once it has 6 confirmations."
}
First copy the config file into a data directory and modify it to suit your needs:
mkdir -p data
cp config-sample.json data/config.json
vi config.json
Once that is done you can spin up the instance using docker-compose. The file will build the image as well:
docker-compose up -d
If you would like to run w/o compose you can do the same with docker:
# First build the image
docker build . --tag bsk-subdomain-registrar
# Then run it with the proper volumes mounted
docker run -d -v data:/root/ -e BSK_SUBDOMAIN_CONFIG=/root/config.json -p 3000:3000 bsk-subdomain-registrar
Root stores the sqlite database that the subdomain uses to queue registrations, and watch zonefiles for broadcasting. To test connectivity for this setup run the following curl command:
Run this command in your terminal :
curl http://localhost:3000/index | jq
You should receive the following output :
{
"status": true
}
The following ENV variables can be set to override settings.
PAYMENT_KEY
- The private key used to pay for the transactionsOWNER_KEY
- The private key that owns the BNS nameOWNER_NAME
- The BNS name used to register subdomains, i.e.foo.id
BLOCKSTACK_API_URL
- A Stacks blockchain API url