|
#!/usr/bin/env bash |
|
# |
|
# Glesys dyn dns updater |
|
# Ville Alatalo 2025 https://github.com/alatalo |
|
# |
|
|
|
set -euo pipefail |
|
|
|
# Load env file if exists/defined |
|
if [[ -f "${ENV_FILE:-.env}" ]]; then |
|
set -o allexport |
|
source "${ENV_FILE:-.env}" |
|
set +o allexport |
|
echo "Loaded environment from ${ENV_FILE:-.env}" |
|
fi |
|
|
|
# Required env vars |
|
: "${GLESYS_USER:?GLESYS_USER is required}" |
|
: "${GLESYS_APIKEY:?GLESYS_APIKEY is required}" |
|
: "${IPINFO_TOKEN:?IPINFO_TOKEN is required}" |
|
: "${DOMAIN_NAME:?DOMAIN_NAME is required}" |
|
: "${HOST_NAME:?HOST_NAME is required}" |
|
|
|
# Optional env vars |
|
: "${RECORD_TYPE:=A}" |
|
: "${RECORD_TTL:=300}" |
|
: "${DISCORD_WEBHOOK_URL:=}" |
|
: "${FORCE_UPDATE:=false}" |
|
|
|
for bin in curl jq; do |
|
if ! command -v "$bin" >/dev/null 2>&1; then |
|
echo "ERROR: missing required command: $bin" >&2 |
|
exit 1 |
|
fi |
|
done |
|
|
|
CURL_OPTS=( -fsS --connect-timeout 5 --max-time 20 ) |
|
FORCE_UPDATE="$(echo "$FORCE_UPDATE" | tr '[:upper:]' '[:lower:]')" |
|
|
|
# Fetch public IP |
|
PUBLIC_IP=$(curl "${CURL_OPTS[@]}" \ |
|
-H "Authorization: Bearer $IPINFO_TOKEN" \ |
|
-H "Accept: application/json" \ |
|
https://api.ipinfo.io/lite/me/ip) |
|
|
|
echo "Public IP: $PUBLIC_IP" |
|
|
|
# Get existing DNS records |
|
RECORDS=$(curl "${CURL_OPTS[@]}" \ |
|
-u "$GLESYS_USER:$GLESYS_APIKEY" \ |
|
-H "Content-Type: application/json" \ |
|
-X POST \ |
|
--data "{ \"domainname\": \"$DOMAIN_NAME\" }" \ |
|
https://api.glesys.com/domain/listrecords) |
|
|
|
# Extract match |
|
RECORD_ID=$(echo "$RECORDS" \ |
|
| jq -r ".response.records[] | select(.host==\"$HOST_NAME\" and .type==\"$RECORD_TYPE\") | .recordid" \ |
|
| head -n1 || true) |
|
|
|
CURRENT_DATA=$(echo "$RECORDS" \ |
|
| jq -r ".response.records[] | select(.recordid==${RECORD_ID:-0}) | .data" \ |
|
| head -n1 || true) |
|
|
|
# No-op if IP is already OK |
|
if [[ "$FORCE_UPDATE" != "true" && -n "${RECORD_ID:-}" && "$CURRENT_DATA" == "$PUBLIC_IP" ]]; then |
|
echo "Skipping DNS record update, it's already up to date." |
|
exit 0 |
|
fi |
|
|
|
if [[ "$FORCE_UPDATE" == "true" ]]; then |
|
echo "Force update enabled, updating DNS record." |
|
fi |
|
|
|
# Create or update record |
|
if [[ -z "${RECORD_ID:-}" ]]; then |
|
echo "Creating DNS record..." |
|
|
|
curl "${CURL_OPTS[@]}" \ |
|
-u "$GLESYS_USER:$GLESYS_APIKEY" \ |
|
-H "Content-Type: application/json" \ |
|
-X POST \ |
|
--data "{ |
|
\"domainname\": \"$DOMAIN_NAME\", |
|
\"host\": \"$HOST_NAME\", |
|
\"type\": \"$RECORD_TYPE\", |
|
\"data\": \"$PUBLIC_IP\", |
|
\"ttl\": \"$RECORD_TTL\" |
|
}" \ |
|
https://api.glesys.com/domain/addrecord |
|
|
|
echo "Created." |
|
else |
|
echo "Updating DNS record..." |
|
|
|
curl "${CURL_OPTS[@]}" \ |
|
-u "$GLESYS_USER:$GLESYS_APIKEY" \ |
|
-H "Content-Type: application/json" \ |
|
-X POST \ |
|
--data "{ |
|
\"recordid\": $RECORD_ID, |
|
\"host\": \"$HOST_NAME\", |
|
\"type\": \"$RECORD_TYPE\", |
|
\"data\": \"$PUBLIC_IP\", |
|
\"ttl\": \"$RECORD_TTL\" |
|
}" \ |
|
https://api.glesys.com/domain/updaterecord |
|
|
|
echo "Updated." |
|
fi |
|
|
|
# Post to Discord |
|
if [[ -n "${DISCORD_WEBHOOK_URL:-}" ]]; then |
|
echo "Posting to Discord..." |
|
|
|
curl "${CURL_OPTS[@]}" \ |
|
-H "Content-Type: application/json" \ |
|
-X POST \ |
|
-d "$(jq -n --arg content "DNS updated, new public IP: $PUBLIC_IP" '{content: $content}')" \ |
|
"$DISCORD_WEBHOOK_URL" |
|
|
|
echo "Posted." |
|
fi |