167 lines
3.6 KiB
Bash
Executable File
167 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
log() {
|
|
printf '[redeploy] %s\n' "$*"
|
|
}
|
|
|
|
read_env_value() {
|
|
local key="$1"
|
|
local line=""
|
|
|
|
if [[ ! -f .env ]]; then
|
|
return 1
|
|
fi
|
|
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
if [[ "$line" == "${key}="* ]]; then
|
|
printf '%s\n' "${line#*=}"
|
|
return 0
|
|
fi
|
|
done < .env
|
|
|
|
return 1
|
|
}
|
|
|
|
upsert_env_value() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local temp_file=""
|
|
local line=""
|
|
local found=0
|
|
|
|
temp_file="$(mktemp)"
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
if [[ "$line" == "${key}="* ]]; then
|
|
printf '%s=%s\n' "$key" "$value" >> "$temp_file"
|
|
found=1
|
|
else
|
|
printf '%s\n' "$line" >> "$temp_file"
|
|
fi
|
|
done < .env
|
|
|
|
if [[ "$found" -eq 0 ]]; then
|
|
printf '%s=%s\n' "$key" "$value" >> "$temp_file"
|
|
fi
|
|
|
|
chmod --reference=.env "$temp_file" 2>/dev/null || chmod 600 "$temp_file"
|
|
mv "$temp_file" .env
|
|
}
|
|
|
|
parse_route_source_ip() {
|
|
local route="$1"
|
|
local previous=""
|
|
local token
|
|
|
|
for token in $route; do
|
|
if [[ "$previous" == "src" ]]; then
|
|
printf '%s\n' "$token"
|
|
return 0
|
|
fi
|
|
previous="$token"
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
detect_ad_dns_ip() {
|
|
local lookup_name="$1"
|
|
local target_ip=""
|
|
local route=""
|
|
|
|
if ! command -v ip >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
if [[ -n "$lookup_name" ]] && command -v getent >/dev/null 2>&1; then
|
|
while read -r target_ip _; do
|
|
if [[ ! "$target_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
|
continue
|
|
fi
|
|
route="$(ip -o -4 route get "$target_ip" 2>/dev/null || true)"
|
|
parse_route_source_ip "$route" && return 0
|
|
done < <(getent ahostsv4 "$lookup_name" 2>/dev/null)
|
|
fi
|
|
|
|
route="$(ip -o -4 route get 1.1.1.1 2>/dev/null || true)"
|
|
parse_route_source_ip "$route"
|
|
}
|
|
|
|
refresh_ad_dns_env() {
|
|
local auto=""
|
|
local domain=""
|
|
local detected_ip=""
|
|
local samba_hostname=""
|
|
local netbios_name=""
|
|
local host_part=""
|
|
|
|
if [[ ! -f .env ]]; then
|
|
log '.env missing; skipping AD DNS IP refresh'
|
|
return
|
|
fi
|
|
|
|
auto="$(read_env_value AD_DNS_IP_AUTO || true)"
|
|
case "${auto,,}" in
|
|
0|false|no)
|
|
log 'AD_DNS_IP_AUTO disabled; keeping configured AD_DNS_IP'
|
|
return
|
|
;;
|
|
esac
|
|
|
|
domain="$(read_env_value DOMAIN || true)"
|
|
if [[ -z "$domain" ]]; then
|
|
log 'DOMAIN missing in .env; skipping AD DNS IP refresh'
|
|
return
|
|
fi
|
|
|
|
detected_ip="$(detect_ad_dns_ip "$domain" || true)"
|
|
if [[ -z "$detected_ip" ]]; then
|
|
log 'Unable to detect host LAN IP; keeping configured AD_DNS_IP'
|
|
return
|
|
fi
|
|
|
|
upsert_env_value AD_DNS_IP "$detected_ip"
|
|
if ! read_env_value AD_DNS_NAME >/dev/null; then
|
|
samba_hostname="$(read_env_value SAMBA_HOSTNAME || true)"
|
|
netbios_name="$(read_env_value NETBIOS_NAME || true)"
|
|
host_part="${samba_hostname:-${netbios_name,,}}"
|
|
host_part="${host_part:-adsambafsrv}"
|
|
upsert_env_value AD_DNS_NAME "${host_part}.${domain}"
|
|
fi
|
|
upsert_env_value AD_DNS_IP_AUTO "1"
|
|
log "Updated AD_DNS_IP=${detected_ip}"
|
|
}
|
|
|
|
if [[ ! -d .git ]]; then
|
|
printf '[redeploy] ERROR: run this script from the repository root.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
refresh_ad_dns_env
|
|
|
|
OLD_COMPOSE_FILE="$(mktemp)"
|
|
|
|
cleanup() {
|
|
if [[ -f "$OLD_COMPOSE_FILE" ]]; then
|
|
rm -f "$OLD_COMPOSE_FILE"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
log 'Capturing current compose configuration'
|
|
docker compose config > "$OLD_COMPOSE_FILE"
|
|
|
|
log 'Pulling latest git changes'
|
|
git pull
|
|
|
|
log 'Building updated images while current stack is running'
|
|
docker compose build --no-cache
|
|
|
|
log 'Stopping previous stack using captured configuration'
|
|
docker compose --project-directory "$PWD" -f "$OLD_COMPOSE_FILE" down
|
|
|
|
log 'Starting stack'
|
|
docker compose up -d
|
|
|
|
log 'Redeploy complete'
|