Created
April 15, 2025 19:24
-
-
Save ConnerWill/334eaa9d2d99f2ffa394d8497825e2f6 to your computer and use it in GitHub Desktop.
Script to update DDNS IP for DynuDNS domain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
#### OPTIONS | |
set -o errexit -o pipefail | |
#### DEFINITIONS | |
PROG=$(basename "${0}") | |
DDNS_USERNAME="${DDNS_USERNAME:-}" | |
DDNS_PASSWORD="${DDNS_PASSWORD:-}" | |
DDNS_HOSTNAME="${DDNS_HOSTNAME:-}" | |
DDNS_ALIAS="${DDNS_ALIAS:-}" | |
UPDATE_ALL="${DDNS_UPDATE_ALL:-false}" | |
IPV4="${DDNS_IPV4:-auto}" | |
IPV6="${DDNS_IPV6:-no}" | |
DRY_RUN=false | |
#### FUNCTIONS | |
## Function to throw an error | |
function throw_error() { | |
local error_input="${1}" | |
printf "[ERROR]: %s\n" "${error_input}" >&2 | |
exit 1 | |
} | |
function is_installed(){ | |
local input="${1}" | |
if ! command -v "${input}" >/dev/null 2>&1; then | |
throw_error "Cannot find '${input}' in PATH. Please make sure '${input}' is installed and is in your PATH" | |
fi | |
} | |
function usage() { | |
cat << EOF | |
Usage: ${PROG} [options] | |
Options: | |
-u, --username <username> Dynu username (required if not updating single hostname) | |
-p, --password <password> Dynu password (required) | |
-h, --hostname <hostname> Hostname to update (required if not updating all domains) | |
-a, --alias <alias> Subdomain alias to update | |
-A, --all Update all domains in account (requires username) | |
-4, --ipv4 <ip|no|auto> IPv4 address, 'no' to skip, or 'auto' to auto-detect (default: auto) | |
-6, --ipv6 <ip|no|auto> IPv6 address, 'no' to skip, or 'auto' to auto-detect (default: auto) | |
-d, --dry-run Print the curl command without executing it | |
-?, --help Show this help message | |
Environment Variables: | |
DDNS_USERNAME Dynu username | |
DDNS_PASSWORD Dynu password | |
DDNS_HOSTNAME Hostname to update | |
DDNS_ALIAS Subdomain alias | |
DDNS_UPDATE_ALL Set to 'true' to update all domains (default: false) | |
DDNS_IPV4 IPv4 address, 'no', or 'auto' (default: auto) | |
DDNS_IPV6 IPv6 address, 'no', or 'auto' (default: auto) | |
EOF | |
exit 0 | |
} | |
function parse_args() { | |
while [[ $# -gt 0 ]]; do | |
case "${1}" in | |
-u|--username) | |
DDNS_USERNAME="${2}" | |
shift 2 | |
;; | |
-p|--password) | |
DDNS_PASSWORD="${2}" | |
shift 2 | |
;; | |
-h|--hostname) | |
DDNS_HOSTNAME="${2}" | |
shift 2 | |
;; | |
-a|--alias) | |
DDNS_ALIAS="${2}" | |
shift 2 | |
;; | |
-A|--all) | |
UPDATE_ALL=true | |
shift | |
;; | |
-4|--ipv4) | |
IPV4="${2}" | |
shift 2 | |
;; | |
-6|--ipv6) | |
IPV6="${2}" | |
shift 2 | |
;; | |
-d|--dry-run) | |
DRY_RUN=true | |
shift | |
;; | |
-\?|--help) | |
usage | |
;; | |
*) | |
throw_error "Unknown option: ${1}" | |
;; | |
esac | |
done | |
} | |
function validate_args() { | |
if [[ -z "${DDNS_PASSWORD}" ]]; then | |
throw_error "Password is required (set DDNS_PASSWORD or use --password)" | |
fi | |
if [[ "${UPDATE_ALL}" == true && -z "${DDNS_USERNAME}" ]]; then | |
throw_error "Username is required when updating all domains (set DDNS_USERNAME or use --username)" | |
fi | |
if [[ "${UPDATE_ALL}" == false && -z "${DDNS_HOSTNAME}" ]]; then | |
throw_error "Hostname is required when not updating all domains (set DDNS_HOSTNAME or use --hostname)" | |
fi | |
} | |
function build_url() { | |
local base_url="https://api.dynu.com/nic/update" | |
local params=() | |
if [[ "${UPDATE_ALL}" == true ]]; then | |
params+=("username=${DDNS_USERNAME}") | |
fi | |
params+=("password=${DDNS_PASSWORD}") | |
if [[ -n "${DDNS_HOSTNAME}" ]]; then | |
params+=("hostname=${DDNS_HOSTNAME}") | |
fi | |
if [[ -n "${DDNS_ALIAS}" ]]; then | |
params+=("alias=${DDNS_ALIAS}") | |
fi | |
if [[ "${IPV4}" != "auto" ]]; then | |
params+=("myip=${IPV4}") | |
fi | |
if [[ "${IPV6}" != "auto" ]]; then | |
params+=("myipv6=${IPV6}") | |
fi | |
query_string=$(IFS='&'; echo "${params[*]}") | |
local query_string | |
echo "${base_url}?${query_string}" | |
} | |
#### MAIN | |
is_installed "curl" | |
parse_args "$@" | |
validate_args | |
url=$(build_url) | |
if [[ "${DRY_RUN}" == true ]]; then | |
echo "Dry run: curl -s \"${url}\"" | |
exit 0 | |
fi | |
response=$(curl -s "${url}") | |
if [[ "${response}" == "good"* || "${response}" == "nochg"* ]]; then | |
echo "DDNS update successful: ${response}" | |
else | |
throw_error "DDNS update failed: ${response}" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment