Repository files, collaboration, releases and project activity.
archforge-external-status / scripts/domain-lib.shmain
▤ scripts/domain-lib.sh2799 bytes
88 lines · Select a line number for a permalink
1
#!/usr/bin/env bash2
# Pure, sourceable helpers for ArchForge External Status domain/TLS configuration.3
# Deliberately never source status.env; it contains literal secrets.5
af_valid_domain() {6
local domain=${1-} label7
[[ ${#domain} -le 253 && "$domain" == *.* && "$domain" != *..* && "$domain" != .* && "$domain" != *. ]] || return 18
[[ "$domain" =~ ^[a-zA-Z0-9.-]+$ ]] || return 19
local IFS=.10
local -a labels11
read -r -a labels <<< "$domain"12
for label in "${labels[@]}"; do13
[[ ${#label} -ge 1 && ${#label} -le 63 && "$label" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$ ]] || return 114
done15
return 016
}18
af_valid_ipv4() {19
local ip=${1-} part20
[[ "$ip" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]] || return 121
local IFS=.22
local -a octets23
read -r -a octets <<< "$ip"24
[[ ${#octets[@]} == 4 ]] || return 125
for part in "${octets[@]}"; do26
[[ ${#part} -le 3 && ( "$part" == 0 || "$part" != 0* ) ]] || return 127
(( 10#$part <= 255 )) || return 128
done29
return 030
}32
af_valid_ipv6() {33
[[ -n ${1-} ]] || return 134
python3 -c 'import ipaddress,sys;ipaddress.IPv6Address(sys.argv[1])' "$1" >/dev/null 2>&135
}37
af_valid_email() {38
local mail=${1-}39
[[ -z "$mail" || ( "$mail" =~ ^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$ && ${#mail} -le 254 ) ]]40
}42
af_read_public_domain() {43
local env_file=$1 url44
[[ -f "$env_file" && ! -L "$env_file" ]] || return 145
url=$(grep -m1 '^STATUS_PUBLIC_URL=' "$env_file" | cut -d= -f2-) || return 146
[[ "$url" == https://* ]] || return 147
url=${url#https://}48
[[ "$url" != */* ]] || return 149
af_valid_domain "$url" || return 150
printf '%s' "$url"51
}53
af_set_public_domain() {54
local env_file=$1 domain=$2 tmp55
af_valid_domain "$domain" || return 156
[[ -f "$env_file" && ! -L "$env_file" ]] || return 157
tmp=$(mktemp "$(dirname "$env_file")/.status-env.XXXXXXXX") || return 158
chmod --reference="$env_file" "$tmp"59
chown --reference="$env_file" "$tmp"60
if ! awk -v new="STATUS_PUBLIC_URL=https://${domain}" '61
/^STATUS_PUBLIC_URL=/ { if (!seen++) print new; next }62
{ print }63
END { if (!seen) print new }64
' "$env_file" > "$tmp"; then65
rm -f "$tmp"66
return 167
fi68
mv -f -- "$tmp" "$env_file"69
}71
af_render_caddy() {72
local domain=$1 email=${2-}73
af_valid_domain "$domain" && af_valid_email "$email" || return 174
printf '%s {\n' "$domain"75
printf ' encode zstd gzip\n'76
printf ' reverse_proxy 127.0.0.1:3000\n'77
if [[ -n "$email" ]]; then78
printf ' tls %s\n' "$email"79
fi80
printf '}\n'81
}83
af_dns_records() {84
local type=$1 domain=$285
[[ "$type" == A || "$type" == AAAA ]] && af_valid_domain "$domain" || return 186
dig +time=3 +tries=1 +short "$type" "$domain" | grep -E "$( [[ "$type" == A ]] && printf '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$' || printf '^[0-9A-Fa-f:]+$' )" || true87
}