Coder Social home page Coder Social logo

digitalocean-dynamic-dns-ip's Introduction

DIGITAL OCEAN DYNAMIC IP API CLIENT

A simple script in Go language to automatically update Digital ocean DNS records if you have a dynamic IP. Since it can be compiled on any platform, you can use it along with raspberrypi etc.

To find your Dynamic IP, this program will call out to https://api.ipify.org/ for ipv4 addresses and https://api64.ipify.org/ for ipv6 addresses. This is to support dual-stack environments. (These URLs can be customized; see Usage, below.)

Requirements

  • The record must already exist in DigitalOcean's DNS so that it can be updated. (manually find your IP and add it to DO's DNS it will later be updated)
  • A Digital Ocean API key that can be created at https://cloud.digitalocean.com/account/api/tokens.

Installation

Download the prebuilt binaries from releases,

or Build from source

# Requires Git, Go 1.8+(GO 1.11 if you want to use GO111MODULE=on).
# clone the repo in ~/go/src/github.com/anaganisk:
git clone https://github.com/anaganisk/digitalocean-dynamic-dns-ip.git
# Skip to next step, if you have GO111MODULE=on in your environment it is fetched automatically
go get github.com/mitchellh/go-homedir
# build the project
go build

Usage

Create a file .digitalocean-dynamic-ip.json (dot prefix to hide the file) and place it in your home directory. Add the following JSON (or refer to the sample configuration file, digitalocean-dynamic-ip.sample.json):

{
  "apikey": "samplekeydasjkdhaskjdhrwofihsamplekey",
  "doPageSize": 20,
  "useIPv4": true,
  "useIPv6": false,
  "allowIPv4InIPv6": false,
  "ipv4CheckUrl": "https://api.ipify.org/?format=text",
  "domains": [
    {
      "domain": "example.com",
      "records": [
        {
          "name": "subdomainOrRecord",
          "type": "A"
        }
      ]
    },
    {
      "domain": "example2.com",
      "records": [
        {
          "name": "subdomainOrRecord2",
          "type": "A",
          "TTL": 30
        }
      ]
    }
  ]
}

The TTL can optionally be updated if passed in the configuration. Digital Ocean has a minimum TTL of 30 seconds. The type and the name must match existing records in the Digital Ocean DNS configuration. Only types of A and AAAA allowed at the moment. Use the name of "@" to update a the top level domain record itself instead of a sub domain.

If you want to reduce the number of calls made to the digital ocean API and have more than 20 DNS records in your domain, you can adjust the doPageSize parameter. By default, Digital Ocean returns 20 records per page. Digital Ocean has a max page size of 200 items.

By default, the configuration checks both IPv4 and IPv6 addresses assuming your provider set up your connection as dual stack. If you know you only have ipv4 or ipv6 you can disable using one or the other in the config. To disable one or the other, set the useIPv4 or useIPv6 settings to false. If the options aren't present, or are set to null, then the configuration assumes a value of true.

The allowIPv4InIPv6 configuration option will allow adding an IPv4 address to be used in a AAAA record for IPv6 lookups.

The ipv4CheckUrl and ipv6CheckUrl configuration settings are optional. If set, they must be URLs which respond to a GET request, with a plaintext response containing only your IP address. If unset, they default to https://api.ipify.org/?format=text and https://api64.ipify.org/?format=text respectively.

# after running `go build digitalocean-dynamic-ip.go`, run:
./digitalocean-dynamic-ip

Optionally, you can create the configuration file with any name wherever you want, and pass it as a command line argument:

#run:
./digitalocean-dynamic-ip /path/to/my/config.json

By default the tool will not output anything on success. If you wish to see debug messages, you can use the -d or -debug command flags. All debug messages will be printed to Standard Out, while warnings and fatal errors will be printed to Standard Error. Warnings and Error messages are always printed regardless of the -d/-debug flag usage.

#run:
./digitalocean-dynamic-ip -debug /path/to/my/config.json

You can either set this to run periodically with a cronjob or use your own method.

# run `crontab -e` to edit your crontab
# sample cron job task

# m h  dom mon dow   command
*/5 * * * * /home/user/digitalocean-dynamic-dns-ip/digitalocean-dynamic-ip

