Hoppa till innehållet

Dynadot

Från Plutten

Mall:Short description

Dynadot Dynamic DNS (DDNS) Setup

This page documents how to configure Dynamic DNS for Dynadot and automatically update the A record when the public IP address changes.

Requirements

  • Dynadot account
  • Domain using Dynadot DNS
  • DDNS password generated in Dynadot
  • Ubuntu server with outbound HTTPS access

Dynadot configuration

1. Enable Dynadot DNS

  1. Log in to Dynadot
  2. Go to My Domains
  3. Click the domain
  4. Set DNSDynadot DNS

2. Enable Dynamic DNS

  1. Domain settings → Dynamic DNS
  2. Enable DDNS
  3. Generate a DDNS password
  4. Save it securely

3. Required values

Field Example
Domain example.com
Subdomain @ or www
Record type A (IPv4) or AAAA (IPv6)
DDNS password (generated in Dynadot)

Dynadot update endpoint

Dynadot accepts HTTP GET updates:

https://www.dynadot.com/set_ddns

Parameters:

  • domain
  • subDomain
  • type
  • ip
  • pwd
  • ttl (optional)

Ubuntu auto-update script

Script: dynadot-ddns.sh

nano .env

Add this:

# SUBDOMAIN should be left empty if root domain.
DOMAIN=<domain>
SUBDOMAIN=
TYPE=A
PASSWORD=YOUR_DYNADOT_PASSWORD
TTL=300
chmod 600 .env
#!/bin/bash

# ===== CONFIG =====
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_DDNS="$SCRIPT_DIR/.env"                # Dynadot settings
ENV_DISCORD="$SCRIPT_DIR/../bots/discord/.env"  # Discord bot settings
IP_FILE="$SCRIPT_DIR/dynadot_last_ip.txt"
LOG_FILE="$SCRIPT_DIR/log.txt"
LOG_ROTATED="$SCRIPT_DIR/log.txt.1"

# ===== LOG ROTATION =====
if [ -f "$LOG_FILE" ]; then
    mv -f "$LOG_FILE" "$LOG_ROTATED"
fi

# ===== LOAD ENV =====
# Dynadot settings
if [ -f "$ENV_DDNS" ]; then
    export $(grep -v '^#' "$ENV_DDNS" | xargs)
else
    echo "ERROR: Dynadot .env not found at $ENV_DDNS"
    exit 1
fi

# Discord bot settings
if [ -f "$ENV_DISCORD" ]; then
    export $(grep -v '^#' "$ENV_DISCORD" | xargs)
else
    echo "ERROR: Discord .env not found at $ENV_DISCORD"
    exit 1
fi

# ===== CHECK REQUIRED ENV VARIABLES =====
for var in DOMAIN PASSWORD TTL DISCORD_BOT_TOKEN LOGS_CHANNEL_ID; do
    if [ -z "${!var}" ]; then
        echo "ERROR: $var not set in .env files"
        exit 1
    fi
done

CHANNEL_ID="$LOGS_CHANNEL_ID"

# ===== LOG FUNCTION =====
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# ===== DISCORD FUNCTION =====
send_discord() {
    local result="$1"
    local ip_old="$2"
    local ip_new="$3"
    local timestamp
    timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")  # ISO 8601 UTC

    local json_payload=$(cat <<EOF
{
  "content": "The domain name #${DOMAIN} dynamically resolves to ${result}.",
  "embeds": [
    {
      "description": "Domains: ${DOMAIN}\nResult: ${result}\nOld IP: ${ip_old}\nNew IP: ${ip_new}\nTime: ${timestamp} UTC",
      "color": 15258703,
      "author": { "name": "DDNS" },
      "footer": { "text": "DDNS ${result}" }
    }
  ]
}
EOF
)

    curl -s -H "Authorization: Bot $DISCORD_BOT_TOKEN" \
         -H "Content-Type: application/json" \
         -X POST \
         -d "$json_payload" \
         "https://discord.com/api/v9/channels/${CHANNEL_ID}/messages" > /dev/null
}

log "---- Script started ----"

# ===== GET CURRENT IP =====
CURRENT_IP=$(curl -s https://checkip.amazonaws.com)
if [ -z "$CURRENT_IP" ]; then
    log "ERROR: Could not fetch public IP"
    send_discord "ERROR" "N/A" "N/A"
    exit 1
fi
CURRENT_IP=$(echo "$CURRENT_IP" | tr -d '[:space:]')
log "Current IP: $CURRENT_IP"

# ===== READ LAST IP =====
if [ -f "$IP_FILE" ]; then
    LAST_IP=$(cat "$IP_FILE")
else
    LAST_IP=""
    touch "$IP_FILE"
    log "Created IP file"
fi
log "Last IP: $LAST_IP"

# ===== COMPARE =====
if [ "$CURRENT_IP" = "$LAST_IP" ]; then
    log "IP unchanged. No update needed."
    exit 0  # No Discord notification if unchanged
fi

# ===== UPDATE DYNDOT =====
SUBDOMAIN=${SUBDOMAIN:-""}  # default to empty if not set
TYPE=${TYPE:-"A"}           # default to A record
UPDATE_URL="https://www.dynadot.com/set_ddns?containRoot=true&domain=${DOMAIN}&subDomain=${SUBDOMAIN}&type=${TYPE}&ip=${CURRENT_IP}&pwd=${PASSWORD}&ttl=${TTL}"
RESPONSE=$(curl -s "$UPDATE_URL")
log "Dynadot response: $RESPONSE"

# ===== SAVE IP & DISCORD =====
if echo "$RESPONSE" | grep -qi "success"; then
    echo "$CURRENT_IP" > "$IP_FILE"
    log "IP updated and saved."
    send_discord "SUCCESS" "$LAST_IP" "$CURRENT_IP"
else
    log "ERROR: Dynadot update failed."
    send_discord "FAIL" "$LAST_IP" "$CURRENT_IP"
fi

log "---- Script finished ----"
echo

Installation

1. Save script

sudo nano /usr/local/bin/dynadot-ddns.sh

Paste script and edit variables.

2. Make executable

sudo chmod +x /usr/local/bin/dynadot-ddns.sh

3. Test manually

/usr/local/bin/dynadot-ddns.sh

4. Add cron job (every 5 minutes)

crontab -e

Add:

*/5 * * * * /usr/local/bin/dynadot-ddns.sh

Security notes

  • Store DDNS password securely
  • Limit file permissions
  • Do not commit the script to public repositories

References

  • Dynadot Help – Dynamic DNS
  • Dynadot API documentation