diff --git a/README.md b/README.md index 2f60cdc..bd70828 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,29 @@ # Vercel Dynamic DNS -Script for exposing local server with [Vercel DNS](https://vercel.com/docs/custom-domains). It runs every 15 minutes, checking current IP address and updates DNS records for your domain. +Simple script for exposing a local server with [Vercel DNS](https://vercel.com/docs/custom-domains). +It runs on CRON, checking the current IP address and updating DNS records for your domain. ## Installation -1. Download -2. Move `dns.config.example` into `dns.config` -3. Edit config -4. Open cron settings `crontab -e` -5. Add this line `*/15 * * * * /home/username/vercel-ddns/dns-sync.sh` +1. Ensure that you have [jq](https://github.com/jqlang/jq) installed +2. Download `dns-sync.sh` +3. Move `dns.config.example` to `dns.config` +4. Edit the configuration variables as required +5. Open the cron settings using the command `crontab -e` +6. Add the following line to the cron job: `*/15 * * * * /path-to/vercel-ddns/dns-sync.sh` + +## Usage example + +```sh +# Creating +➜ ./dns-sync.sh +Updating IP: x.x.x.x +Record for SUBDOMAIN does not exist. Creating... +🎉 Done! + +# Updating +➜ ./dns-sync.sh +Updating IP: x.x.x.x +Record for SUBDOMAIN already exists (id: rec_xxxxxxxxxxxxxxxxxxxxxxxx). Updating... +🎉 Done! +``` diff --git a/dns-sync.sh b/dns-sync.sh index eea6a45..a25b74d 100755 --- a/dns-sync.sh +++ b/dns-sync.sh @@ -1,21 +1,103 @@ #!/bin/bash +# Vercel Dynamic DNS +# https://github.com/iam-medvedev/vercel-ddns + source ./dns.config -# 1. Get current IP -IP=$(curl -s http://whatismyip.akamai.com/) -echo "$IP" - -# 2. Create/update DNS record -curl -X POST "https://api.vercel.com/v2/domains/$DOMAIN_NAME/records" \ - -H "Authorization: Bearer $VERCEL_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "'$SUBDOMAIN'", - "type": "A", - "value": "'$IP'", - "ttl": 60 -}' - -echo '' +# Check if jq is installed +if ! command -v jq >/dev/null; then + echo "Error: 'jq' is not installed. Please install 'jq' to run this script." + exit 1 +fi + +# Returns current IP +get_current_ip() { + local ip + ip=$(curl -s http://whatismyip.akamai.com/) + echo $ip +} + +# Function to check if subdomain exists +check_subdomain_exists() { + local subdomain="$1" + local response + response=$(curl -sX GET "https://api.vercel.com/v4/domains/$DOMAIN_NAME/records" \ + -H "Authorization: Bearer $VERCEL_TOKEN" \ + -H "Content-Type: application/json") + + local record_id + record_id=$(echo "$response" | jq -r ".records[] | select(.name == \"$subdomain\") | .id") + if [[ -n "$record_id" ]]; then + # Return record ID if exists + echo "$record_id" + else + # Subdomain does not exist + return 1 + fi +} + +# Updates dns record +update_dns_record() { + local ip="$1" + local record_id="$2" + local response + response=$(curl -sX PATCH "https://api.vercel.com/v1/domains/records/$record_id" \ + -H "Authorization: Bearer $VERCEL_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "comment": "vercel-ddns", + "name": "'$SUBDOMAIN'", + "type": "A", + "value": "'$ip'", + "ttl": 60 + }') + + # Check for errors in the response + if [[ "$response" == *"error"* ]]; then + local error_message + error_message=$(echo "$response" | jq -r '.error.message') + echo "⚠️ Error updating DNS record: $error_message" + exit 1 + fi +} + +# Creates dns record +create_dns_record() { + local ip="$1" + local response + response=$(curl -sX POST "https://api.vercel.com/v4/domains/$DOMAIN_NAME/records" \ + -H "Authorization: Bearer $VERCEL_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "comment": "vercel-ddns", + "name": "'$SUBDOMAIN'", + "type": "A", + "value": "'$ip'", + "ttl": 60 + }') + + # Check for errors in the response + if [[ "$response" == *"error"* ]]; then + local error_message + error_message=$(echo "$response" | jq -r '.error.message') + echo "⚠️ Error creating DNS record: $error_message" + exit 1 + fi +} + +# Get current IP +ip=$(get_current_ip) +echo "Updating IP: $ip" + +# Check if subdomain exists +record_id=$(check_subdomain_exists "$SUBDOMAIN") +if [[ -n "$record_id" ]]; then + echo "Record for $SUBDOMAIN already exists (id: $record_id). Updating..." + update_dns_record "$ip" "$record_id" +else + echo "Record for $SUBDOMAIN does not exist. Creating..." + create_dns_record "$ip" +fi + echo "🎉 Done!" diff --git a/dns.config.example b/dns.config.example index e53e4f9..90cc8e0 100644 --- a/dns.config.example +++ b/dns.config.example @@ -1,5 +1,10 @@ -# Get token here https://vercel.com/account/tokens +#!/bin/bash + +# Get the token from https://vercel.com/account/tokens VERCEL_TOKEN="" -# Your domain/subdomain +# Domain name (e.g. example.com) DOMAIN_NAME="" + +# Subdomain to update (note: use an empty string for the root record) +SUBDOMAIN=""