digitalocean-dynamic-dns-ip's People

Contributors

anaganisk avatar cdzombak avatar johnjaylward avatar josharrington avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

digitalocean-dynamic-dns-ip's Issues

IP lookup API not longer provided by third-party

From whatismyipaddress.com:

Public IP Address
As of November 10, 2021 we are no longer providing this API due to massive abuse.

bot.whatismyipaddress.com – Responds to IPv4 & IPv6 queries – This API is no longer available
ipv4bot.whatismyipaddress.com – Responds to IPv4 queries only – This API is no longer available
ipv6bot.whatismyipaddress.com – Responds to IPv6 queries only – This API is no longer available

This completely breaks the script. Could we replicate the response on a second service and pass that URL as a config param? Any examples of what the old response was?

0 of x records updated

Hello,

I have spun up a Docker container to test your service utility, it's exactly what I was looking for. When I run the command, it successfully reads the config file, but reports "0 of 1 records updated". The API key I'm using has Read/Write Scope. I'm not sure if I'm overlooking something in the config.

Thank you

TD

root@160b0ec7a0ed:/tmp/digitalocean-dynamic-dns-ip# go version
go version go1.13.13 linux/amd64
root@160b0ec7a0ed:/tmp/digitalocean-dynamic-dns-ip# ./digitalocean-dynamic-dns-ip
2021/09/06 22:26:17 Discovered IPv4 address `24.116.xx.xx`
2021/09/06 22:26:17 mydomain.com: START
2021/09/06 22:26:17 mydomain.com: 1 to update
2021/09/06 22:26:17 https://api.digitalocean.com/v2/domains/mydomain.com/records
2021/09/06 22:26:17 https://api.digitalocean.com/v2/domains/mydomain.com/records?page=2&per_page=20
2021/09/06 22:26:18 https://api.digitalocean.com/v2/domains/mydomain.com/records?page=3&per_page=20
2021/09/06 22:26:18 mydomain.com: 45 DNS records found in DigitalOcean
2021/09/06 22:26:18 mydomain.com: trying to update `A` : `subdomainOrRecord`
2021/09/06 22:26:18 mydomain.com: 0 of 1 records updated
2021/09/06 22:26:18 mydomain.com: END
root@160b0ec7a0ed:/tmp/digitalocean-dynamic-dns-ip# 

{
  "apikey": "<key_obfuscated>",
  "doPageSize": 20,
  "useIPv4": true,
  "useIPv6": false,
  "allowIPv4InIPv6": false,
  "ipv4CheckUrl": "https://ipv4bot.whatismyipaddress.com",
  "domains": [
    {
      "domain": "mydomain.com",
      "records": [
        {
          "name": "subdomainOrRecord",
          "type": "A"
        }
      ]
    }
  ]
}

Update domain A record

If I have domain xyz.com how do I update the A record for xyz.com?

I have it working for A records on subdomains ie. test.xyz.com

url.PathScape error when building

