Created
August 21, 2012 12:52
-
-
Save schrockwell/3415112 to your computer and use it in GitHub Desktop.
Linode dynamic DNS updater v0.0.3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
# | |
# Linode dynamic DNS updater | |
# Version 0.0.3 | |
# August 21, 2012 | |
# | |
# By Rockwell Schrock | |
# [email protected] | |
# https://gist.github.com/3415112 | |
# | |
# This Ruby script updates a Linode DNS listing with your public IP | |
# address. Think of it as a personalized dynamic DNS service. Throw | |
# it in a crontab or a system init script for +1 effectiveness. | |
# | |
# You only have to set two constants: | |
# | |
# RedirectDomain: This is the fully-qualified domain you wish to | |
# forward, of the form "[subdomain].[domain].[tld]". The script | |
# will automatically figure out the Linode DomainID and ResourceID | |
# for you! If the subdomain A record does not yet exist, it will be | |
# created. Nifty, huh? | |
# | |
# APIKey: This is the Linode developer API key from the 'my profile' | |
# link at the top-right of the Linode Manager. Mmm, copypasta. | |
# | |
# Enjoy! | |
require 'uri' | |
require 'net/http' | |
require 'net/https' | |
require 'json' | |
RedirectDomain = '[SUBDOMAIN.EXAMPLE.COM]' | |
APIKey = '[LINODE API KEY]' | |
PublicIPURL = 'http://icanhazip.com/' | |
APIURL = 'https://api.linode.com/?api_key=%s&api_action=%s' | |
def execute(action, params) | |
url = APIURL % [APIKey, action] | |
param_strings = params.map { |param, value| "#{param}=#{URI.escape(value)}" } | |
url << '&' << param_strings * '&' | |
uri = URI.parse(url) | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
request = Net::HTTP::Get.new(uri.request_uri) | |
response = http.request(request) | |
JSON.parse(response.body) | |
end | |
# Figure out the subdomain | |
subdomain_name = RedirectDomain.split('.')[0] | |
domain_name = RedirectDomain.split('.')[1..2] * '.' | |
# Get the public IP | |
public_ip = Net::HTTP.get(URI(PublicIPURL)).chomp | |
# First find the domain ID | |
response = execute('domain.list', {}) | |
response['DATA'].each do |domain| | |
if domain['DOMAIN'].downcase == domain_name.downcase | |
@domain_id = domain['DOMAINID'].to_s | |
break | |
end | |
end | |
raise "Domain #{domain_name} not found" unless @domain_id | |
# Now get the resource ID, and create it if not already there | |
response = execute('domain.resource.list', { :DomainID => @domain_id }) | |
response['DATA'].each do |resource| | |
if resource['TYPE'].downcase == 'a' and resource['NAME'].downcase == subdomain_name.downcase | |
@resource_id = resource['RESOURCEID'].to_s | |
@old_ip = resource['TARGET'] | |
break | |
end | |
end | |
if @resource_id | |
if @old_ip == public_ip | |
puts "Subdomain '#{subdomain_name}' found, no update needed" | |
else | |
puts "Subdomain '#{subdomain_name}' found, updating..." | |
response = execute('domain.resource.update', { :DomainID => @domain_id, :ResourceID => @resource_id, :Target => public_ip }) | |
end | |
else | |
puts "Subdomain '#{subdomain_name}' not found, creating..." | |
response = execute('domain.resource.create', { :DomainID => @domain_id, :Type => 'A', :Name => subdomain_name, :Target => public_ip }) | |
end | |
puts "Updated #{RedirectDomain} to #{public_ip}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment