Execute the following steps to configure "VM Customization Specifications":
1. Prepare a Debian OS template with the necessary software that should already be included with new hosts.
2. Make sure to install "open-vm-tools" and verify that the "vmtoolsd" service is set to autostart:
sudo apt-get install open-vm-tools
sudo systemctl enable vmtoolsd && sudo systemctl start vmtoolsd
3. Enable support for customization scripts:
sudo vmware-toolbox-cmd config set deployPkg enable-custom-scripts true
To check the current status of the parameter, execute:
sudo vmware-toolbox-cmd config get deployPkg enable-custom-scripts
4. Next, configure "VM Customization Specifications" on vCenter Server. During configuration, specify: OS type - Linux, hostname generation rules, time zone, TCP/IP settings, and add the following script:
#!/bin/bash
# Function to convert subnet mask to CIDR prefix
mask2cidr() {
local mask=$1
local n=0
IFS=.
for byte in $mask; do
case $byte in
255) n=$((n+8));;
254) n=$((n+7));;
252) n=$((n+6));;
248) n=$((n+5));;
240) n=$((n+4));;
224) n=$((n+3));;
192) n=$((n+2));;
128) n=$((n+1));;
0);;
*) echo 24; return 1;;
esac
done
echo $n
}
# Function to determine network management method with priority: NM -> SystemD -> Ifupdown
get_network_manager() {
local interface=$1
# 1. Check NetworkManager first
if command -v nmcli >/dev/null 2>&1; then
# Check if the interface is managed by NetworkManager
if nmcli -t -f DEVICE device 2>/dev/null | grep -q "^${interface}$"; then
echo "NetworkManager"
return
fi
# Check if NetworkManager is active as a service
if systemctl is-active NetworkManager >/dev/null 2>&1; then
echo "NetworkManager"
return
fi
# Check if there is a NetworkManager connection for this interface
if nmcli -t -f NAME,DEVICE connection show 2>/dev/null | grep -q ":${interface}$"; then
echo "NetworkManager"
return
fi
fi
# 2. Check systemd-networkd
if systemctl is-active systemd-networkd >/dev/null 2>&1 && \
systemctl is-active systemd-resolved >/dev/null 2>&1; then
echo "SystemD"
return
fi
# 3. Check ifupdown (traditional Debian method)
if [ -f "/etc/network/interfaces" ]; then
# Check if the interface is mentioned in the configuration
if grep -q -E "^(auto|allow-hotplug|iface|mapping).*${interface}" /etc/network/interfaces; then
echo "Ifupdown"
return
fi
# Check for configs in interfaces.d
if [ -d "/etc/network/interfaces.d" ]; then
for config in /etc/network/interfaces.d/*; do
if [ -f "$config" ] && grep -q "${interface}" "$config"; then
echo "Ifupdown"
return
fi
done
fi
fi
# Check if the networking service (ifupdown) is active
if systemctl is-active networking >/dev/null 2>&1; then
echo "Ifupdown"
return
fi
# 4. If nothing is found, check by service presence
if systemctl is-enabled NetworkManager >/dev/null 2>&1; then
echo "NetworkManager"
elif systemctl is-enabled systemd-networkd >/dev/null 2>&1; then
echo "SystemD"
elif systemctl is-enabled networking >/dev/null 2>&1; then
echo "Ifupdown"
else
# If nothing is determined, use ifupdown as a fallback
echo "Ifupdown"
fi
}
# Function to configure NetworkManager
configure_networkmanager() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
# Delete existing connection for this interface
nmcli connection delete "$interface" 2>/dev/null || true
nmcli connection delete "Wired connection 1" 2>/dev/null || true
nmcli connection delete "System ${interface}" 2>/dev/null || true
# Create a new connection
if [ "$bootproto" = "static" ]; then
local prefix_length=$(mask2cidr "$netmask")
nmcli con add type ethernet con-name "$interface" ifname "$interface" ipv4.method manual \
ipv4.addresses "${ipaddr}/${prefix_length}" \
ipv4.gateway "$gateway" \
ipv4.dns "$dns_servers" \
ipv4.dns-search "$domain" \
autoconnect yes
else
nmcli con add type ethernet con-name "$interface" ifname "$interface" \
ipv4.method auto autoconnect yes
fi
# Activate the connection
nmcli con up "$interface"
}
# Function to configure SystemD networkd
configure_systemd() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
local dns_from_dhcp=$8
# Make sure the service is active
systemctl enable systemd-networkd 2>/dev/null || true
systemctl start systemd-networkd 2>/dev/null || true
# Clear the /etc/systemd/network directory
rm -rf /etc/systemd/network/*
# Create basic configuration for loopback interface
mkdir -p /etc/systemd/network
cat > /etc/systemd/network/00-loopback.network <<EOF
[Match]
Name=lo
[Network]
Address=127.0.0.1/8
Address=::1/128
EOF
# Create configuration for the main interface
CONFIG_FILE="/etc/systemd/network/10-${interface}.network"
if [ "$bootproto" = "static" ]; then
if [ -z "$ipaddr" ] || [ -z "$netmask" ]; then
echo "Error: IPADDR and NETMASK are required for static configuration"
exit 1
fi
prefix_length=$(mask2cidr "$netmask")
if [ -z "$prefix_length" ]; then
prefix_length=24
fi
# Create config for static IP
cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface
[Network]
Address=$ipaddr/$prefix_length
EOF
if [ -n "$gateway" ]; then
echo "Gateway=$gateway" >> "$CONFIG_FILE"
fi
# Add DNS servers
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "DNS=$dns" >> "$CONFIG_FILE"
done
fi
else
# Create config for DHCP
cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface
[Network]
DHCP=ipv4
[DHCPv4]
UseDomains=true
EOF
# Configure DNS usage
if [ "$dns_from_dhcp" = "yes" ]; then
echo "UseDNS=yes" >> "$CONFIG_FILE"
else
echo "UseDNS=no" >> "$CONFIG_FILE"
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "DNS=$dns" >> "$CONFIG_FILE"
done
fi
fi
fi
# Configure systemd-resolved if needed
if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
mkdir -p /etc/systemd/resolved.conf.d
cat > /etc/systemd/resolved.conf.d/10-${interface}.conf <<EOF
[Resolve]
EOF
if [ -n "$dns_servers" ]; then
echo "DNS=$dns_servers" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
fi
if [ -n "$domain" ]; then
echo "Domains=$domain" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
fi
systemctl enable systemd-resolved 2>/dev/null || true
systemctl start systemd-resolved 2>/dev/null || true
# Create symlink for resolv.conf
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 2>/dev/null || true
fi
systemctl restart systemd-networkd
if systemctl is-active systemd-resolved >/dev/null 2>&1; then
systemctl restart systemd-resolved
fi
}
# Function to configure Ifupdown (/etc/network/interfaces)
configure_ifupdown() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
echo "Configuring interface $interface using ifupdown" >&2
# Create base interfaces file if it doesn't exist
if [ ! -f /etc/network/interfaces ]; then
mkdir -p /etc/network
cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
EOF
fi
# Remove ALL configuration for this interface
# Create temporary file without current interface configuration
tmpfile=$(mktemp)
in_block=0
while IFS= read -r line; do
# Check if a new interface block starts
if [[ "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+$interface([[:space:]]|$) ]]; then
in_block=1
continue
fi
# If we are inside a block and encounter another block start, exit the block
if [[ $in_block -eq 1 && "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+ ]]; then
in_block=0
fi
# If we are not inside the block of the interface being removed, save the line
if [[ $in_block -eq 0 ]]; then
echo "$line" >> "$tmpfile"
fi
done < /etc/network/interfaces
# Copy back and remove temporary file
mv "$tmpfile" /etc/network/interfaces
chmod 644 /etc/network/interfaces
# Remove possible duplicate empty lines
sed -i '/^$/N; /^\n$/D' /etc/network/interfaces
sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' /etc/network/interfaces
# Add new configuration
{
echo ""
echo "auto $interface"
if [ "$bootproto" = "static" ]; then
echo "iface $interface inet static"
echo " address $ipaddr"
echo " netmask $netmask"
[ -n "$gateway" ] && echo " gateway $gateway"
[ -n "$dns_servers" ] && echo " dns-nameservers $dns_servers"
[ -n "$domain" ] && echo " dns-search $domain"
else
echo "iface $interface inet dhcp"
fi
} >> /etc/network/interfaces
# Configure DNS via resolvconf if installed
if command -v resolvconf >/dev/null 2>&1; then
# Create temporary file for resolvconf
TMP_RESOLV="/tmp/resolv.conf.${interface}"
echo "# Generated by network configuration script" > "$TMP_RESOLV"
if [ -n "$domain" ]; then
echo "domain $domain" >> "$TMP_RESOLV"
echo "search $domain" >> "$TMP_RESOLV"
fi
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "nameserver $dns" >> "$TMP_RESOLV"
done
fi
# Update resolvconf
resolvconf -a "${interface}" < "$TMP_RESOLV" 2>/dev/null || true
rm -f "$TMP_RESOLV"
else
# Direct configuration of /etc/resolv.conf
if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
echo "# Generated by network configuration script" > /etc/resolv.conf
if [ -n "$domain" ]; then
echo "domain $domain" >> /etc/resolv.conf
echo "search $domain" >> /etc/resolv.conf
fi
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "nameserver $dns" >> /etc/resolv.conf
done
fi
fi
fi
# Restart network service
if systemctl is-active networking >/dev/null 2>&1; then
systemctl restart networking
else
# Old method of network restart
ifdown "$interface" 2>/dev/null || true
ifup "$interface" 2>/dev/null || true
fi
}
# --- Function to clean logs and temporary files ---
clean_system() {
# Clean logs (preserving directory structure)
find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
find /var/log -type f -name "*.gz" -delete 2>/dev/null || true
find /var/log -type f -name "*.old" -delete 2>/dev/null || true
find /var/log -type f -name "lastlog" -exec rm -f {} \; 2>/dev/null || true
# Clean temporary files
rm -rf /tmp/* 2>/dev/null || true
rm -rf /var/tmp/* 2>/dev/null || true
# Clean command history and user data
for user_home in /home/*; do
if [[ -d "$user_home" ]]; then
user=$(basename "$user_home")
# Clean bash_history and other histories
truncate -s 0 "$user_home/.bash_history" 2>/dev/null || true
# Clean application caches
rm -rf "$user_home/.cache/*" 2>/dev/null || true
fi
done
# Clean root
truncate -s 0 /root/.bash_history 2>/dev/null || true
rm -rf /root/.cache/* 2>/dev/null || true
# Delete random seed files
rm -f /var/lib/systemd/random-seed 2>/dev/null || true
}
# --- Function to delete SSH host keys ---
reset_ssh_keys() {
rm -f /etc/ssh/ssh_host_* 2>/dev/null || true
# Regenerate SSH server keys
if command -v dpkg-reconfigure >/dev/null 2>&1; then
dpkg-reconfigure -f noninteractive openssh-server 2>/dev/null || true
fi
# Alternative method for Debian
if [ -x /usr/sbin/sshd ]; then
/usr/sbin/sshd-keygen -A 2>/dev/null || true
fi
}
# ============================================================
# Main script logic
# ============================================================
if [ "$1" = "precustomization" ]; then
# Perform system cleanup
clean_system
# Check and create /etc/network/interfaces
if [ ! -f /etc/network/interfaces ]; then
echo "Creating /etc/network/interfaces file"
mkdir -p /etc/network
cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
EOF
fi
# Check and create /etc/sysconfig/network-scripts directory if needed
if [ ! -d "/etc/sysconfig/network-scripts" ]; then
mkdir -p /etc/sysconfig/network-scripts 2>/dev/null || true
fi
# Pre-configuration stage
VMCUST_DIR=$(ls -d /var/run/.vmware-imgcust* 2>/dev/null | head -n 1)
if [ -n "$VMCUST_DIR" ]; then
CUST_CFG_PATH="$VMCUST_DIR/cust.cfg"
if [ -f "$CUST_CFG_PATH" ]; then
cp "$CUST_CFG_PATH" "/root/cust.cfg"
fi
fi
elif [ "$1" = "postcustomization" ]; then
# Post-configuration stage
reset_ssh_keys
if [ ! -f "/root/cust.cfg" ]; then
echo "Error: configuration file /root/cust.cfg not found"
exit 1
fi
CFG_FILE="/root/cust.cfg"
# Parse configuration parameters
BOOTPROTO=$(awk -F' = ' '/^BOOTPROTO/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
IPADDR=$(awk -F' = ' '/^IPADDR/ {line=$2} END{print line}' "$CFG_FILE")
NETMASK=$(awk -F' = ' '/^NETMASK/ {line=$2} END{print line}' "$CFG_FILE")
GATEWAY=$(awk -F' = ' '/^GATEWAY/ {line=$2} END{print line}' "$CFG_FILE")
HOSTNAME=$(awk -F' = ' '/^HOSTNAME/ {line=$2} END{print line}' "$CFG_FILE")
DOMAIN=$(awk -F' = ' '/^DOMAINNAME/ {line=$2} END{print line}' "$CFG_FILE")
MACADDR=$(awk -F' = ' '/^MACADDR/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
DNS_SERVERS=$(awk -F' = ' '/^NAMESERVER\|[0-9]/ {print $2}' "$CFG_FILE" | tr '\n' ' ' | sed 's/ $//')
DNS_FROM_DHCP=$(awk -F' = ' '/^DNSFROMDHCP/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
TIMEZONE=$(awk -F' = ' '/^TIMEZONE/ {line=$2} END{print line}' "$CFG_FILE")
UTC=$(awk -F' = ' '/^UTC/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
# Determine network interface
INTERFACE=$(ip -o link | awk -v mac="$MACADDR" 'tolower($0) ~ mac {gsub(":", "", $2); print $2}')
if [ -z "$INTERFACE" ]; then
INTERFACE=$(ip route | awk '/default/ {print $5; exit}')
fi
if [ -z "$INTERFACE" ]; then
# Last attempt: take the first Ethernet interface
INTERFACE=$(ip -o link | awk -F': ' '$2 !~ /^lo|virbr|docker|veth/ {print $2; exit}' | sed 's/@.*//')
fi
if [ -z "$INTERFACE" ]; then
echo "Error: could not determine network interface"
exit 1
fi
# Determine network management method
NET_MGR=$(get_network_manager "$INTERFACE")
echo "Determined network management method: $NET_MGR for interface $INTERFACE"
case "$NET_MGR" in
"NetworkManager")
configure_networkmanager "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
"SystemD")
configure_systemd "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN" "$DNS_FROM_DHCP"
;;
"Ifupdown")
configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
*)
echo "Unknown network management method, using ifupdown as fallback"
configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
esac
# Common settings
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || echo "$HOSTNAME" > /etc/hostname
sed -i "/127\.0\.1\.1/d" /etc/hosts
echo "127.0.1.1 $HOSTNAME.$DOMAIN $HOSTNAME" >> /etc/hosts
# Configure time zone
if [ -n "$TIMEZONE" ]; then
timedatectl set-timezone "$TIMEZONE" 2>/dev/null || true
# Alternative method for Debian
if [ -f "/usr/share/zoneinfo/$TIMEZONE" ]; then
cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime 2>/dev/null || true
echo "$TIMEZONE" > /etc/timezone 2>/dev/null || true
fi
fi
# Configure BIOS time format (UTC or local)
if [ -n "$UTC" ]; then
if [ "$UTC" = "yes" ]; then
# Set UTC time in BIOS
timedatectl set-local-rtc 0 2>/dev/null || true
else
# Set local time in BIOS
timedatectl set-local-rtc 1 2>/dev/null || true
fi
fi
# Save configuration
CONFIG_LOG="/root/vm-customization.log"
{
echo "=========================================="
echo "Configuration completed: $(date)"
echo "=========================================="
echo "CONFIG_SOURCE=$CFG_FILE"
echo "BOOTPROTO=$BOOTPROTO"
echo "INTERFACE=$INTERFACE"
echo "NETWORK_MANAGER=$NET_MGR"
echo "HOSTNAME=$HOSTNAME"
echo "DOMAIN=$DOMAIN"
echo "TIMEZONE=$TIMEZONE"
echo "UTC=$UTC"
[ -n "$DNS_FROM_DHCP" ] && echo "DNS_FROM_DHCP=$DNS_FROM_DHCP"
[ -n "$DNS_SERVERS" ] && echo "DNS_SERVERS=\"$DNS_SERVERS\""
if [ "$BOOTPROTO" = "static" ]; then
echo "IP_ADDRESS=$IPADDR"
echo "NETMASK=$NETMASK"
[ -n "$GATEWAY" ] && echo "GATEWAY=$GATEWAY"
fi
} > "$CONFIG_LOG"
rm -f "/root/cust.cfg"
# Sync changes to disk
sync
echo "Configuration completed successfully. Network management method: $NET_MGR"
##############################################################################################
# PLACE FOR ADDITIONAL SYSTEM CONFIGURATION
# Here you can add commands for final machine setup:
# - Installing additional necessary software
# - Configuration via Ansible or other configuration management systems
# - Execution of user scripts
# - Setting up monitoring, logging, and other services
# Example: install basic packages
# apt-get update && apt-get install -y curl wget net-tools
##############################################################################################
fi
This script covers all possible network configuration options: IfUpDown, NetworkManager, Systemd-Networkd, both with static IP and DHCP.
No comments:
Post a Comment