Pages

Automating Multi-Host Active Directory Join on Linux

Managing Linux servers in an Active Directory (AD) environment can be tedious, especially when you have multiple hosts that need to join the domain. Doing this manually is time-consuming, error-prone, and inconsistent.
In this post, I’ll share a fully automated, secure, and parallelized Bash script that allows you to join multiple Linux hosts to an AD domain, configure SSSD, home directories, and sudo permissions for AD groups — all in one go.

Why Automation Matters
  • Manually joining Linux hosts to AD can involve:
  • Installing the required packages (realmd, sssd, adcli, etc.)
  • Editing /etc/resolv.conf and /etc/hosts
  • Configuring Kerberos encryption
  • Joining the AD domain using credentials
  • Setting up SSSD and home directory creation
  • Granting sudo privileges to AD groups
Doing this across 10, 50, or 100 hosts is not scalable. With this script, it becomes:
Secure – prompts once for your AD password and never stores it in plain text.
Parallel – all hosts are processed simultaneously for faster deployment.
Robust – logs are kept per host, so troubleshooting is easier.

The Script: Multi-Host AD Join
Below is the script. Save it as ad_join_multi_pw.sh, make it executable with chmod +x ad_join_multi_hosts.sh, and run it with your hostnames as arguments:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
#
# Author : adminCtrlX
# Description : Multi-host AD join with secure password prompt, parallel execution, logs
# Usage : ./ad_join_multi_hosts.sh host1 host2 host3
#
set -euo pipefail

### CHECK ARGUMENTS ###
if [ $# -lt 1 ]; then
echo "Usage: $0 <hostname1> [hostname2 ...]"
exit 1
fi

HOSTS=("$@")
AD_ADMIN="administrator"
AD_SERVER_FQDN="inddcpads01.ppc.com"
DOMAIN="ppc.com"
REALM="PPC.COM"
AD_GROUP="unix_admin"

# Prompt once for the AD password
read -s -p "Enter AD password for $AD_ADMIN: " AD_PASSWORD
echo
echo "===== Starting AD Integration for ${#HOSTS[@]} host(s) ====="

for TARGET_HOST in "${HOSTS[@]}"; do
(
LOG_FILE="/tmp/ad_join_${TARGET_HOST}.log"
echo "===== Starting AD join on $TARGET_HOST =====" | tee -a "$LOG_FILE"

ssh -q root@"$TARGET_HOST" bash -s "$DOMAIN" "$REALM" "$AD_SERVER_FQDN" "$AD_GROUP" "$AD_ADMIN" "$AD_PASSWORD" >> "$LOG_FILE" 2>&1 <<'REMOTE_EOF'

set -euo pipefail

# Assign positional parameters
DOMAIN="$1"
REALM="$2"
AD_SERVER_FQDN="$3"
AD_GROUP="$4"
AD_ADMIN="$5"
AD_PASSWORD="$6"
RESOLV_CONF="/etc/resolv.conf"
HOSTS_FILE="/etc/hosts"
SSSD_CONF="/etc/sssd/sssd.conf"
KRB_CRYPTO="/etc/krb5.conf.d/crypto-policies"
SUDOERS_FILE="/etc/sudoers.d/unix_admin"

echo "===== Running AD Integration on $(hostname) ====="

# Install required packages
dnf install -y realmd sssd oddjob oddjob-mkhomedir adcli samba-common-tools krb5-workstation

# Configure DNS (append safely)
grep -q "$DOMAIN" "$RESOLV_CONF" || echo "search $DOMAIN" >> "$RESOLV_CONF"
grep -q "192.168.10.100" "$RESOLV_CONF" || echo "nameserver 192.168.10.100" >> "$RESOLV_CONF"
grep -q "192.168.20.100" "$RESOLV_CONF" || echo "nameserver 192.168.20.100" >> "$RESOLV_CONF"

# Update /etc/hosts if missing
grep -q "$AD_SERVER_FQDN" "$HOSTS_FILE" || echo "192.168.10.100 $AD_SERVER_FQDN inddcpads01" >> "$HOSTS_FILE"

# Configure Kerberos crypto policies
mkdir -p "$(dirname "$KRB_CRYPTO")"
cat <<KRB > "$KRB_CRYPTO"
[libdefaults]
permitted_enctypes = aes256-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 camellia256-cts-cmac aes128-cts-hmac-sha1-96 aes128-cts-hmac-sha256-128 camellia128-cts-cmac rc4-hmac
KRB

# Join AD domain using password
echo "$AD_PASSWORD" | realm join -v -U "$AD_ADMIN" "$AD_SERVER_FQDN"

# Configure SSSD
cat <<SSSD > "$SSSD_CONF"
[sssd]
domains = $DOMAIN
services = nss, pam
[domain/$DOMAIN]
id_provider = ad
ad_domain = $DOMAIN
krb5_realm = $REALM
cache_credentials = True
use_fully_qualified_names = False
fallback_homedir = /home/%u
default_shell = /bin/bash
access_provider = simple
simple_allow_groups = $AD_GROUP
SSSD

chmod 600 "$SSSD_CONF"
systemctl enable --now sssd

# Ensure oddjobd for home directories
systemctl enable --now oddjobd.service
authselect select sssd with-mkhomedir --force

# Configure sudoers for AD group
echo "%$AD_GROUP ALL=(ALL) NOPASSWD: ALL" > "$SUDOERS_FILE"
chmod 440 "$SUDOERS_FILE"
visudo -cf "$SUDOERS_FILE"

# Permit AD group
realm permit -g "$AD_GROUP"
echo "===== AD Integration Completed on $(hostname) ====="
REMOTE_EOF
echo "===== Finished AD join on $TARGET_HOST. Log: $LOG_FILE ====="
) &
done

# Wait for all parallel jobs to finish
wait
unset AD_PASSWORD
echo "===== All AD joins completed ====="
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
How It Works
The script prompts for the AD administrator password once and never stores it.
Each host is joined to AD in parallel, logging progress to /tmp/ad_join_<hostname>.log.
DNS and /etc/hosts are updated safely.
Kerberos encryption is configured to meet AD standards.
SSSD is configured for AD authentication, with automatic home directory creation (oddjobd).
The specified AD group (unix_admin) is granted sudo privileges.

Usage Example
chmod +x ad_join_multi_hosts.sh
./ad_join_multi_hosts.sh host1 host2 host3
Check logs for each host in /tmp/ad_join_<hostname>.log.
After completion, all hosts will be AD-joined, with SSSD running and AD users able to log in with home directories and sudo privileges.

Benefits
Fast – parallel execution saves time.
Secure – password handled safely.
Reproducible – consistent configuration across all hosts.
Auditable – per-host logs help track exactly what happened.

This script is perfect for Linux administrators managing multiple AD-integrated servers in enterprise environments.

No comments:

Post a Comment