Files
ad-ds-simple-file-server/redeploy
2026-06-24 10:33:52 +00:00

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'