Compare commits

...

14 Commits

Author SHA1 Message Date
IamTheFij b5e99939fb Back to alpine. This is dumb
continuous-integration/drone/push Build is failing Details
2021-01-20 18:21:40 -08:00
IamTheFij 01dc2dd149 Drop back cloudflare version
continuous-integration/drone/push Build is failing Details
2021-01-20 18:14:44 -08:00
IamTheFij 4702310823 Try to go back to py3.8
continuous-integration/drone/push Build is failing Details
2021-01-20 17:56:36 -08:00
IamTheFij aef73188f2 Add setuptools back
continuous-integration/drone/push Build was killed Details
2021-01-20 17:50:17 -08:00
IamTheFij 9a8445e6ec switch to slim python
continuous-integration/drone/push Build was killed Details
2021-01-20 17:42:27 -08:00
IamTheFij a752c67dad update setuptools
continuous-integration/drone/push Build is failing Details
2021-01-20 17:32:46 -08:00
IamTheFij 2c9b26a283 Switch pip method
continuous-integration/drone/push Build was killed Details
2021-01-20 17:27:33 -08:00
IamTheFij ff2d50b6e8 Fix drone builds on tags 2021-01-20 17:03:07 -08:00
IamTheFij d66c11cc00 Bump Cloudflare version to 2.8.15
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is failing Details
2021-01-20 16:38:51 -08:00
IamTheFij fdb3c744b0 Fix permissions on script
Was this broken for months?
2021-01-20 16:38:51 -08:00
IamTheFij d9b20c4759 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:54:19 -08:00
IamTheFij 2b41676824 Copy all qemu files because drone is being weird
continuous-integration/drone/push Build is passing Details
Change qemu version
2020-01-30 11:57:28 -08:00
IamTheFij 176feef895 Slightly reduce image size by removing pip cache 2020-01-30 11:09:32 -08:00
IamTheFij 3402b91b04 Contain entire build in Dockerfile
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is passing Details
Rather than pulling and storing the py file, having start script
and fetching of qemu files here, everything can just be done in the
Dockerfile.
2020-01-23 17:49:12 -08:00
8 changed files with 80 additions and 253 deletions

View File

@ -1,19 +1,16 @@
---
kind: pipeline
name: linux-amd64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
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
@ -25,30 +22,20 @@ steps:
from_secret: docker_username
password:
from_secret: docker_password
when:
branch:
- master
event:
- push
- tag
---
kind: pipeline
name: linux-arm
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
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
@ -62,31 +49,21 @@ steps:
from_secret: docker_password
build_args:
- ARCH=arm
- REPO=arm32v6
when:
branch:
- master
event:
- push
- tag
- REPO=arm32v7
---
kind: pipeline
name: linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
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
@ -101,12 +78,6 @@ steps:
build_args:
- ARCH=aarch64
- REPO=arm64v8
when:
branch:
- master
event:
- push
- tag
---
kind: pipeline
@ -117,6 +88,14 @@ depends_on:
- linux-arm
- linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: publish manifest
image: plugins/manifest
@ -128,10 +107,3 @@ steps:
from_secret: docker_username
password:
from_secret: docker_password
when:
branch:
- master
event:
- push
- tag

View File

@ -1,21 +1,28 @@
ARG REPO=library
FROM ${REPO}/python:3-alpine
FROM multiarch/qemu-user-static:4.2.0-2 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.8-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-* /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 +rx ./update_ddns.py
COPY ./start.sh ./
COPY ./update_ddns.py ./update_ddns.py
RUN python -m pip install --no-cache-dir 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
docker build --build-arg REPO=arm32v6 --build-arg ARCH=arm . -t ${DOCKER_TAG}-linux-arm
cross-build-arm:
docker build --build-arg REPO=arm32v7 --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()