Compare commits

...

7 Commits

Author SHA1 Message Date
IamTheFij 66efa5e17c Add repo links to README.md
continuous-integration/drone/push Build is passing Details
Should make it easier to finds the original source.
2020-02-22 07:52:16 -08:00
IamTheFij d6c46b5c10 README.md update to describe new contents
continuous-integration/drone/push Build is passing Details
Explains that this repo does not actually have any code and it merely
is an image wrapping an existing example script
2020-01-21 18:10:16 -08:00
IamTheFij 356071570a update drone pipelines for new Dockerfile
continuous-integration/drone/push Build is passing Details
2020-01-21 18:00:35 -08:00
IamTheFij 6ac78cbe89 Stop copying extra qemu files
continuous-integration/drone/push Build is passing Details
2020-01-21 17:52:45 -08:00
IamTheFij b11d6f6d88 WIP: Get started squashing things down 2020-01-21 17:46:39 -08:00
IamTheFij de8cf7aab8 WIP: Get started squashing things down 2020-01-21 17:44:02 -08:00
IamTheFij fea176f7f3 Update upstream example script 2020-01-21 17:29:05 -08:00
8 changed files with 43 additions and 225 deletions

View File

@ -2,18 +2,6 @@ kind: pipeline
name: linux-amd64
steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-x86_64-static
when:
branch:
- master
event:
- push
- tag
- name: build
image: plugins/docker
@ -37,18 +25,6 @@ kind: pipeline
name: linux-arm
steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-arm-static
when:
branch:
- master
event:
- push
- tag
- name: build
image: plugins/docker
@ -75,18 +51,6 @@ kind: pipeline
name: linux-arm64
steps:
- name: get qemu
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y make wget
- make build/qemu-aarch64-static
when:
branch:
- master
event:
- push
- tag
- name: build
image: plugins/docker

View File

@ -1,21 +1,27 @@
ARG REPO=library
FROM multiarch/qemu-user-static:4.1.0-1 as qemu-user-static
# Make sure a dummy x86_64 file exists so that the copy command doesn't error
RUN touch /usr/bin/qemu-x86_64-fake
FROM ${REPO}/python:3-alpine
# Copy mutliarch file to run builds on x86_64
ARG ARCH=x86_64
COPY ./build/qemu-${ARCH}-static /usr/bin/
COPY --from=qemu-user-static /usr/bin/qemu-${ARCH}-* /usr/bin/
RUN mkdir -p /src
WORKDIR /src
COPY ./requirements.txt ./
RUN pip install -r ./requirements.txt
# Get Cloudflare example script
ENV CF_VERSION=2.6.0
ADD https://raw.githubusercontent.com/cloudflare/python-cloudflare/$CF_VERSION/examples/example_update_dynamic_dns.py ./update_ddns.py
RUN chmod +x ./update_ddns.py
COPY ./start.sh ./
COPY ./update_ddns.py ./update_ddns.py
RUN pip install cloudflare==$CF_VERSION
ENV DOMAIN=""
USER nobody
CMD [ "/src/start.sh" ]
ENTRYPOINT [ "/src/update_ddns.py" ]

View File

@ -1,4 +1,5 @@
DOCKER_TAG ?= cloudflare-ddns-dev-${USER}
.PHONY: clean
.PHONY: default
default: test
@ -7,35 +8,25 @@ default: test
test:
@echo ok
.PHONY: update
update:
curl -o update_ddns.py https://raw.githubusercontent.com/cloudflare/python-cloudflare/master/examples/example_update_dynamic_dns.py
chmod +x update_ddns.py
.PHONY: build
build: build/qemu-x86_64-static
build:
docker build . -t ${DOCKER_TAG}
build/qemu-arm-static:
./get_qemu.sh arm
build/qemu-x86_64-static:
./get_qemu.sh x86_64
build/qemu-aarch64-static:
./get_qemu.sh aarch64
.PHONY: cross-build-arm
cross-build-arm: build/qemu-arm-static
cross-build-arm:
docker build --build-arg REPO=arm32v6 --build-arg ARCH=arm . -t ${DOCKER_TAG}-linux-arm
.PHONY: cross-build-arm64
cross-build-arm64: build/qemu-aarch64-static
cross-build-arm64:
docker build --build-arg REPO=arm64v8 --build-arg ARCH=aarch64 . -t ${DOCKER_TAG}-linux-arm64
.PHONY: all
all: build cross-build-arm cross-build-arm64
.PHONY: run
run: build
docker run --rm -e DOMAIN=${DOMAIN} \
docker run --rm \
-e CF_API_EMAIL=${CF_API_EMAIL} \
-e CF_API_KEY=${CF_API_KEY} \
${DOCKER_TAG}
${DOCKER_TAG} \
"${DOMAIN}"

View File

