initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.venv
|
||||||
|
.env
|
||||||
|
develop.py
|
||||||
|
.idea
|
||||||
62
README.md
Normal file
62
README.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Cloudflare Python DynDNS
|
||||||
|
|
||||||
|
This script provides a way to implement a self-hosted Dynamic DNS (DynDNS) service that automatically updates your Cloudflare DNS record with your current public IP address whenever it changes.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. **Create a Subdomain**: Set up a subdomain like `dyndns.your-domain.com` in your Cloudflare account. All other DNS records should be `CNAME` records that resolve to `dyndns.your-domain.com`.
|
||||||
|
|
||||||
|
2. **Retrieve Cloudflare Details**: In your Cloudflare dashboard, find the following details for the subdomain you created:
|
||||||
|
- **Zone ID**
|
||||||
|
- **DNS Record Name**
|
||||||
|
- **DNS Record ID**
|
||||||
|
|
||||||
|
Set these values in the script configuration.
|
||||||
|
|
||||||
|
3. **How It Works**: The script checks your current public IP address. If it has changed, it updates the DNS record for `dyndns.your-domain.com` to reflect the new IP address.
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Step 1: Create Virtual Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv /opt/cloudflare-python-dyndns/venv
|
||||||
|
/opt/cloudflare-python-dyndns/venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Install Dependencies
|
||||||
|
|
||||||
|
Clone the repository and install required Python packages:
|
||||||
|
```bash
|
||||||
|
pip install -r /path/to/requirements.txt
|
||||||
|
```
|
||||||
|
### Step 3: Set Up Cron Job
|
||||||
|
|
||||||
|
To run the script periodically, open your crontab and add the following line to check for IP address changes every 15 minutes:
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
```
|
||||||
|
Then add this line:
|
||||||
|
```bash
|
||||||
|
*/15 * * * * /opt/cloudflare-python-dyndns/venv/bin/python /opt/cloudflare-python-dyndns/cloudflare-python-dyndns/main.py >/dev/null 2>&1
|
||||||
|
```
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Make sure to create a .env file in the project directory and add the following environment variables:
|
||||||
|
|
||||||
|
CLOUDFLARE_API_TOKEN: Your Cloudflare API token with permission to edit DNS records.`
|
||||||
|
CLOUDFLARE_ZONE_ID: The Zone ID of your domain in Cloudflare.
|
||||||
|
CLOUDFLARE_DNS_RECORD_NAME: The DNS record name (e.g., dyndns.your-domain.com).
|
||||||
|
CLOUDFLARE_DNS_RECORD_ID: The DNS record ID for the dyndns record.
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
Support for IPv6 addresses.
|
||||||
|
Automate the process of fetching the DNS Record Name and ID.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- [@lucashahmann](https://www.github.com/lucashahmann)
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://choosealicense.com/licenses/mit/)
|
||||||
61
main.py
Normal file
61
main.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Imports
|
||||||
|
import os
|
||||||
|
from cloudflare import Cloudflare
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from requests import get
|
||||||
|
|
||||||
|
# Function to retrieve public IPv4 address
|
||||||
|
def get_public_ipv4():
|
||||||
|
ip_v4 = get('https://api.ipify.org').content.decode('utf8')
|
||||||
|
return ip_v4
|
||||||
|
|
||||||
|
# Function to set the dynamic DNS record in Cloudflare
|
||||||
|
def set_dyndns_record(client, new_public_ip):
|
||||||
|
response = client.dns.records.edit(
|
||||||
|
zone_id=zone_id,
|
||||||
|
dns_record_id=record_id,
|
||||||
|
name=record_name,
|
||||||
|
content=new_public_ip,
|
||||||
|
type="A"
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Retrieve required environment variables
|
||||||
|
api_token = os.environ.get("CLOUDFLARE_API_TOKEN")
|
||||||
|
if not api_token:
|
||||||
|
raise ValueError("Cloudflare API token is not set in environment variables.")
|
||||||
|
|
||||||
|
zone_id = os.environ.get("CLOUDFLARE_ZONE_ID")
|
||||||
|
record_name = os.environ.get("CLOUDFLARE_DNS_RECORD_NAME")
|
||||||
|
record_id = os.environ.get("CLOUDFLARE_DNS_RECORD_ID")
|
||||||
|
|
||||||
|
# Set the headers for Cloudflare API request
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {api_token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Initialize Cloudflare client with the API token and headers
|
||||||
|
client = Cloudflare(default_headers=headers)
|
||||||
|
|
||||||
|
# Get the current DNS record for dynamic DNS
|
||||||
|
dyndns_record = client.dns.records.get(
|
||||||
|
dns_record_id=record_id,
|
||||||
|
zone_id=zone_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Retrieve the current public IP address
|
||||||
|
public_ip = get_public_ipv4()
|
||||||
|
|
||||||
|
# Check if the current public IP matches the existing DNS record
|
||||||
|
if public_ip == dyndns_record.content:
|
||||||
|
# Exit if the IP addresses are the same
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
# Update the DNS record with the new public IP
|
||||||
|
set_dyndns_record(client, public_ip)
|
||||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
requests
|
||||||
|
cloudflare
|
||||||
|
python-dotenv
|
||||||
Reference in New Issue
Block a user