Suleman-Elahi / Cfddns

A no nonsense python script to treat Cloudflare as a dynamic DNS. Run as Docker container/scheduled task. Ipv4 and Ipv6 support.
MIT License
18 stars 2 forks source link

Docker image does not run the crontab #3

Closed Sorwrath closed 12 months ago

Sorwrath commented 1 year ago

Hello,

The crontab refuses to work after i build the image, i tried to ru it every minute, i added it also the cron.daily and cron.hourly. i even changed the structure to match the python3 command structure but it does not work, nor are any log files. The python3 manual command work fine from the docker image.

let me know what command output you want to see

edit:maybe it will work with https://github.com/aptible/supercronic

Suleman-Elahi commented 12 months ago

I am not sure what you are trying to say .. you want to use anacron?

Because for every minute, hour, and daily, you can just use these expressions

  1. * * * * * #every minute
  2. 0 * * * * #every hour
  3. 0 0 * * * #daily
Sorwrath commented 12 months ago

Hello,

Thank you for the reply. To clarify, the container was created, the manual python command works but the crontab is not working to automatically change the public ip in Cloudflare.

I tried different troubleshooting steps (like adding into different cron folders, and modify the command in crontab) but is not updating the public IP in Cloudflare, when i change the public IP at the DNS Records in CLoudflare for testing purposes. Also no logs are generated, i.e. in /var/logs. I have made the crontab with all * so it should update every minute, and i use proxy in my DNS record (value, is changed from False to True)

here is the python script from the /apps in my docker container

root@cb22abdc4aee:/app# cat cfddns.py 

import requests
import json
import re
import sys, time

################--CONFIG--#############################################################
requests.packages.urllib3.util.connection.HAS_IPV6 = False

record_id = ''
domain = sys.argv[1]
api_key = sys.argv[2]
record_type = sys.argv[3]
existing_IP = ''
ip = ''
post_data = ''
CF_ZONE_URL = 'https://api.cloudflare.com/client/v4/zones/'
CF_TRACE = 'https://cloudflare.com/cdn-cgi/trace' 
#######################################################################################

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}",
}

def get_zone_id(domain, api_key, headers):
    params = {'name': domain}
    response = requests.get(CF_ZONE_URL, headers=headers, params=params)
    if response.status_code == 200:
        zones = response.json()['result']
        if len(zones) > 0:
            return zones[0]['id']
    return None

def get_public_ip():
   response = requests.get(CF_TRACE)
   match = re.search(r'^ip=([\d\.]+)', response.text, re.MULTILINE)
   return match.group(1).strip()

def get_public_ipv6():
   ipv6_pattern = re.compile(r'ip=([a-fA-F0-9:]+)')
   response = requests.get(CF_TRACE)
   match = ipv6_pattern.search(response.text, re.MULTILINE)
   return match.group(1).strip()

if record_type.upper() in ['A','MX','NS']:
   ip = get_public_ip()
else:
   requests.packages.urllib3.util.connection.HAS_IPV6 = True
   ip = get_public_ipv6()
   requests.packages.urllib3.util.connection.HAS_IPV6 = False

zone_id = get_zone_id(re.sub(r'^.+?\.(?=[^\.]+\.[^\.]+$)', '', domain), api_key, headers)

if not zone_id:
    print(f"Zone ID for {domain} not found")
    sys.exit(0)

response = requests.get(CF_ZONE_URL + f"{zone_id}/dns_records", headers=headers)

if response.status_code == 200:
    # find the record ID for the first A record for the supplied domain name
    dns_records = json.loads(response.text)['result']
    for record in dns_records:
        if record['type'] == record_type.upper() and record['name'] == domain:
            record_id = record['id']
            existing_IP = record['content']
            break
else:
    print('Error fetching DNS records:', response.text)
    sys.exit(0)

if ip == existing_IP:
    print("Nothing needs to be done..")
    sys.exit(0)

post_data = {

    "content": ip,
    "name": domain,
    "proxied": True,
    "type": record_type.upper(),
    "comment": "DNS Record updated using Cfddns at " + time.strftime("%H:%M:%S on %Y-%m-%d", time.localtime(time.time())),
    "ttl": 0
}
# Update the record via PUT request
response = requests.put(CF_ZONE_URL + f"{zone_id}/dns_records/{record_id}", headers=headers, data=json.dumps(post_data))

if response.status_code == 200:
    print('Record updated successfully')
else:
    print('Error updating record:', response.text)

root@cb22abdc4aee:/app# 

here is the crontab in /etc/cron.d/ in my docker container

root@cb22abdc4aee:/etc/cron.d# ls
-rw-r--r-- 1 root root 168 Sep 22 12:31 crontab

root@cb22abdc4aee:/etc/cron.d# cat crontab 
# START CRON JOB
* * * * * /usr/bin/python3 /app/cfddns.py ommited-domain omitted-API-token A /proc/1/fd/1 2>/proc/1/fd/2
# END CRON JOB
root@cb22abdc4aee:/etc/cron.d# 

here is the crontab in the /usr/bin/ in my docker container

root@cb22abdc4aee:/usr/bin# ls -l crontab 
-rw-r--r-- 1 root crontab 168 Sep 22 12:36 crontab

root@cb22abdc4aee:/usr/bin# cat crontab 
# START CRON JOB
* * * * * /usr/bin/python3 /app/cfddns.py omitted-domain omitted-API-token A /proc/1/fd/1 2>/proc/1/fd/2 
# END CRON JOB
Suleman-Elahi commented 12 months ago

Try /usr/local/bin/python3 instead of /usr/bin/python3

I can't reproduce the issue ... it works as it supposed to on my side.