do-dyndns 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +39 -0
- data/bin/console +14 -0
- data/bin/dyndns +27 -0
- data/bin/setup +8 -0
- data/config.example.yml +4 -0
- data/lib/dyndns.rb +5 -0
- data/lib/dyndns/updater.rb +85 -0
- data/lib/dyndns/version.rb +3 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6acae6a533a232c1b1a6669a654a720a888ec149ab2caee17c08db14e81e5a11
|
4
|
+
data.tar.gz: '09b944f01f9b9aefbadfabb50c23c71a31981cee7817eb9117153d95ead2bd74'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db766ce0f59398b1834bf0e7f199730371aef8d0d41c64f1f912c07831bf4ddd25a2a3bf594a9c4233cc4f4697293138c493efc91c69f8983d65a39314f789d2
|
7
|
+
data.tar.gz: dacd17e32bce6057f759d0a4655aa0dd59da5110dbc6e26df48e3512f1ce9a12a2824002ca4d28f3b9ed974f97d1ca0ec1d9d61735e96426e2286312c1265d4d
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# DO-Dyndns
|
2
|
+
|
3
|
+
Automatically update DNS records on DigitalOcean
|
4
|
+
|
5
|
+
Finds the wan IPv4 address of the server it's running on and
|
6
|
+
updates the corresponding DNS records on digital ocean.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
`$ gem install do-dyndns`
|
10
|
+
|
11
|
+
## Configuration
|
12
|
+
Configuration is located at:
|
13
|
+
`~/.config/dyndns.yml`
|
14
|
+
|
15
|
+
if no config file is found, do-dyndns will create one and open it with your `$EDITOR`
|
16
|
+
|
17
|
+
```yaml
|
18
|
+
:token: your_digital_ocean_token_here
|
19
|
+
:domains:
|
20
|
+
example-domain1.com:
|
21
|
+
- example-subdomain1
|
22
|
+
```
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
```
|
26
|
+
$ dyndns
|
27
|
+
I, [2019-03-26T14:39:20.643564 #11387] INFO -- : Started IP check
|
28
|
+
I, [2019-03-26T14:39:20.720905 #11387] INFO -- : Current WAN IP: **.**.**.**
|
29
|
+
I, [2019-03-26T14:39:21.977426 #11387] INFO -- : IPs Match for ***.***.***
|
30
|
+
```
|
31
|
+
|
32
|
+
## Automation
|
33
|
+
|
34
|
+
### Cron:
|
35
|
+
Check every 15 minutes:
|
36
|
+
|
37
|
+
```
|
38
|
+
*/15 * * * * dyndns
|
39
|
+
```
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "dyndns"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/dyndns
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
lib = File.expand_path(File.join(__dir__, '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'logger'
|
8
|
+
require 'shellwords'
|
9
|
+
require 'dyndns'
|
10
|
+
|
11
|
+
LOG = Logger.new($stdout)
|
12
|
+
|
13
|
+
rpath = File.expand_path(File.dirname(__FILE__))
|
14
|
+
Dir.chdir rpath
|
15
|
+
|
16
|
+
config_path = File.expand_path "~/.config/dyndns.yml"
|
17
|
+
|
18
|
+
if File.exist? config_path
|
19
|
+
config = YAML.load_file config_path
|
20
|
+
Dyndns::Updater.new(**config, logger: LOG).update_ips
|
21
|
+
else
|
22
|
+
LOG.warn "No configuration exists @ #{config_path}: Creating file."
|
23
|
+
FileUtils.mkdir_p File.dirname(config_path)
|
24
|
+
FileUtils.cp("../config.example.yml", config_path)
|
25
|
+
editor = ENV['EDITOR'] || 'nano'
|
26
|
+
system "#{editor} #{Shellwords.shellescape(config_path)}"
|
27
|
+
end
|
data/bin/setup
ADDED
data/config.example.yml
ADDED
data/lib/dyndns.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Dyndns
|
2
|
+
class Updater
|
3
|
+
require 'droplet_kit'
|
4
|
+
|
5
|
+
def initialize(token:, domains:, logger: Logger.new($stdout))
|
6
|
+
@logger = logger
|
7
|
+
@domains = domains
|
8
|
+
@api = DropletKit::Client.new(access_token: token)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get the domains from DO's API and selecto only ones specified in the config
|
12
|
+
def domains
|
13
|
+
@api.domains
|
14
|
+
.all
|
15
|
+
.select{ |d| @domains.keys.include? d.name }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the config specified sub domains for a domain
|
19
|
+
# - param {DropletKit::Domain} domain - The domain object
|
20
|
+
def sub_domains_for(domain)
|
21
|
+
@api.domain_records
|
22
|
+
.all(for_domain: domain.name)
|
23
|
+
.select{ |r| r.type == "A" && @domains[domain.name].include?(r.name) }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Check if a record ip differs from your current ip
|
27
|
+
# - param {DropletKit::DomainRecord} record - A domain record
|
28
|
+
def ip_changed?(record)
|
29
|
+
raise "Cannot determine WAN IPv4" unless _ip = wan_ipv4
|
30
|
+
record.data != _ip
|
31
|
+
end
|
32
|
+
|
33
|
+
# Calls update on all configured domain's subdomains
|
34
|
+
def update_ips
|
35
|
+
@logger.info "Started IP check"
|
36
|
+
@logger.info "Current WAN IP: #{wan_ipv4}"
|
37
|
+
|
38
|
+
domains.each do |domain|
|
39
|
+
sub_domains_for(domain).each do |record|
|
40
|
+
if ip_changed?(record)
|
41
|
+
@logger.info "IPs Differ for #{record.name}.#{domain.name}"
|
42
|
+
update(domain, record)
|
43
|
+
else
|
44
|
+
@logger.info "IPs Match for #{record.name}.#{domain.name}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Update the associated domain with the current WAN IPv4 address
|
51
|
+
# - param {DropletKit::Domain} domain - The domain object
|
52
|
+
# - param {DropletKit::DomainRecord} record - A domain record
|
53
|
+
def update(domain, record)
|
54
|
+
@logger.info "Updating record #{record.name}.#{domain.name} from #{record.data} to #{wan_ipv4}"
|
55
|
+
record.data = wan_ipv4
|
56
|
+
@api.domain_records.update(record, for_domain: domain.name, id: record.id)
|
57
|
+
end
|
58
|
+
|
59
|
+
def wan_ipv4
|
60
|
+
resolve([
|
61
|
+
"dig -4 @resolver1.opendns.com ANY myip.opendns.com +short",
|
62
|
+
"dig -4 @ns1-1.akamaitech.net ANY whoami.akamai.net +short",
|
63
|
+
"dig -4 @ns1.google.com ANY o-o.myaddr.l.google.com +short"
|
64
|
+
])
|
65
|
+
end
|
66
|
+
|
67
|
+
def wan_ipv6
|
68
|
+
resolve([
|
69
|
+
"dig -6 @resolver1.opendns.com ANY myip.opendns.com +short",
|
70
|
+
"dig -6 @ns1.google.com ANY o-o.myaddr.l.google.com +short"
|
71
|
+
])
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def resolve(commands)
|
77
|
+
_ip = nil
|
78
|
+
commands.each do |service|
|
79
|
+
_ip = `#{service}`.chomp.gsub(/[^a-z0-9\:\.]/i, '')
|
80
|
+
_ip = _ip and break unless _ip.empty?
|
81
|
+
end
|
82
|
+
_ip.empty? ? nil : _ip
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: do-dyndns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Clink
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: droplet_kit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: |
|
70
|
+
Finds the wan IPv4 address of the server it's running on and
|
71
|
+
updates the corresponding DNS records on digital ocean.
|
72
|
+
email:
|
73
|
+
- alexclink@gmail.com
|
74
|
+
executables:
|
75
|
+
- dyndns
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files: []
|
78
|
+
files:
|
79
|
+
- README.md
|
80
|
+
- bin/console
|
81
|
+
- bin/dyndns
|
82
|
+
- bin/setup
|
83
|
+
- config.example.yml
|
84
|
+
- lib/dyndns.rb
|
85
|
+
- lib/dyndns/updater.rb
|
86
|
+
- lib/dyndns/version.rb
|
87
|
+
homepage: http://alexclink.com/gems/dyndns
|
88
|
+
licenses:
|
89
|
+
- UNLICENSED
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubygems_version: 3.0.3
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Automatically update DNS records on DigitalOcean
|
110
|
+
test_files: []
|