User:Datagrok/ddns
ddns.py is a small script that maintains a DNS record that points at one's home network. This process is sometimes called Dynamic DNS.
There are others like it; see The DNS section of API Apps or Dynamic DNS for some. I wrote this one to obtain the following features that I could not find elsewhere:
- It runs from your DreamHost shell account, and uses your ssh connection to determine your IP.
- It's implemented in Python.
- Uses my own Python module to interface with the DreamHost API.
ddns.py listing:
#!/usr/bin/python -O
from dreamhostapi import DreamHostServerProxy
from os import environ
def main():
dh_api_key = '6SHU5P2HLDAYECUM'
hostname = 'home.mydomain.com'
new_ip = environ['SSH_CLIENT'].split()[0]
server = DreamHostServerProxy(dh_api_key)
if __debug__:
print "Retrieving list of current domains..."
for record in server.dns.list_records():
if not (record['record'] == hostname and record['type'] == 'A'):
continue
if record['value'] == new_ip:
if __debug__:
print "Old record for %(record)s found with IP %(value)s, no update needed." % record
raise SystemExit()
if __debug__:
print "Old record for %(record)s found with IP %(value)s, removing." % record
result = server.dns.remove_record(
record=record['record'],
type=record['type'],
value=record['value'],
)
result = server.dns.add_record(
comment='Dynamic DNS IP',
record=hostname,
type='A',
value=new_ip,
)
if result != 'record_added':
raise ValueError("There was a problem adding the record.")
if __debug__:
print "Success"
if __name__=="__main__":
main()
Required module
dreamhostapi.py is a small Python module I wrote to interface with the DreamHost API. There are others like it; DreamPyLib is one such. I wrote this one to obtain the following features that I could not find elsewhere:
- It is implemented as a wrapper around Python's built-in XMLRPC library.
- It's short.
dreamhost.api listing:
from xmlrpclib import ServerProxy, _Method
from uuid import uuid1
class DreamHostMethod(_Method):
def __init__(self, send, name):
_Method.__init__(self, send, name)
def __getattr__(self, name):
return DreamHostMethod(self._Method__send, "%s-%s" % (self._Method__name, name))
def __call__(self, **kw):
return self._Method__send(self._Method__name, kw)
class DreamHostServerProxy(ServerProxy):
dh_api_server = 'https://api.dreamhost.com/xmlrpc'
def __init__(self, key, verbose=0):
ServerProxy.__init__(self, uri=self.dh_api_server, verbose=verbose)
self.dh_api_key = key
def __getattr__(self, name):
return DreamHostMethod(self.__request, name)
def __request(self, name, params):
if not params:
params = {}
params['key'] = self.dh_api_key
params['uuid'] = str(uuid1())
result = ServerProxy._ServerProxy__request(self, name, (params,))
if result['result'] != 'success':
raise ValueError("Server returned %(result)s: %(data)s" % result)
return result['data']
Installation
- Copy the text above for ddns.py to a file named ddns.py on your DreamHost webserver.
- Change the variables dh_api_key and hostname to whatever you're using.
- Make it executable. (chmod +x ddns.py)
- Copy the text above for dreamhostapi.py to a file named dreamhostapi.py on your DreamHost webserver.
- Set up a machine within your home network to periodically connect to your shell account and run the ddns.py script.
Advanced Installation
I prefer to keep dreamhostapi.py in ~/lib/python/datagrok/; ~/lib/python is in my $PYTHONPATH. I then change the import statement to read:
from datagrok.dreamhostapi import DreamHostServerProxy
I set this to run periodically by creating an executable script /etc/cron.daily/ddns-update on a local machine:
#!/bin/sh ssh mydomain.com "ddns.py"
Replace mydomain.com everywhere with your own domain name.
For better security, create a separate ssh key just for this automatic process, then restrict the key to run only ddns.py in .ssh/authorized_keys on your DreamHost shell account.