Compare commits

...

18 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
IamTheFij c1125b9310 Fix incorrect phony make target 2020-01-10 13:38:09 -08:00
IamTheFij 1cb69ad575 Drop to nobody from root
continuous-integration/drone/push Build is passing Details
2019-06-03 16:00:31 -07:00
IamTheFij 8a39181d22 Switch from bash to sh
continuous-integration/drone/push Build is passing Details
2019-03-11 09:11:29 -07:00
IamTheFij 52dced87a8 Add multiarch building from Drone
continuous-integration/drone/push Build is passing Details
2019-03-10 18:09:12 -07:00
9 changed files with 197 additions and 162 deletions

109
.drone.yml Normal file
View File

@ -0,0 +1,109 @@
---
kind: pipeline
name: linux-amd64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: build
image: plugins/docker
settings:
repo: iamthefij/cloudflare-ddns
auto_tag: true
auto_tag_suffix: linux-amd64
username:
from_secret: docker_username
password:
from_secret: docker_password
---
kind: pipeline
name: linux-arm
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: build
image: plugins/docker
settings:
repo: iamthefij/cloudflare-ddns
auto_tag: true
auto_tag_suffix: linux-arm
username:
from_secret: docker_username
password:
from_secret: docker_password
build_args:
- ARCH=arm
- REPO=arm32v7
---
kind: pipeline
name: linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: build
image: plugins/docker
settings:
repo: iamthefij/cloudflare-ddns
auto_tag: true
auto_tag_suffix: linux-arm64
username:
from_secret: docker_username
password:
from_secret: docker_password
build_args:
- ARCH=aarch64
- REPO=arm64v8
---
kind: pipeline
name: manifest
depends_on:
- linux-amd64
- linux-arm
- linux-arm64
trigger:
event:
- push
- tag
refs:
- refs/heads/master
- refs/tags/v*
steps:
- name: publish manifest
image: plugins/manifest
settings:
spec: manifest.tmpl
auto_tag: true
ignore_missing: true
username:
from_secret: docker_username
password:
from_secret: docker_password

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
qemu-*
*.tar.gz
tags

View File

@ -1,14 +1,28 @@
FROM python:3-alpine
ARG REPO=library
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 --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=""
CMD [ "/src/start.sh" ]
USER nobody
ENTRYPOINT [ "/src/update_ddns.py" ]

View File

@ -1,18 +1,32 @@
DOCKER_TAG ?= cloudflare-ddns-dev-${USER}
.PHONY: clean
.PHONY: default
default: test
.PHONY:test
test:
@echo ok
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:
docker build . -t ${DOCKER_TAG}
.PHONY: cross-build-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:
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

25
manifest.tmpl Normal file
View File

@ -0,0 +1,25 @@
image: iamthefij/cloudflare-ddns:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: iamthefij/cloudflare-ddns:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: iamthefij/cloudflare-ddns:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
variant: v8
-
image: iamthefij/cloudflare-ddns:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
platform:
architecture: arm
os: linux
variant: v7

View File

@ -1 +0,0 @@
cloudflare

View File

@ -1,3 +0,0 @@
#! /bin/bash
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()