Skip to content

Instantly share code, notes, and snippets.

@alatalo
Last active December 15, 2025 05:34
Show Gist options
  • Select an option

  • Save alatalo/5948ec7203a608f3cc92aa5d658f7ece to your computer and use it in GitHub Desktop.

Select an option

Save alatalo/5948ec7203a608f3cc92aa5d658f7ece to your computer and use it in GitHub Desktop.
Glesys dyn dns updater - Simple shell script to update DNS record in Glesys Cloud based on your current public IP.

Glesys dyn dns updater

Simple shell script to update DNS record in Glesys Cloud based on your current public IP.

Requirements

  • IPinfo.io API token
  • Glesys Cloud API account with permissions: domain/addrecord, domain/listrecord, domain/updaterecord
  • Optional Discord webhook notification on IP change
  • curl and jq installed

Licensed under MIT License

# Glesys API credentials
GLESYS_USER=CL12345
GLESYS_APIKEY=your_glesys_api_key
# IPinfo.io token
IPINFO_TOKEN=your_ipinfo_io_token
# DNS record details
DOMAIN_NAME=example.com
HOST_NAME=home
# (optional)
RECORD_TYPE=A
RECORD_TTL=300
# (optional) Discord webhook URL for notification on IP change
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your_webhook_url
# (optional) Force update
FORCE_UPDATE=false
#!/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
#/etc/systemd/system/glesys-dyndns.service
[Unit]
Description=Glesys dyndns updater
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
WorkingDirectory=/opt/glesys-dyndns
ReadOnlyPaths=/opt/glesys-dyndns
Environment=ENV_FILE=.env
RuntimeDirectory=glesys-dyndns
ExecStart=/usr/bin/flock -n /run/glesys-dyndns/lock /opt/glesys-dyndns/glesys-update-dns.sh
User=glesys-dyndns
Group=glesys-dyndns
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
StandardOutput=journal
StandardError=journal
Nice=10
TimeoutStartSec=60
[Install]
WantedBy=multi-user.target
#/etc/systemd/system/glesys-dyndns.timer
[Unit]
Description=Run Glesys dyndns updater hourly
[Timer]
OnBootSec=2min
OnUnitActiveSec=1h
AccuracySec=1min
Persistent=true
[Install]
WantedBy=timers.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment