51 lines
2.6 KiB
Bash
Executable file
51 lines
2.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# =====================================================================================
|
|
# Add a second domain controller (replica) for availability.
|
|
#
|
|
# This runs the `replica` compose profile, which needs its own hostname/IP and the join
|
|
# credentials of an existing DC. Because the profile uses host networking it is meant to
|
|
# run on a SECOND MACHINE that has this repo synced to it (otherwise two containers fight
|
|
# over UDP/TCP 53, 88, 445...). For one machine, use macvlan instead.
|
|
#
|
|
# Required in .env on the replica machine:
|
|
# AD_DNS_DOMAIN / AD_REALM = the existing domain
|
|
# AD_HOSTNAME2=dc2
|
|
# AD_IP=<this machine's LAN ip>
|
|
# AD_JOIN_SERVER=dc1.ad.example.com
|
|
# AD_JOIN_USER=administrator
|
|
# AD_JOIN_PASSWORD (or secrets/join.password)
|
|
# =====================================================================================
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
. "$(dirname "$0")/envfile.sh"; ad_env_load .env # parsed, never executed (see envfile.sh)
|
|
|
|
[ -n "${AD_DNS_DOMAIN:-}" ] || { echo "set AD_DNS_DOMAIN to the existing domain in .env" >&2; exit 2; }
|
|
[ -n "${AD_HOSTNAME2:-}" ] || { echo "set AD_HOSTNAME2 (e.g. dc2) in .env" >&2; exit 2; }
|
|
[ -n "${AD_IP:-}" ] || { echo "set AD_IP to the reachable LAN address of this machine" >&2; exit 2; }
|
|
[ -n "${AD_JOIN_SERVER:-}" ] || { echo "set AD_JOIN_SERVER (existing DC FQDN) in .env" >&2; exit 2; }
|
|
|
|
echo ">> replica: ${AD_HOSTNAME2}.${AD_DNS_DOMAIN} joining via ${AD_JOIN_SERVER}"
|
|
|
|
# the joining DC must be able to resolve the existing DC before its own DNS is trustworthy
|
|
if ! getent hosts "$AD_JOIN_SERVER" >/dev/null 2>&1; then
|
|
echo "!! ${AD_JOIN_SERVER} does not resolve from this host."
|
|
echo " add AD_EXTRA_HOSTS=\"<ip> ${AD_JOIN_SERVER} ${AD_JOIN_SERVER%%.*}\" to .env"
|
|
exit 1
|
|
fi
|
|
|
|
# sanity: realm must be reachable over Kerberos before we attempt the join
|
|
if command -v kinit >/dev/null 2>&1; then
|
|
echo " (tip: pre-auth once with 'kinit administrator@${AD_REALM:-}' to catch realm/ clock problems early)"
|
|
fi
|
|
|
|
docker compose --profile replica up -d ad-dc2
|
|
sleep 20
|
|
AD_CONTAINER="${AD_CONTAINER2:-ad-dc2}" ./scripts/verify.sh || true
|
|
|
|
echo
|
|
echo "Post-join checklist"
|
|
echo " 1. DNS: point clients at BOTH DCs (DHCP option 006 = dc1,dc2)"
|
|
echo " 2. docker exec ${AD_CONTAINER2:-ad-dc2} samba-tool drs showrepl -> no failing inbound/outbound"
|
|
echo " 3. docker exec ${AD_CONTAINER2:-ad-dc2} samba-tool ntacl sysvolcheck"
|
|
echo " 4. from a joined Windows host: nltest /dsgetdc:${AD_DNS_DOMAIN^^} (should list both DCs)"
|
|
echo " 5. time sources: both DCs must be NTP-synced from outside; clients follow the PDC emulator"
|