Hello there! thanks for your work. I was trying to just do the build of your script for two hours now. :(

First install go, then downloading dependences (go-homedir package....), now after all that, I get this error:
./digitalocean-dynamic-ip.go:177: undefined: url.PathEscap
./digitalocean-dynamic-ip.go:269: undefined: url.PathEscape

Its an ubuntu server 18 almost clean install

connect: cannot assign requested address

I am trying to understand why I cannot remedy this error msg.

Thank you in advance!

TD

Get https://ipv6bot.whatismyipaddress.com: dial tcp [2606:6e00:c000:1000::501]:443: connect: cannot assign requested address

My config file does not contain https://ipv6bot.whatismyipaddress.com as the lookup URL for IPV4

Config

{
  "apikey": "MY_DO_API_KEY",
  "doPageSize": 20,
  "useIPv4": true,
  "useIPv6": false,
  "allowIPv4InIPv6": false,
  "ipv4CheckUrl": "http://ipecho.net/plain",
  "domains": [
    {
      "domain": "mydomain.com",
      "records": [
        {
          "name": "my_subdomain",
          "type": "A"
        }
      ]
    }
  ]
}

I am running this in a docker container built with a Linuxserver.io base image.

services-admin@docker3:[10.10.0.5:67.61.xx.xx]~/DockerServices/dynamic_dns_updater$ docker run -it --rm -v "${PWD}/data":/data lsiobase/alpine:3.11 ash
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-envfile: executing... 
[cont-init.d] 01-envfile: exited 0.
[cont-init.d] 10-adduser: executing... 
usermod: no changes

-------------------------------------
          _         ()
         | |  ___   _    __
         | | / __| | |  /  \ 
         | | \__ \ | | | () |
         |_| |___/ |_|  \__/


Brought to you by linuxserver.io
-------------------------------------

To support LSIO projects visit:
https://www.linuxserver.io/donate/
-------------------------------------
GID/UID
-------------------------------------

User uid:    911
User gid:    911
-------------------------------------

[cont-init.d] 10-adduser: exited 0.
[cont-init.d] 90-custom-folders: executing... 
[cont-init.d] 90-custom-folders: exited 0.
[cont-init.d] 99-custom-files: executing... 
[custom-init] no custom files found exiting...
[cont-init.d] 99-custom-files: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# apk update && apk upgrade
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
v3.11.12-27-g76291da1fc [http://dl-cdn.alpinelinux.org/alpine/v3.11/main]
v3.11.11-124-gf2729ece5a [http://dl-cdn.alpinelinux.org/alpine/v3.11/community]
OK: 11275 distinct packages available
OK: 16 MiB in 30 packages
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# apk add build-base git curl go --no-cache
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/25) Installing libgcc (9.3.0-r0)
(2/25) Installing libstdc++ (9.3.0-r0)
(3/25) Installing binutils (2.33.1-r1)
(4/25) Installing libmagic (5.37-r1)
(5/25) Installing file (5.37-r1)
(6/25) Installing gmp (6.1.2-r1)
(7/25) Installing isl (0.18-r0)
(8/25) Installing libgomp (9.3.0-r0)
(9/25) Installing libatomic (9.3.0-r0)
(10/25) Installing mpfr4 (4.0.2-r1)
(11/25) Installing mpc1 (1.1.0-r1)
(12/25) Installing gcc (9.3.0-r0)
(13/25) Installing musl-dev (1.1.24-r3)
(14/25) Installing libc-dev (0.7.2-r0)
(15/25) Installing g++ (9.3.0-r0)
(16/25) Installing make (4.2.1-r2)
(17/25) Installing fortify-headers (1.1-r0)
(18/25) Installing build-base (0.5-r1)
(19/25) Installing nghttp2-libs (1.40.0-r1)
(20/25) Installing libcurl (7.79.1-r0)
(21/25) Installing curl (7.79.1-r0)
(22/25) Installing expat (2.2.9-r1)
(23/25) Installing pcre2 (10.34-r1)
(24/25) Installing git (2.24.4-r0)
(25/25) Installing go (1.13.13-r0)
Executing busybox-1.31.1-r10.trigger
OK: 506 MiB in 55 packages
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# git clone https://github.com/anaganisk/digitalocean-dynamic-dns-ip.git
Cloning into 'digitalocean-dynamic-dns-ip'...
remote: Enumerating objects: 114, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 114 (delta 1), reused 4 (delta 1), pack-reused 105
Receiving objects: 100% (114/114), 30.53 KiB | 512.00 KiB/s, done.
Resolving deltas: 100% (55/55), done.
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# cd digitalocean-dynamic-dns-ip/
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip#
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip#
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# go get github.com/mitchellh/go-homedir
go: finding github.com/mitchellh/go-homedir v1.1.0
go: downloading github.com/mitchellh/go-homedir v1.1.0
go: extracting github.com/mitchellh/go-homedir v1.1.0
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip#
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip#
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# go build
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# cp digitalocean-dynamic-dns-ip /usr/bin/
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# chmod +x /usr/bin/digitalocean-dynamic-dns-ip
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# apk del build-base curl git
(1/13) Purging build-base (0.5-r1)
(2/13) Purging file (5.37-r1)
(3/13) Purging g++ (9.3.0-r0)
(4/13) Purging make (4.2.1-r2)
(5/13) Purging libc-dev (0.7.2-r0)
(6/13) Purging fortify-headers (1.1-r0)
(7/13) Purging curl (7.79.1-r0)
(8/13) Purging git (2.24.4-r0)
(9/13) Purging libmagic (5.37-r1)
(10/13) Purging libcurl (7.79.1-r0)
(11/13) Purging nghttp2-libs (1.40.0-r1)
(12/13) Purging expat (2.2.9-r1)
(13/13) Purging pcre2 (10.34-r1)
Executing busybox-1.31.1-r10.trigger
OK: 424 MiB in 42 packages
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# ll /data/
ash: ll: not found
root@b8e3ee12893b:/digitalocean-dynamic-dns-ip# cd ..
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# rm -rf digitalocean-dynamic-dns-ip/
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# digitalocean-dynamic-dns-ip /data/digitalocean-dynamic-ip.json 
2021/10/20 18:36:43 Discovered IPv4 address `67.61.xx.xx`   <------- THIS IS CORRECT
2021/10/20 18:36:43 Get https://ipv6bot.whatismyipaddress.com: dial tcp [2606:6e00:c000:1000::501]:443: connect: cannot assign requested address
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# ls /data/
digitalocean-dynamic-ip.json
root@b8e3ee12893b:/#
root@b8e3ee12893b:/#
root@b8e3ee12893b:/# cat /data/digitalocean-dynamic-ip.json 
{
  "apikey": "MY_DO_API_KEY",
  "doPageSize": 20,
  "useIPv4": true,
  "useIPv6": false,
  "allowIPv4InIPv6": false,
  "ipv4CheckUrl": "http://ipecho.net/plain",
  "domains": [
    {
      "domain": "mydomain.com",
      "records": [
        {
          "name": "my_subdomain",
          "type": "A"
        }
      ]
    }
  ]
}

Alpine linunx in Docker

What is required to get this to run in an Alpine Linux Docker container?

/ # /usr/local/bin/digitalocean-dynamic-dns-ip-linux-amd64
sh: /usr/local/bin/digitalocean-dynamic-dns-ip-linux-amd64: not found
/ #

Definitely downloaded locally during build:

Connecting to github.com (52.64.108.95:443)
Connecting to github-releases.githubusercontent.com (185.199.109.154:443)
saving to '/usr/local/bin/digitalocean-dynamic-dns-ip-linux-amd64'
digitalocean-dynamic  30% |*********                       | 1953k  0:00:02 ETA
digitalocean-dynamic  85% |***************************     | 5553k  0:00:00 ETA
digitalocean-dynamic 100% |********************************| 6458k  0:00:00 ETA
'/usr/local/bin/digitalocean-dynamic-dns-ip-linux-amd64' saved

It works fine in my Debian Buster container but I was trying to make a smaller container on Alpine.

disabling ipv6 check has no effect?

it still tries to check even when the connection has no ipv6 and fails to update record for ipv4

2019/10/25 00:15:56 Discovered IPv4 address mypublicip
2019/10/25 00:15:56 Get https://ipv6bot.whatismyipaddress.com: dial tcp: lookup ipv6bot.whatismyipaddress.com: no such host

build it on windows from git
go version go1.13.3 windows/amd64

I can't seem to get this script to work

Hi there
I'm not sure if anyone is around to actively help with this, but I've followed ALL the instructions, and when I run the script, this is what I get (IPs committed for privacy)

umbrel@umbrel:~/digitalocean-dynamic-dns-ip $ ./digitalocean-dynamic-ip 2021/05/18 14:50:35 Discovered IPv4 address xxx.226.170.xxx2021/05/18 14:50:36 Discovered IPv6 addressxxxx:ed0:4338:6e00:6988:8434:xxxx:26fd``

However, when I log in to my DigitalOcean, the record has not been updated accordingly.
The API key is correct, I checked it twice.
Ideas?

Thanks in advance.

[request] Have an A+AAAA type

Hey,
I was wondering if it would make sense to create a type for both A and AAAA domains, since all my domains have both entries, and it creates a large duplication.

You could also just expand the json each time and then just handle this in the configuration loading and not in the actual dns update code. After the json.Unmarshal comand here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.