added cf and ddns for deploying new cloudflare subdomains behind a Caddy reverse-proxy and updating Cloudflare DDNS, respectively
This commit is contained in:
parent
78d7e305d7
commit
6c38e4210a
3 changed files with 168 additions and 0 deletions
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
113
cf
Normal file
113
cf
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#!/bin/bash
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "This script must be run as root. Try using 'sudo'."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
source /home/sij/.zshrc
|
||||||
|
source /home/sij/.GLOBAL_VARS
|
||||||
|
ddns
|
||||||
|
|
||||||
|
# Initialize variables
|
||||||
|
full_domain=$1
|
||||||
|
shift # Shift the arguments to left so we can get remaining arguments as before
|
||||||
|
caddyIP="" # Optional IP for Caddyfile
|
||||||
|
port=""
|
||||||
|
|
||||||
|
# Fixed IP for Cloudflare from ip.txt
|
||||||
|
cloudflareIP=$(cat /home/sij/.services/ip.txt)
|
||||||
|
api_key=$CF_API_KEY
|
||||||
|
cf_domains_file=/home/sij/.services/cf_domains.json
|
||||||
|
|
||||||
|
# Usage message
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <full-domain> [--ip <ip address>] --port <port>"
|
||||||
|
echo "Note: <full-domain> is required and can be a subdomain or a full domain."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command-line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--ip|-i)
|
||||||
|
caddyIP="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--port|-p)
|
||||||
|
port="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check required parameter
|
||||||
|
if [[ -z "$full_domain" ]] || [[ -z "$port" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract subdomain and domain
|
||||||
|
subdomain=$(echo "$full_domain" | awk -F"." '{print $1}')
|
||||||
|
remaining_parts=$(echo "$full_domain" | awk -F"." '{print NF}')
|
||||||
|
if [ "$remaining_parts" -eq 2 ]; then
|
||||||
|
# Handle root domain (e.g., env.esq)
|
||||||
|
domain=$full_domain
|
||||||
|
subdomain="@" # Use "@" for root domain
|
||||||
|
else
|
||||||
|
# Handle subdomain (e.g., sub.env.esq)
|
||||||
|
domain=$(echo "$full_domain" | sed "s/^$subdomain\.//")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default to localhost for Caddyfile if IP is not provided via --ip
|
||||||
|
if [[ -z "$caddyIP" ]]; then
|
||||||
|
caddyIP="localhost"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract zone_id from JSON file
|
||||||
|
zone_id=$(jq -r ".\"$domain\".zone_id" "$cf_domains_file")
|
||||||
|
|
||||||
|
# Check if zone_id was successfully retrieved
|
||||||
|
if [ "$zone_id" == "null" ] || [ -z "$zone_id" ]; then
|
||||||
|
echo "Error: Zone ID for $domain could not be found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# API call setup for Cloudflare A record using the fixed IP from ip.txt
|
||||||
|
endpoint="https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records"
|
||||||
|
data="{\"type\":\"A\",\"name\":\"$subdomain\",\"content\":\"$cloudflareIP\",\"ttl\":120,\"proxied\":true}"
|
||||||
|
|
||||||
|
# Make API call
|
||||||
|
response=$(curl -s -X POST "$endpoint" -H "Authorization: Bearer $api_key" -H "Content-Type: application/json" --data "$data")
|
||||||
|
|
||||||
|
# Parse response
|
||||||
|
record_id=$(echo "$response" | jq -r '.result.id')
|
||||||
|
success=$(echo "$response" | jq -r '.success')
|
||||||
|
error_message=$(echo "$response" | jq -r '.errors[0].message')
|
||||||
|
error_code=$(echo "$response" | jq -r '.errors[0].code')
|
||||||
|
|
||||||
|
# Function to update Caddyfile with correct indentation
|
||||||
|
update_caddyfile() {
|
||||||
|
echo "$full_domain {
|
||||||
|
reverse_proxy $caddyIP:$port
|
||||||
|
tls {
|
||||||
|
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
|
||||||
|
}
|
||||||
|
}" >> /etc/caddy/Caddyfile
|
||||||
|
echo "Configuration appended to /etc/caddy/Caddyfile with correct formatting."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for success or specific error to update Caddyfile
|
||||||
|
if [ "$success" == "true" ]; then
|
||||||
|
jq ".\"$domain\".subdomains[\"$full_domain\"] = \"$record_id\"" "$cf_domains_file" > temp.json && mv temp.json "$cf_domains_file"
|
||||||
|
echo "A record created and cf_domains.json updated successfully."
|
||||||
|
update_caddyfile
|
||||||
|
elif [ "$error_message" == "Record already exists." ]; then
|
||||||
|
echo "Record already exists. Updating Caddyfile anyway."
|
||||||
|
update_caddyfile
|
||||||
|
else
|
||||||
|
echo "Failed to create A record. Error: $error_message (Code: $error_code)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Restarting caddy!"
|
||||||
|
sudo systemctl restart caddy
|
55
ddns
Normal file
55
ddns
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
source /home/sij/.GLOBAL_VARS
|
||||||
|
|
||||||
|
service="https://am.i.mullvad.net/ip"
|
||||||
|
# Obtain the current public IP address
|
||||||
|
#current_ip=$(ssh -n sij@10.13.37.10 curl -s $service)
|
||||||
|
current_ip=$(curl -s $service)
|
||||||
|
last_ip=$(cat /home/sij/.services/ip.txt)
|
||||||
|
api_token=$CF_API_KEY
|
||||||
|
|
||||||
|
# Path to the JSON file with zone IDs, subdomains, and DNS IDs mappings
|
||||||
|
json_file="/home/sij/.services/cf_domains.json"
|
||||||
|
|
||||||
|
force_update=false
|
||||||
|
|
||||||
|
# Parse command line arguments for --force flag
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-f|--force) force_update=true ;;
|
||||||
|
*) echo "Unknown parameter passed: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Temporary file to store update results
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
# Function to update DNS records
|
||||||
|
update_dns_record() {
|
||||||
|
zone_id=$1
|
||||||
|
subdomain=$2
|
||||||
|
dns_id=$3
|
||||||
|
update_result=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$dns_id" \
|
||||||
|
-H "Authorization: Bearer $api_token" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data "{\"type\":\"A\",\"name\":\"$subdomain\",\"content\":\"$current_ip\",\"ttl\":120,\"proxied\":true}")
|
||||||
|
echo "$update_result" >> "$temp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if IP has changed or --force flag is used
|
||||||
|
if [ "$current_ip" != "$last_ip" ] || [ "$force_update" = true ]; then
|
||||||
|
echo $current_ip > /home/sij/.services/ip.txt
|
||||||
|
# Iterate through each domain in the JSON
|
||||||
|
/home/sij/miniforge3/bin/jq -r '.[] | .zone_id as $zone_id | .subdomains | to_entries[] | [$zone_id, .key, .value] | @tsv' $json_file |
|
||||||
|
while IFS=$'\t' read -r zone_id subdomain dns_id; do
|
||||||
|
update_dns_record "$zone_id" "$subdomain" "$dns_id"
|
||||||
|
done
|
||||||
|
# Combine all update results into a single JSON array
|
||||||
|
/home/sij/miniforge3/bin/jq -s '.' "$temp_file"
|
||||||
|
# Remove the temporary file
|
||||||
|
rm "$temp_file"
|
||||||
|
else
|
||||||
|
echo "IP address has not changed from ${last_ip}. No action taken."
|
||||||
|
fi
|
||||||
|
|
Loading…
Reference in a new issue