Login Form

Your own DDNS Server with Ubuntu and Plesk

Annoyed by new regulations of dyndns.org to log in every 30 days to maintain your free account, I decided to host my own dynamic DNS server. I have a rented vServer running Ubuntu 10.04 LTS with Plesk 11.5 on top. Plesk is also the reason that none of the existing tutorials I found did entirely help me.

To outline what I am doing to accomplish this service:

Most tutorials describe how to create/manipulate DNS zones with the BIND server. This however is not a convenient option if you are running plesk. Plesk is doing most of the DNS configuration automatically based on the domains you maintain in the web interface. Therefore we make use of all the magic Plesk is doing by manipulating not the actual zone/key files, but the records in the Plesk database. After that it is just a matter of telling Plesk to update its records and voila: All the DNS records have been created/updated for us.

To update the database we build a little PHP website which can be called from the host you want to maintain the dyn dns record for. In my case that’s a FritzBox 7390 router.

So what do you need for this tutorial?

  • An Ubuntu server (most other Linux distributions should do the trick as well)
  • Plesk. I am using 11.5 but I very much assume that older versions will also work.
  • At least one own domain. You could also split the different parts below into different domains.
Now lets get started:
  1. First of all we need a MySQL database user that’s allowed to read and write in the Plesk database. Obviously we need to be careful when touching this database to not do any damage to our Plesk configuration. Therefore we create a new user which has very limited privileges. This user can only access the table dns_recs of Plesks psa database. That’s where Plesk stores its DNS information. So your user might look as follows:
    GRANT SELECT, UPDATE (time_stamp, displayVal, val) ON `psa`.`dns_recs` TO 'dnsupdateuser'@'localhost';
  2. The important columns are host, type and val as you will see later
  3. Now, I assume that you have your domain configured and running in Plesk. Lets call it example.com
  4. Now we create the first subdomain in Plesk which will host our dyndns server. Let’s call it dyn.example.com. You could also host this directly on you domain if you like. E.g. example.com/dyn/
  5. We create one subdomain for each dynamic host you want to facilitate. We call ours home.example.com
  6. By default Plesk does not enable the DNS for the sub domain but manages the entries together with the main domain. So we need to enable this manually: Select the subdomain –> DNS –> Enable DNS-Service
  7. Now we see a lot of DNS entries which Plesk creates automatically. We can get rid of most of them. So we delete all entries except for the A record. This is the important one. I am not really sure about the NS records, so I kept them :-) If anyone has a comment there, please let me know.
  8. Currently the A record will show the IP of your server. However, this is the one we will later update to point to your dyn host.
  9. In the webspace of the dyn.example.com subdomain first of all we create a .htaccess and .htpasswd to password protect this entire domain. The .htaccess might look like this:
    AuthType Basic
    AuthName "Login"
    AuthUserFile /var/www/vhosts/example.com/example.com/.htpasswd
    Require valid-user
    Options +Indexes
  10. Now comes the update page. This is a rather simple php page with not much of an output. As it will be the only page in the webspace we can call index.php. Of course you can customize this any further if you like. You should be able to understand most of the code yourself so just a few remarks:
    • We take the IP from the requestor as our new to-be IP.
    • Check if the requested domain (as a GET parameter) is one of our dyn domains
    • Check the plesk database if the IP has changed since the last update
    • If it has changed, we alter the database record.
    • To notify the actual updater – a cron job – we create a watched file
    • In the sucess event I echo “good [IP]” since this seems to be what makes the FritzBox recognize the update without any errors.

include 'mysql_config.php';

$dynDomains = array('home.example.com', 'garden.example.com', 'dog.example.com');

$DoUpdateFile = "updatefile/doupdate";

    die('Parameter "domain" not set');
// Check if the requested domain is in our list of domains we want to keep updated.
if(! in_array($_GET['domain'], $dynDomains)){
    die('Requested domain is not in the list of maintained dyn domains.');

// Check if IP is really an IP (should always be the case, but just to be safe...)
if($newIP == "" || !preg_match_all("/(\d{1,3}\.){3}\d{1,3}/", $newIP, $matches )){

// We need to append a dot (.) to the end of the requested domain
$dyndns = $_GET['domain'] . '.';

$query = "SELECT id, val FROM dns_recs WHERE host = '$dyndns' AND type = 'A';";

$result = mysql_query($query);
$row = mysql_fetch_assoc($result);

$rowId = $row['id'];
$oldIP = $row['val'];

if($oldIP == $newIP){
    echo "No update. IP has not changed since last update: " . $newIP;
    echo "good ".$newIP;

// Update IP
$updateQuery = "UPDATE dns_recs SET val = '$newIP', displayVal = '$newIP' WHERE id = $rowId;";

$updated = mysql_query($updateQuery ) or die (mysql_error());

$updateDomain = $_GET['domain'] . ";";
# Create do-update file to notice cron job to update the DNS entry
file_put_contents($DoUpdateFile, $updateDomain, FILE_APPEND);

echo "good ".$newIP;


And as requested in the comments my mysql_config.php file


$server = "localhost";
$user_server = "dnsupdateuser";
$password_server = "yourPassword";
$database= "psa";

$verbindung = mysql_connect ("$server", "$user_server", "$password_server")
or die ("connection failed. User and/or password incorrect.");

or die ("Database does not exist");

    1. Make sure you created the directory (updatefile/) and  your webserver user (mostly called www-data) has sufficient permissions to write in it.
    2. That done, the last step is to create a script to run the Plesk update. I decided for an hourly cron job, but you might prefer something else.
    3. My script called updatedynamicdns resides in /etc/cron.hourly. Make sure it is executable.
    4. The script checks if the doupdate file exists and if so, it runs the plesk dns update command for each hostname in the update file: /opt/psa/admin/bin/dnsmng --update hostname This reloads the DNS config for the specified host from the database and recreates the zone/key files. Afterwards the updatefile is deleted.

# log file

# update file

## do things

# check the update file exists. If not, do not update DNS record

if [ ! -s $updatefile ]
#       echo "$(date -R) Update file doesn't exist. No update necessary. Quitting." >> "$logfile"

domainList=`cat $updatefile`

# Split domain list by ;
IFS=';' read -ra domainsArr <<< "$domainList"

# Iterate over all domains in the array and update them one by one
for domain in "${domainsArr[@]}"; do

echo "$(date -R) Updating DNS entry for $domain" >> "$logfile"

# Update DNS entry for $domain via PLESK
/opt/psa/admin/bin/dnsmng --update $domain


# delete update file
rm $updatefile


    1. After all that done you can test you own DDNS: Open the update page in your web browser, e.g. http://dyn.example.com/?domain=home.example.com. (You should see the login page first)
    2. Check if the doupdate file was created correctly. If so, you can either wait for the hourly cron job to run or start the script yourself.
    3. Now check the file /var/named/run-root/var/home.example.com There you should now see the new IP instead of the IP of your server.
    4. After that it is just a matter of time until your DNS record has been properly propagated and you can reach your home from anywhere