@ -1,21 +1,34 @@
# Docker Cloudfare DDNS
Simple Docker image to dynamically update a Cloudflare DNS record.
Simple Docker image that wraps an example script to dynamically update a Cloudflare DNS record.
## Usage
All parameters are passed to the script using env variables, so export the following:
There are two things to configure. First, the domain that you wish to update needs to be provided as a command line argument. This can be done by adding it to the end of your run command (example in the Makefile) or by adding it as a command to your compose file. Eg:
DOMAIN=sub.example.com
CF_API_EMAIL=admin@example.com
ddns:
image: IamTheFij/cloudflare-ddns
command: ["example.com"]
Your Cloudflare credentials can be passed in any way that [python-cloudflare](https://github.com/cloudflare/python-cloudflare) allows. Generally, either via envioronment variables:
CF_API_EMAIL=admin@example.com # Do not set if using an API Token
CF_API_KEY=00000000000000000000
CF_API_CERTKEY='v1.0-...'
Or by providing a file mounted to the working directory in the image, `/src/.cloudflare.cfg` that contains something like:
[CloudFlare]
emal = admin@example.com # Do not set if using an API Token
token = 00000000000000000000
certtoken = v1.0-...
Then run. To execute from this directory, you can use the convenient Make target.
make run
## Development
## Source
The script is straight from the examples provided by Cloudflare on their Github. The latest version can be downloaded using:
Original source: https://git.iamthefij.com/iamthefij/docker-cloudflare-ddns
make update
Github mirror: https://github.com/iamthefij/docker-cloudflare-ddns

View File

@ -1,13 +0,0 @@
#! /bin/bash
HOST_ARCH=x86_64
VERSION=v2.9.1-1
mkdir -p build
cd build
for target_arch in $*; do
wget -N https://github.com/multiarch/qemu-user-static/releases/download/$VERSION/${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
tar -xvf ${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
rm ${HOST_ARCH}_qemu-${target_arch}-static.tar.gz
done

View File

@ -1 +0,0 @@
cloudflare

View File

@ -1,3 +0,0 @@
#! /bin/sh
exec /src/update_ddns.py $DOMAIN

View File

@ -1,139 +0,0 @@
#!/usr/bin/env python
"""Cloudflare API code - example"""
from __future__ import print_function
import os
import sys
import re
import json
import requests
sys.path.insert(0, os.path.abspath('..'))
import CloudFlare
def my_ip_address():
"""Cloudflare API code - example"""
# This list is adjustable - plus some v6 enabled services are needed
# url = 'http://myip.dnsomatic.com'
# url = 'http://www.trackip.net/ip'
# url = 'http://myexternalip.com/raw'
url = 'https://api.ipify.org'
try:
ip_address = requests.get(url).text
except:
exit('%s: failed' % (url))
if ip_address == '':
exit('%s: failed' % (url))
if ':' in ip_address:
ip_address_type = 'AAAA'
else:
ip_address_type = 'A'
return ip_address, ip_address_type
def do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type):
"""Cloudflare API code - example"""
try:
params = {'name':dns_name, 'match':'all', 'type':ip_address_type}
dns_records = cf.zones.dns_records.get(zone_id, params=params)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones/dns_records %s - %d %s - api call failed' % (dns_name, e, e))
updated = False
# update the record - unless it's already correct
for dns_record in dns_records:
old_ip_address = dns_record['content']
old_ip_address_type = dns_record['type']
if ip_address_type not in ['A', 'AAAA']:
# we only deal with A / AAAA records
continue
if ip_address_type != old_ip_address_type:
# only update the correct address type (A or AAAA)
# we don't see this becuase of the search params above
print('IGNORED: %s %s ; wrong address family' % (dns_name, old_ip_address))
continue
if ip_address == old_ip_address:
print('UNCHANGED: %s %s' % (dns_name, ip_address))
updated = True
continue
# Yes, we need to update this record - we know it's the same address type
dns_record_id = dns_record['id']
dns_record = {
'name':dns_name,
'type':ip_address_type,
'content':ip_address
}
try:
dns_record = cf.zones.dns_records.put(zone_id, dns_record_id, data=dns_record)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones.dns_records.put %s - %d %s - api call failed' % (dns_name, e, e))
print('UPDATED: %s %s -> %s' % (dns_name, old_ip_address, ip_address))
updated = True
if updated:
return
# no exsiting dns record to update - so create dns record
dns_record = {
'name':dns_name,
'type':ip_address_type,
'content':ip_address
}
try:
dns_record = cf.zones.dns_records.post(zone_id, data=dns_record)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones.dns_records.post %s - %d %s - api call failed' % (dns_name, e, e))
print('CREATED: %s %s' % (dns_name, ip_address))
def main():
"""Cloudflare API code - example"""
try:
dns_name = sys.argv[1]
except IndexError:
exit('usage: example-update-dynamic-dns.py fqdn-hostname')
host_name, zone_name = dns_name.split('.', 1)
ip_address, ip_address_type = my_ip_address()
print('MY IP: %s %s' % (dns_name, ip_address))
cf = CloudFlare.CloudFlare()
# grab the zone identifier
try:
params = {'name':zone_name}
zones = cf.zones.get(params=params)
except CloudFlare.exceptions.CloudFlareAPIError as e:
exit('/zones %d %s - api call failed' % (e, e))
except Exception as e:
exit('/zones.get - %s - api call failed' % (e))
if len(zones) == 0:
exit('/zones.get - %s - zone not found' % (zone_name))
if len(zones) != 1:
exit('/zones.get - %s - api call returned %d items' % (zone_name, len(zones)))
zone = zones[0]
zone_name = zone['name']
zone_id = zone['id']
do_dns_update(cf, zone_name, zone_id, dns_name, ip_address, ip_address_type)
exit(0)
if __name__ == '__main__':
main()