This tutorial will show you how to configure ddclient on Raspbian and Ubuntu. Many tutorials don't explain what to do if your server is behind a router, but this one will. I recently set up a backup server on an internet connection that has a dynamic IP address. So far, I've been spoiled at home because my ISP (PlusNet) makes switching to a static IP address easy and cheap, so obviously I did that. This time though, I didn't have that option, and I didn't want to configure a dynamic dns client on that router either, so I had to set it up on the server itself.
Some DNS providers offer their own dynamic DNS clients, but most of them are proprietary. The one I am going to use is called ddclient, it's free and open source, and written in Perl. Use this command to install ddclient:
sudo apt-get install ddclient
Enable dynamic DNS with your DNS provider
If you're not using namecheap, then this section will be different, but the concept is the same regardless of DNS provider. Log into namecheap and select the relevant domain, then choose "Dynamic DNS" under Miscellaneous settings. Use the radio buttons to enable dynamic DNS, and then make a note of the password. It should go without saying, but be really careful what you do with this password - anyone with access to it could change any DNS record for your domain that they wanted to. Unfortunately, namecheap doesn't let you restrict the dynamic DNS to just one subdomain. Next, navigate to "All host records" add a DNS A record for your domain (use the @ symbol for this), or subdomain. Use the dummy IP address
127.0.0.1 for now, the first time we run ddclient this will be updated to your actual Wide Area Network (WAN) IP address.
Now you have everything you need to configure ddclient. The main configuration file for ddclient is at
/etc/ddclient.conf, you can open this file to edit it with a text editor of your choice - this command will open it in nano:
sudo nano /etc/ddclient.conf
Here is a sample "normal" configuration file for ddclient:
protocol=namecheap server=dynamicdns.park-your-domain.com login=yourdomain.com password='password' subdomain
- protocol is set by your dynamic DNS provider. For namecheap the value is "namecheap"
- server is the hostname of the dynamic DNS server. The dynamic DNS servers used by namecheap are located at "dynamicdns.park-your-domain.com"
- login is your domain name
- password is the string we obtained earlier from the namecheap web interface. Leave the single quotation marks around the string.
- The last line is the subdomain to be modified. In my case this was backup, for backup.samhobbs.co.uk. If you wanted to update your root domain, you would put an @ symbol on this line instead
WAN IP discovery
The above configuration would work fine if ddclient was installed on a router, since the router knows your WAN IP address. However, it doesn't work if your server is behind a router because the server only knows its Local Area Network (LAN) IP address. There is a configuration parameter called
use, which determines the method ddclient uses to find the WAN IP. - if you specify this parameter, it must go above the rest of the configuration in the file. If you specify it below, it won't work! This caused me quite a lot of grief. The default value for
if, which uses information from the netwrok interface (think
ifconfig). If you have multiple network interfaces, you can specify which one like
use=if, if=eth0 for ethernet,
if=lo for the loopback address,
if=wlan0 for wireless LAN etc. However, none of these will work for us because none of them will give the WAN IP. There are two more types of value you can set:
web, and router firmware values like
Getting your WAN IP from your router's status page
Although I haven't opted for the router firmware method, I think it's quite interesting and worth discussing. Router firmware settings look something like this:
use=fw, fw=192.168.1.1/status.htm, fw-login=admin, fw-password=admin, fw-skip='IP Address'
fw= sets the location of the status page for that particular router containing the WAN IP address. If the status page is not available to unauthenticated users, you must set the username and password to allow ddclient to authenticate with the router.
fw-skip tells ddclient to ignore any IP address on the status page you specified before a certain string, in this case 'IP Address'. Some popular router manufacturers have their own settings for ease of use, for example if you have a Linksys router you can use this line:
use=linksys, fw=linksys, fw-login=admin, fw-password=admin
Note that since a lot of routers won't let more than one user log in as admin at a time, you could potentially prevent ddclient from updating your dynamic IP address if you are logged in yourself at the same time.
Getting your WAN IP address from a web service
web method involves ddclient querying one of the many "what is my ip" type web services on the internet, and extracting your IP address from the page returned. You can tell ddclient to use this method by using this line:
Similarly to other methods, you can also specify which website to use with the
web-skip parameter. Some options with preset values are
loopia, although you can use any site you like. For example, you could use somedomain.com by setting
use=somedomain.com, with an appropriate
web-skip-pattern=foo to ignore IP addresses before the string "foo" if necessary..
Remember how I said anyone with your dynamic dns password can change your DNS records? Sending your password via http (not https) is a bad idea. This parameter will force https:
Again, this needs to go above the
protocol parameter in your config file. For this to work, you need a perl library that can use SSL. Install it with this command:
sudo apt-get install libio-socket-ssl-perl
Testing your configuration
You can check if the pre-defined
use values can detect your WAN IP by running this command:
sudo ddclient -query
If your server is connected with an ethernet cable, the output should look something like this:
use=if, if=lo address is 127.0.0.1 use=if, if=p2p1 address is 192.168.1.119 use=if, if=wlan0 address is NOT FOUND use=web, web=dnspark address is 188.8.131.52 use=web, web=dyndns address is 184.108.40.206 use=web, web=loopia address is 220.127.116.11
To test your ddclient configuration with really verbose output, printing all possible configuration parameters and their values, you can use this command:
sudo ddclient -debug -verbose -noquiet
I won't print a sample output because it's too long, but somewhere near the bottom you should see a line like this:
SUCCESS: updating backup: good: IP address set to 18.104.22.168
While we've got all this information, It's worth checking to make sure you are actually using SSL to connect to your dynamic DNS provider. Look for lines like this:
CONNECT: dynamicdns.park-your-domain.com CONNECTED: using SSL
Run ddclient as a daemon
Since we don't just want the IP address to update once, we still need to set up ddclient to run as a daemon so it can check for a change of IP address periodically and notify the dynamic DNS provider if necessary. To start the daemon we need to open another configuration file,
/etc/default/ddclient and set:
You will notice there is a
daemon_interval parameter there too, I think the default value of 300 seconds (5 minutes) is reasonable, so I didn't change it. Save and close the file, and then run:
sudo service ddclient start
to start the daemon, and:
sudo service ddclient status
to check its status. ddclient keeps a cache of your IP address, and it will only update the record with your dynamic DNS provider if your IP address has changed. Since some ISPs seem to only allocate new IP addresses when the modem is power cycled, and some dynamic DNS providers will time out if you don't update the record in a while, there is one thing left to do - we need to add a cron job to force an update weekly, just in case. Choose whether you want to force an update daily or weekly, and then create a file called ddclient in the relevant directory, e.g.
sudo nano /etc/cron.daily/ddclient
Fill in this information:
#!/bin/sh /usr/sbin/ddclient -force
Then make the script executable:
sudo chmod +x /etc/cron.daily/ddclient
I am new to the Raspberry. I have followed your excellent tutorial and setup DDNS with NameCheap using ddclient. My domain is annapolisbluebird.com which I have set up for my Raspberry on a sailboat in a marina so I can keep track of critical parameters on my boat. The Raspberry is connected to the Internet with a WiFi connection through a router. Using hcidata I come up with an IP address for that domain. I can ping to it. The problem when I try to make a Putty or VNC connection, I get the error message that the server has actively refused the connection. Not sure what the problem is.
I have used ssl=yes and use=web at the beginning of the configuration file. I assume these settings are for communications with NameCheap, but it appears there may be some kind of authentication problem with Putty.
Yes, I control the router and have set port forwarding for port 22 to the Raspberry. The router is Netgear WNDR4300. Are there other ports that need to be forwarded for Putty and VNC?
I have it all working now. I changed ddclient.conf to the following:
use web, web=dynamicdns.park-your-domain.com/getip
This is what NameCheap specifies. On the port issues I added port 5902 to the port forwarding of the router. This was in addition to forwarding port 22. I do use a static IP there for the Raspberry. With VNC viewer I connect to the external DDNS IP using port 5902. Both Putty and VNC now work remotely. When I actually put my Raspberry and Interface Board on my boat in the marina (right now it is in my shop...smile), I will probably have more router problems.
As other people have said, thank you for an excellent tutorial and rapid response to questions
One change I found from your tutorial is that NameCheap has apparently changed their server address to parkingpage.namecheap.com from dynamicdns.park-your-domain.com. I have used the new address in the ddclient.conf file.
I'm a total newbie but this guided me thru the dynamic dns setup with ease. Had the same issue as others with not using ssl, but cache clear sorted this out.
Thanks for making the guide!
Thanks a lot for this efficient tutorial, you save me so much time !
Hello Mr Hobbs,
Thanks for your magnificent guide. I was having a lot of trouble with PIA VPN and getting my DDNS to update to the correct public IP address. I switched from the no-ip script (noip2) to a ddclient and it just works. I did have some trouble with using ssl (https) instead of http but I kept changing my "if=web, web=******" to a suitable https://"ip look up site". The only problem I currently have is I have to wait 10 minutes for the ddclient to update to the correct public IP address on reboots (first ddns ip on reboot is the last cached one, second is just slightly wrong for some reason, third is corrected and stays updated). And on an unrelated note my router or computer is blocking forwarded ports so I cant test remote ssh connects.
If you have any ideas on getting the wright ddns on reboot, that would be fantastic, otherwise thanks again!!!!
Also FYI, my config for those trying similar things, ddns:no-ip.com, vpn: PIA VPN, comp: Rasberry PI, OS: Rasbian. comp use: headless remote server.
Thanks for your response, forgive me if I've misunderstood.
You're saying that I wont be able to connect to my box running a openvpn service because a public (external to lan) remote request will give me an incorrect public IP address to the box?
Wouldn't the ddclient getting the public ip from the web route give me my openvpn public ip? And from there my router will direct the forwarded port to the box?
i.e. outside web ssh request>openvpn public ip>router port>box on the inside.
Again sorry if I have misunderstood your previous comment.
Thanks once again Sam for all your stuff. I've been running the pi mail server for 2 years now with no issues. Arrived back here because of an issue with my internet connection and closed down my dynamic dns temporarily. But now they seem to have sorted out the connection so I needed to remind myself of the client config information...
Please keep your pages going, I keep thinking I should take hard copies in case you decide to delete them, but there's a lot there!
it's me again. You helped me a lot last year. Now I'm totally lost. Last year I was able to manage that the domain dns was setup to use duckdns for updating the ip for using raspi as mail server. But now I'm totally lost. Followed every step from your tutorial. So postfix and dovecot run fine so far. But the dns entries are killing me. What to set where? I't can't figure it out.
The ddclient command gives me this out:
RECEIVE: Current IP CheckCurrent IP Address: 22.214.171.124
DEBUG: get_ip: using web, http://checkip.dyndns.org/ reports 126.96.36.199
WARNING: skipping update of thisismydomaintobeupdated.com from to 188.8.131.52.
WARNING: last updated but last attempt on Sun Dec 23 23:41:02 2018 failed.
WARNING: Wait at least 5 minutes between update attempts.
Don't know what. I added a txt entry so far in dns section for spf ptr, but the error happened before too. have an mx record set:
Type Host Value TTL
MX Record @ thisisthedomaintobeupdated.com. 10 Automatic
Thanks in advance for reading this.
Kind regards from germany
happy new year to you and your beloved ones. Thanks for your support. My MX-entry was missing :o( - sorry.
I fixed it and all runs well now. The only problem I have is my IP-range (because dynamic) is in the bad list on spamhaus. So it will only be delivered to spam every time I send one (to myself atm). SPF setting throws errors in the mx-check on google dev tools. But the more important point is that all mail marketing tools I wanted to use are not running on raspi. Some dependencies or whatever are missing not fixable for a noob like me. I learned a lot and tried day in night out but know I'm at the point to make it easier for me and - so I think atm - to take things over to aws on amazon cloud services. And that's where my question begins and adds up.
Will all these steps to make the mailserver running be possible on aws cloud server? I stuck in thinking. Because I never used aws before and don't know what then have to be changed in the scripts. Do I have to use dynamic dns service (ddclient) again or does this work another way round? Do you have any experience with that?
Thanks and warm regards
that sounds good so far. AWS offers elastic ip, I guess this is not the same like the static one? A static ip from my isp is not possible since I'm not a business at the moment. As a private I can't have one, german telekom :o(
I'm a bit confused now.
Read you soon.
thanks for your good reply. I assigned the elastic IP as the instance was running. But the elastic IP is not the Public IP mentioned in the instance entry. Don't know, but it's accessible throught the public IP.
The mail server is up and running. At this very moment I ended to configure postfix for spamassassin from your tutorial. But now :) I can't login through the web panel "Authorization failed" rainloop is saying to me. And I don't get it, what happened. I don't think it has something to do with the other. But as I mentioned before. I'm not a UNIX/LINUX professional. I have to look up every problem in forums and other web sources.
Before the problem existed, I tried to send an email to the email from configured but it didn't arrive supervising the mail.log showed no response as if nothing was put through to em. The IP was renewed through ddclient. I thought this time it could be a little easier ... but "Hey, take this and that". I don't want to give this up, but I guess I'm too stupid to figure this out.
Nice to hear from you.
the "use=" part helped me a lot on my case which is "a local IP in NAT behind the router which has a public IP"
I was wondering how my server can DDNS update with ddclient.
This is like my go-to post to configure ddclient and has been for a few years! Cheers for that! :)
I was wondering if you can help me with what I think is a simple problem but perhaps isn't.
I'm trying to update my A+ records, for @ and www, so that `blah.tld` and `www.blah.tld` both point to my IP.
I can't seem to get the last line right in the .conf. Namecheap told me to put `blah.tld,www.blah.tld` but it didn't work that I could see (I set the IPs in namecheap advanced dns panel A+ records to 127.0.0.0 to see that they'd changed)
I've tried '@,wwww' but also no luck.
Have you any experience of this?
That sounds perfect, Sam! Thank you kindly, I'll look into it.
I have two different DNS providers. I have two websites with one provider and two different websites with the other. With one of the providers, I could update multiple hosts on one line (blah.tld, www.blah.tld). With the other, I had to have separate entries for each host:
It took me a loooong time figure this out as a single line worked perfectly with one of the providers.
Hope this helps!
That's a very useful piece of information to share, Charles, thank you kindly! I did not know you could use/include multiple .conf files - this is what you are implying? I'll find out soon :)
No, I was not trying to imply include files. All of the hosts are in a single .conf file. One mistake I did make, was not putting a "\" (backslash) after the login and the password lines. Also, I left off the protocol and server info.
What I was trying to show was the login, password and sub-domains had to be separate, complete entries for each sub-domain.
Here is a more complete example:
#The following is common to both DNS providers:
#Get the public ip address of this machine. Note, the "https://" is needed, otherwise, the response will be too slow and will time out.
#This is unique to zoneedit. Other DNS providers don't require it. Also, setting SSL=yes, prior to this statement, does not solve
# the "https" problem. See my comment on 8 September 2016, for more detail.
#Zoneedit specific parameters, all sub-domains may be on one line.
login=xxx password=yyy blah1.tld, www.blah1.tld
#Hurricane Electric specific parameters, sub-domains must be on separate lines.
login=xxx password=yyy blah.tld
login=xxx password=yyy www.blah.tld
Hope this helps!
Let me know if you have any questions.
Based on Charles great info (and this tutorial), I finally got a working SSL config for multiple subdomains on namecheap.
Here follows a sanitized copy for www.mylogin.tld and mylogin.tld
# Configuration file for ddclient generated by debconf
use=web, web=dynamicdns.park-your-domain.com/getip # look up external IP from this URL
syslog=yes # log the output to syslog
ssl=yes # use ssl when updating IP
# @ record
# www record
Thank you Charles
Congratulations on figuring it out. Sometimes the simplest things can be the hardest!
I'm glad I was able to help! Thank you for letting me know :-)
Great tutorial, thanks for the work! Since it's already online for a while you might want to update it to use the newer 3.9.0 ddclient (not in raspberry repo). This supports cloudflare out of the box which is a great addition. Manual install and link to updated ddclient: https://www.cloudflare.com/technical-resources/#ddclient Work flawless in combination with your tutorial.
Two things I noticed, I had to install libdata-validate-ip-perl as well. Could well be a default dependency when installing ddclient from repo though. Cloudflare does not require an update every month, so a cron job is not needed. Second, the command: $ sudo ddclient -debug -verbose -noquiet did not give any output. Perhaps something changed there?