On that note digitalocean has free DNS servers (I think you can also use them when you don’t actually buy anything… but maybe you have to buy something once in your life).
Since they have an API you can do just about anything. Including adding new DNS entries and updating IPs. You can also use that for dyndns.
There is this node script that you can run on a set schedule to update a DNS entry for your home IP. I run that every day even though my IP rarely ever changes.
There was SOMETHING that didn’t quite work out for me with that script, but I made some changes to get it working. I don’t know what I changed. But it didn’t update the IP for me initially.
The changed script
#!/usr/bin/env node
var request = require("request");
var fs = require("fs");
var figlet = require("figlet");
var args = process.argv;
var updated = false;
if (process.argv.indexOf("-h") != -1 || process.argv.indexOf("--help") != -1) {
showHelp();
process.exit();
}
try {
var configFileId = process.argv.indexOf("--config");
var config = JSON.parse(
fs.readFileSync(process.argv[configFileId + 1], "utf8")
);
} catch (error) {
if (configFileId === -1) {
console.log(new Date() + " Missing --config parameter.");
} else {
console.log(
new Date() +
" Error reading cofig file. File either missing or malformed."
);
}
process.exit();
}
if (
process.argv.indexOf("--list") !== -1 ||
process.argv.indexOf("-l") !== -1
) {
var domainInfo = JSON.parse(getDomainInfo());
console.dir(domainInfo, { depth: null, colors: true });
process.exit();
}
function getIPv4() {
var source;
request(
{
url: "http://ip4.iurl.no",
method: "GET",
headers: {
"Content-Type": "application/text"
}
},
function (error, response, body) {
if (error) {
console.log(
new Date() +
" Error getting IP " +
error.code +
" (" +
error.host +
")"
);
process.exit();
}
source = body;
}
);
while (source === undefined) {
require("deasync").runLoopOnce();
}
return source;
}
function updateIP(newIP, domain, API_KEY, domainid) {
var rest_response = undefined;
request(
{
method: "PUT",
url: `https://api.digitalocean.com/v2/domains/${domain}/records/${domainid}?data=${newIP}`,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
}
},
function (error, response, body) {
rest_response = response;
if (error) {
console.log(new Date() + " Error uppdating IP " + error.code);
process.exit();
}
}
);
while (rest_response === undefined) {
require("deasync").runLoopOnce();
}
}
function getServerIP(i) {
var remoteIP;
request(
{
url: `https://api.digitalocean.com/v2/domains/${config.domains[i].name}/records/${config.domains[i].id}`,
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + config.api_key
}
},
function (error, response, body) {
try {
var data = JSON.parse(body);
remoteIP = [data.domain_record.type, data.domain_record.data];
} catch (error) {
console.log(new Date() + " Error getting remote IP " + error.code);
process.exit();
}
}
);
while (remoteIP === undefined) {
require("deasync").runLoopOnce();
}
return remoteIP;
}
function getDomainInfo() {
var domainInfo;
request(
{
url: `https://api.digitalocean.com/v2/domains/${config.domains[0].name}/records`,
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${config.api_key}`
}
},
function (error, response, body) {
try {
domainInfo = body;
} catch (error) {
console.log(new Date() + " Error getting domaininfo " + error.code);
process.exit();
}
}
);
while (domainInfo === undefined) {
require("deasync").runLoopOnce();
}
return domainInfo;
}
function showHelp() {
console.log(
figlet.textSync("dynDNS", {
horizontalLayout: "default",
verticalLayout: "default"
})
);
console.log(
"\r\ndynDNS updates your Digital Ocean DNS record with your local (public) IPv4"
);
console.log("Usage :");
console.log('dyndns --config "/path/to/file/config.json"');
console.log(
"\r\nOptions : \r\n -h or --help Show this help"
);
console.log(" -l or --list Lists subdomains");
console.log('\r\nExample: dyndns --config "/home/testuser/config.json"');
}
if (
process.argv.indexOf("--list") !== -1 ||
process.argv.indexOf("-l") !== -1
) {
var domainInfo = JSON.parse(getDomainInfo());
console.dir(domainInfo, { depth: null, colors: true });
process.exit();
}
var IP4 = getIPv4();
for (var i = 0; i < config.domains.length; i++) {
var dnsIP = getServerIP(i);
if (dnsIP[0] === "A" && IP4.localeCompare(dnsIP[1]) != 0) {
updateIP(IP4, config.domains[i].name, config.api_key, config.domains[i].id);
updated = true;
console.log(new Date() + " Updated IP to " + IP4);
}
}
if (!updated) console.log("[" + new Date() + "] IP not updated.");
process.exit();
I never got around to actually validate what I changed (it sure works for me now, but at this point I forgot what I changed). So, I didn’t contribute it to the github because of that. Should have done that back then.
The script looks huge, but it actually does not do all that much.
Effectively it just determines your ip using http://ip4.iurl.no
and calls a digitalocean api to update the DNS entry with the result. So you could easiely make a MUCH shorter thing, but it would work just for your use case and for no one elses.