Engineers on-premises infrastructure including IPMI/iLO/iDRAC remote
Install to Claude Code
npx -y skills add paulpas/agent-skill-router --skill on-prem-infrastructure --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of On Prem Infrastructure?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/paulpas-on-prem-infrastructure)More formats (shields.io, HTML) on the badges page.
---
name: on-prem-infrastructure
description: Engineers on-premises infrastructure including IPMI/iLO/iDRAC remote
management, PXE deployment, network storage (NFS/iSCSI/FC), multipath I/O, and datacenter
physical operations for bare-metal Linux systems.
license: MIT
compatibility: opencode
metadata:
version: "1.0.0"
domain: linux
triggers: IPMI, iLO, iDRAC, PXE boot, iSCSI, multipath, bare-metal provisioning,
datacenter rack
archetypes:
- tactical
anti_triggers:
- brainstorming
- vague ideation
response_profile:
verbosity: low
directive_strength: high
abstraction_level: operational
role: implementation
scope: infrastructure
output-format: code
content-types:
- code
- guidance
- config
- do-dont
related-skills: hardware-provisioning, networking, kernel-tuning, linux-security
maturity: draft
completeness: 90
exampleCount: 6
---
# On-Premises Infrastructure Engineering
Infrastructure engineer managing physical servers, datacenter operations, and network-attached hardware for on-premises Linux environments — covering remote management (IPMI/iLO/iDRAC), PXE deployment, network storage (NFS/iSCSI/FC), multipath I/O, and datacenter physical operations.
## TL;DR Checklist
- [ ] Verify BMC/management interface accessibility via IPMI before any remote hardware operation
- [ ] Configure multipath I/O for all SAN-attached storage with appropriate failover policy
- [ ] Set up NFS mounts with hard/async or soft/sync options matching workload criticality
- [ ] Test PXE boot workflow with a non-production host before mass deployment
- [ ] Validate NTP/PTP synchronization across all on-prem systems for time-sensitive operations
- [ ] Check thermal and power metrics (sensors, PDU) before any hardware replacement procedure
- [ ] Document datacenter rack position, U slot, cable IDs, and BMC IP for every server
---
## When to Use
Use this skill when:
- **Managing remote server hardware** — You need to interact with IPMI, iLO, or iDRAC interfaces for power control, console access, or hardware diagnostics
- **Deploying OS at scale** — You need to set up PXE boot infrastructure for network-based operating system installation across multiple bare-metal servers
- **Configuring network-attached storage** — You need to set up NFS mounts, iSCSI targets/initiators, or Fibre Channel HBA configuration
- **Troubleshooting on-prem storage** — SAN/NAS connectivity issues, multipath I/O problems, or HBA firmware/configuration
- **Datacenter physical operations** — You need guidance on rack positioning, cable management, power/cooling considerations, or hardware replacement procedures
- **Hardware diagnostics at scale** — You need to run ECC memory tests, thermal monitoring, or SMART analysis across many servers
---
## When NOT to Use
Avoid this skill for:
- **Cloud instance provisioning** — Use `hardware-provisioning` for cloud instances (AWS EC2, GCP, Azure VMs)
- **Virtual network configuration** — Use `networking` for bond interfaces, VLANs, and nftables firewall rules
- **Kernel parameter tuning** — Use `kernel-tuning` for TCP stack, filesystem, or I/O scheduler parameters
- **Software application development** — This skill covers infrastructure, not application-level concerns
Use `hardware-provisioning` for RAID array configuration (local storage), SSD optimization, and initial workload-to-hardware matching. Use `hardware-provisioning` when the task is about selecting or sizing hardware before deployment.
---
## Core Workflow
### 1. Verify Management Interface Accessibility
Before any remote hardware operation, confirm the BMC/management interface is reachable and responsive.
```bash
# Test IPMI connectivity to BMC
sudo ipmitool -I lanplus -H <BMC_IP> -U <username> -P '<password>' chassis power status
# If IPMI over LAN is blocked, try serial-over-LAN (SOL)
sudo ipmitool -I lanplus -H <BMC_IP> -U <username> -P '<password>' sol activate
# For iLO (HPE) — use the hponcfg or ipmitool with iLO-specific commands
sudo ipmitool -I lanplus -H <ILO_IP> -U admin chassis power status
# For iDRAC (Dell) — check iDRAC specific sensors and alerts
sudo ipmitool -I lanplus -H <IDRAC_IP> -U root sdr type "Temperature"
sudo ipmitool -I lanplus -H <IDRAC_IP> -U root event list
# Bulk check all BMCs from an inventory file
while IFS=',' read -r hostname bmc_ip bmc_user bmc_pass; do
status=$(sudo ipmitool -I lanplus -H "$bmc_ip" -U "$bmc_user" -P "$bmc_pass" chassis power status 2>&1)
echo "$hostname | BMC: $bmc_ip | Power: $status"
done < /opt/inventory/bmc_hosts.csv
```
**Checkpoint:** All target BMCs respond to basic IPMI commands. If a BMC is unreachable, verify network connectivity to the management VLAN (typically UDP port 623) and that the BMC is powered on.
### 2. Assess Hardware Health via BMC and Sensors
Gather a comprehensive hardware health picture before making changes or planning maintenance.
```bash
# Comprehensive hardware health check script
# Usage: ./hardware-health-check.sh [--bmc <ip> --user <u> --pass <p>] [--local]
set -euo pipefail
BMC_IP="${BMC_IP:-}"
BMC_USER="${BMC_USER:-}"
BMC_PASS="${BMC_PASS:-}"
MODE="${1:---local}"
check_local_health() {
echo "=== Local Hardware Health ==="
# CPU temperatures and fan speeds via lm-sensors
echo "--- Thermal Sensors ---"
sudo sensors 2>/dev/null || echo "lm-sensors not configured. Run: sudo sensors-detect"
# SMART health for all disks
echo "--- Disk SMART Health ---"
for dev in /dev/sd* /dev/nvme*; do
[[ -b "$dev" ]] || continue
echo -n "$dev: "
sudo smartctl -H "$dev" 2>/dev/null | grep -oP 'Overall-health.*?\K.*' || echo "N/A"
done
# ECC memory errors (if available)
echo "--- Memory Error Counts ---"
if command -v edac-util &>/dev/null; then
edac-util -v 2>/dev/null || echo "EDAC not reporting errors"
elif [[ -f /sys/devices/system/edac/mc/mc*/csrow*/ch*_ce_count ]]; then
echo "Correctable errors:"
cat /sys/devices/system/edac/mc/mc*/csrow/*/ch*_ce_count 2>/dev/null || echo "N/A"
else
echo "EDAC interface not available — ECC error monitoring requires kernel support"
fi
# PSU status via DMI
echo "--- PSU Status ---"
sudo ipmitool sdr type "Power Supply" 2>/dev/null || echo "IPMI not available for PSU check"
}
check_bmc_health() {
echo "=== BMC-Managed Hardware Health ==="
# SEL (System Event Log) — critical for failure forensics
echo "--- System Event Log (last 20 entries) ---"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" sel list 2>/dev/null | tail -20
# FRU (Field Replaceable Unit) information
echo "--- Field Replaceable Unit Info ---"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" fru print 2>/dev/null || echo "FRU info unavailable"
# Asset tag
echo "--- Asset Information ---"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" fru print "Asset Tag" 2>/dev/null || echo "Asset tag unavailable"
# Power supply status
echo "--- Power Supplies ---"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" sdr type "Power Supply" 2>/dev/null
# Thermal status
echo "--- Thermal Readings ---"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" sdr type "Temperature" 2>/dev/null
}
case "$MODE" in
--local) check_local_health ;;
--bmc) check_bmc_health ;;
*) check_local_health; check_bmc_health ;;
esac
```
**Checkpoint:** SEL logs are reviewed for recurring errors, SMART health is green for all disks, and thermal readings are within manufacturer specifications. Any anomalies are documented before proceeding.
### 3. Configure Network-Attached Storage
Set up the appropriate network storage protocol based on workload requirements.
```bash
# =============================================
# Pattern 1: NFS Mount Configuration
# =============================================
# NFS mount options — choose based on workload:
# hard,intr — Retry forever on server failure (databases, filesystems)
# soft,timeo=N — Return errors after timeout (non-critical, interactive)
# async — Improve write performance (non-critical data)
# sync — Guarantee writes are flushed (critical data)
# noatime — Skip access time updates (performance)
# /etc/fstab entry for NFS
cat >> /etc/fstab << 'FSTAB'
# Production database storage — hard mount, noatime, sync
server1.example.com:/data/db /mnt/db nfs4 hard,intr,rsize=131072,wsize=131072,noatime,sync 0 0
# General file storage — hard mount, async, noatime
server1.example.com:/data/files /mnt/files nfs4 hard,intr,rsize=131072,wsize=131072,noatime,async 0 0
# Temporary/scratch storage — soft mount, async, noatime
server2.example.com:/data/scratch /mnt/scratch nfs4 soft,timeo=50,retrans=2,noatime,async 0 0
FSTAB
# Verify mount
sudo mount -a
df -h /mnt/db /mnt/files /mnt/scratch
# NFS client performance tuning
cat > /etc/sysctl.d/99-nfs-client.conf << 'SYSCTL'
# NFS client socket buffer tuning
net.core.rmem_max = 16777216
net.core.rmem_default = 1048576
net.core.wmem_max = 16777216
net.core.wmem_default = 1048576
# NFS mount timeout tuning
fs.nfs.tcp_write_timeout_min = 1000
fs.nfs.tcp_read_timeout_list = 600 1000 2000 4000
SYSCTL
sudo sysctl -p /etc/sysctl.d/99-nfs-client.conf
# =============================================
# Pattern 2: iSCSI Initiator Configuration
# =============================================
# Install iSCSI initiator tools
sudo apt install -y open-iscsi iscsadm # Debian/Ubuntu
sudo dnf install -y iscsi-initiator-utils # RHEL/CentOS/Alma
# Discover targets on the iSCSI network
iscsiadm -m discovery -t st -p 10.100.50.10:3260
iscsiadm -m discovery -t st -p 10.100.50.11:3260
# Log into discovered targets (persistent across reboots)
iscsiadm -m node -T iqn.2001-04.com.example:storage.disk1 --login
# Set initiator name in config
cat > /etc/iscsi/initiatorname.iscsi << 'INITIATOR'
InitiatorName=iqn.2025-01.local:hostname.example.com
INITIATOR
# Configure CHAP authentication (required by most SAN arrays)
cat > /etc/iscsi/iscsid.conf << 'ISCSID'
# CHAP authentication to target
node.session.auth.authmethod = CHAP
node.session.auth.username = initiator_user
node.session.auth.password = secret_password
# Enable multipath-friendly path detection
node.conn[0].timeo.noop_out_interval = 5
node.conn[0].timeo.noop_out_timeout = 5
node.conn[0].timeo.initial_r2t_time = 0
ISCSID
# =============================================
# Pattern 3: Multipath I/O Configuration
# =============================================
# Install and configure multipath-tools
sudo apt install -y multipath-tools # Debian/Ubuntu
sudo dnf install -y device-mapper-multipath # RHEL/CentOS
# Start multipath service
sudo systemctl enable --now multipathd
# Configure multipath
cat > /etc/multipath.conf << 'MULTIPATH'
defaults {
user_friendly_names yes
find_multipaths yes
max_fds 8192
}
devices {
device {
vendor "DELL"
product "MD38xx"
path_checker tur
path_selector "service-time 0"
hardware_handler "1 alua"
failback immediate
no_path_retry 18
rr_weight priorities
features "1 queue_if_no_path"
prio alua
}
device {
vendor "HPE"
product "P6000"
path_checker tur
path_selector "service-time 0"
hardware_handler "1 alua"
failback immediate
no_path_retry 18
prio alua
}
device {
vendor "NETAPP"
product "LUN"
path_checker tur
path_selector "service-time 0"
hardware_handler "1 alua"
failback immediate
no_path_retry 18
prio alua
}
}
blacklist {
devnode "^sda" # Exclude local OS disk
devnode "^nvme[0-9]n1" # Exclude local NVMe
}
MULTIPATH
# Reload and verify multipath
sudo multipath -r
sudo multipath -ll
# Expected output shows multiple paths per device with failover
# dm-0 (3600601603e1d2800d6e9f0a1b3c4d5e6) dm-0 DEVEL,MD38xx
# size=2.0T features='1 queue_if_no_path' hwhandler='1 alua'
# \_ round-robin 0 [prio=200][active]
# \_ 3:0:0:0 sdb 8:16 [ready][running]
# \_ 4:0:0:0 sdc 8:32 [ready][running]
```
**Checkpoint:** All storage paths are visible via `multipath -ll`, the device is marked active, and failover paths are ready. For NFS, verify the mount with `mount | grep nfs` and test read/write operations.
### 4. Configure PXE Boot Infrastructure
Set up network-based OS deployment for bare-metal server provisioning.
```bash
# =============================================
# PXE Boot Infrastructure Setup
# =============================================
# Components needed:
# - DHCP server (isc-dhcp-server or dnsmasq)
# - TFTP server (tftpd-hpa or dnsmasq)
# - HTTP/HTTPS server (nginx/apache) for install media
# - Kickstart/PXE config files
# --- Step 1: DHCP Configuration ---
cat > /etc/dhcp/dhcpd.conf << 'DHCPD'
# PXE boot DHCP configuration
authoritative;
# Option for PXE client to find TFTP server
option tftp-server-name "10.0.1.20";
option bootfile-name "pxelinux.0";
subnet 10.0.1.0 netmask 255.255.255.0 {
range 10.0.1.100 10.0.1.200;
option routers 10.0.1.1;
option domain-name-servers 10.0.1.53, 8.8.8.8;
# PXE boot group — all hosts
next-server 10.0.1.20;
# Per-host PXE entries (optional, for specific provisioning)
# host server-rack1a {
# hardware ethernet 00:1a:2b:3c:4d:5e;
# fixed-address 10.0.1.10;
# option host-name "server-rack1a";
# }
}
DHCPD
# --- Step 2: TFTP Server Setup ---
sudo apt install -y tftpd-hpa # Debian/Ubuntu
sudo dnf install -y tftp-server # RHEL/CentOS
# Configure tftpd-hpa
sudo tee /etc/default/tftpd-hpa > /dev/null << 'TFTPD'
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --listen --map-file=/etc/tftpd-map"
TFTPD
# --- Step 3: Deploy PXE Boot Files ---
sudo mkdir -p /var/lib/tftpboot/{pxelinux.cfg,EFI/boot,kernel,initrd}
# Copy PXE boot loader (Syslinux)
sudo cp /usr/lib/syslinux/modules/bios/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/lib/syslinux/modules/bios/libutil.c32 /var/lib/tftpboot/
# UEFI boot
sudo cp /usr/lib/shim/shimx64.efi.signed /var/lib/tftpboot/EFI/boot/bootx64.efi 2>/dev/null || \
sudo cp /usr/lib/shim/shimx64.efi /var/lib/tftpboot/EFI/boot/bootx64.efi
# Copy kernel and initrd for the target OS
sudo cp /var/www/html/ubuntu/22.04/casper/vmlinuz /var/lib/tftpboot/kernel/vmlinuz-ubuntu2204
sudo cp /var/www/html/ubuntu/22.04/casper/initrd.lz /var/lib/tftpboot/initrd/initrd-ubuntu2204.lz
# PXE boot menu configuration
cat > /var/lib/tftpboot/pxelinux.cfg/default << 'PXE'
DEFAULT menu.c32
PROMPT 0
TIMEOUT 300
ONTIMEOUT ubuntu-local
LABEL ubuntu-local
MENU LABEL ^Local Boot
LOCALBOOT 0
LABEL ubuntu-2204-ks
MENU LABEL Ubuntu 22.04 ^Kickstart (Automated)
KERNEL /kernel/vmlinuz-ubuntu2204
APPEND initrd=/initrd/initrd-ubuntu2204.lz auto=true priority=critical \
url=http://10.0.1.20/ks/ubuntuks.cfg \
ip=dhcp netcfg/choose_interface=auto
LABEL ubuntu-2204-manual
MENU LABEL Ubuntu 22.04 ^Manual Install
KERNEL /kernel/vmlinuz-ubuntu2204
APPEND initrd=/initrd/initrd-ubuntu2204.lz auto=true priority=high \
ip=dhcp netcfg/choose_interface=auto
LABEL memtest
MENU LABEL ^Memory Test (Memtest86+)
KERNEL /kernel/memtest
PXE
# --- Step 4: Kickstart Configuration (RHEL/Alma) ---
cat > /var/www/html/ks/almalinux.cfg << 'KICKSTART'
# Auto-provisioned AlmaLinux 9
install
text
keyboard 'us'
lang en_US.UTF-8
network --bootproto=dhcp --device=eth0 --onboot=on --hostname=$HOSTNAME
rootpw --iscrypted <hashed_root_password>
timezone UTC --isUtc
bootloader --location=mbr --driveorder=sda --append="crashkernel=auto"
# Disk layout — wipe all disks
zerombr
clearpart --all --initlabel
part /boot --fstype=xfs --size=1024 --ondisk=sda
part / --fstype=xfs --size=100 --grow --ondisk=sda
# Firewall configuration
firewall --enabled --ssh
# Reboot after installation
reboot --exit
%packages
@core
@hardware-monitoring
smartmontools
ipmitool
net-tools
wget
curl
%end
%post
# Configure NTP
yum install -y chrony
systemctl enable --now chronyd
# Enable IPMI
systemctl enable --now ipmi
# Install monitoring agent
wget -O /usr/local/bin/node-exporter https://example.com/node_exporter
chmod +x /usr/local/bin/node-exporter
# Set up SSH authorized keys from config server
curl -s http://10.0.1.20/keys/$HOSTNAME.pub >> /root/.ssh/authorized_keys
# Update hostname
hostnamectl set-hostname $HOSTNAME
%end
KICKSTART
```
**Checkpoint:** PXE boot is verified by booting a test client. Confirm DHCP assigns the correct bootfile, TFTP serves the boot files, and the kickstart installation completes without manual intervention.
### 5. Configure Network Time Synchronization
Set up NTP or PTP for precision timing across on-prem infrastructure.
```bash
# =============================================
# Pattern 1: NTP with Chrony (recommended)
# =============================================
sudo apt install -y chrony # Debian/Ubuntu
sudo dnf install -y chrony # RHEL/CentOS
# Chrony configuration for on-prem datacenter
cat > /etc/chrony/chrony.conf << 'CHRONY'
# Datacenter NTP configuration
# Stratum 1: Direct GPS or PTP grandmaster
# Stratum 2: Local datacenter NTP servers
# Stratum 3+: All other servers
# External time sources (stratum 1)
server time.cloudflare.com iburst minpoll 4 maxpoll 6
server pool.ntp.org iburst minpoll 4 maxpoll 6
# Local stratum 1 reference (GPS or hardware clock)
# server 127.127.28.1 # GPS reference clock
# fudge 127.127.28.1 refid GPS
# Local NTP servers for the datacenter (stratum 2)
server ntp1.internal.corp iburst prefer
server ntp2.internal.corp iburst
# Allow local clients to sync from this server (if acting as NTP server)
# Allow subnet only — never open to the world
allow 10.0.0.0/8
allow 172.16.0.0/12
allow 192.168.0.0/16
# deny 0.0.0.0/0 # Explicit deny all others
# Local clock as fallback (when no external sources available)
local stratum 10
leapsectz right/UTC
# Record clock drift for analysis
driftfile /var/lib/chrony/drift
# Log every 30 minutes
logdir /var/log/chrony
log measurements statistics tracking
# Key tracking
keyfile /etc/chrony/chrony.keys
# Clock discipline
makestep 1.0 3
rtcsync
CHRONY
sudo systemctl enable --now chronyd
# Verify synchronization
chronyc tracking
chronyc sources -v
# =============================================
# Pattern 2: PTP (Precision Time Protocol) for sub-microsecond precision
# =============================================
# PTP is required for: financial trading, distributed databases, HPC clusters
# Requires: PTP-capable NIC, PTP grandmaster, linuxptp package
sudo apt install -y linuxptp # Debian/Ubuntu
sudo dnf install -y linuxptp # RHEL/CentOS
# PTP configuration — select the PTP-capable interface
# Check if NIC supports PTP
ethtool -T eth1 | grep "SOF_TIMESTAMPING"
# Configure phc2sys (hardware timestamping)
cat > /etc/ptp4l.conf << 'PTP'
[global]
default_ds.port_state_change_threshold 5
delay_mechanism E2E
time_stamping hardware
log_announce_interval -3
announce_receipt_timeout 4
sync_receipt_timeout 3
announce_interval -3
sync_interval -3
parentstats_mean_offset_threshold 10000000
assume_two_step 0
[eth1]
# PTP-enabled interface
delay_filter 2
PTP
# Start PTP clock
sudo ptp4l -i eth1 -f /etc/ptp4l.conf &
sudo phc2sys -a -s eth1
# Verify PTP sync
sudo phc_ctl eth1 getcrosstimestamp
sudo ptptime eth1
```
**Checkpoint:** `chronyc tracking` shows locked to a stratum 1 or 2 source with offset in acceptable range (< 1ms for NTP, < 1μs for PTP). `chronyc sources -v` shows at least one reachable source marked with `*`.
### 6. Hardware Replacement Procedure
When a component fails, follow a structured replacement procedure to minimize downtime and data loss.
```bash
#!/bin/bash
# Hardware replacement procedure — for use during maintenance windows
# Usage: ./hardware-replace.sh <component> <server> [--dry-run]
# Components: disk, memory, psu, hba, fan, cpu
set -euo pipefail
COMPONENT="${1:-}"
SERVER="${2:-}"
DRY_RUN="${3:---live}"
if [[ -z "$COMPONENT" || -z "$SERVER" ]]; then
echo "Usage: $0 <component> <server> [--dry-run]"
echo "Components: disk, memory, psu, hba, fan, cpu"
exit 1
fi
echo "=== Hardware Replacement Procedure ==="
echo "Component: $COMPONENT"
echo "Server: $SERVER"
echo "Mode: $DRY_RUN"
echo "=== "
# Pre-replacement checks
echo ""
echo "1. Pre-Replacement Health Check"
echo "---"
if [[ "$COMPONENT" == "disk" ]]; then
# Identify the failing disk
echo "Checking SMART status on all disks..."
for dev in /dev/sd* /dev/nvme*; do
[[ -b "$dev" ]] || continue
health=$(sudo smartctl -H "$dev" 2>/dev/null | grep -oP 'Overall-health.*?\K.*' || echo "unknown")
temp=$(sudo smartctl -A "$dev" 2>/dev/null | grep -i 'temperature' | head -1 | awk '{print $10}')
reallocated=$(sudo smartctl -A "$dev" 2>/dev/null | grep -i 'Reallocated_Sector' | awk '{print $10}')
echo " $dev: health=$health temp=${temp}C reallocated=$reallocated"
done
# Identify disk in RAID (if applicable)
if command -v mdadm &>/dev/null; then
echo ""
echo "RAID status:"
mdadm --detail --scan 2>/dev/null | while read -r line; do
echo " $line"
done
fi
if command -v multipath &>/dev/null; then
echo ""
echo "Multipath devices:"
multipath -ll 2>/dev/null | head -20
fi
fi
if [[ "$COMPONENT" == "psu" ]]; then
echo "Checking power supply status via IPMI..."
sudo ipmitool sdr type "Power Supply" 2>/dev/null || echo "IPMI unavailable"
sudo ipmitool sdr type "Voltage" 2>/dev/null | grep -i "psu\|power" || echo "No PSU voltage sensors found"
fi
if [[ "$COMPONENT" == "memory" ]]; then
echo "Checking memory error counts..."
if command -v edac-util &>/dev/null; then
edac-util -v 2>/dev/null || echo "No EDAC errors reported"
fi
dmesg | grep -iE 'mem|e?cc|uncorrectable' | tail -20 || echo "No memory errors in dmesg"
fi
# Pre-replacement data backup
echo ""
echo "2. Verify Data Backup Status"
echo "---"
echo " [!] Ensure backups are current before replacing any component"
echo " [!] For disk replacement, verify RAID sync is complete"
echo " [!] For PSU replacement, confirm UPS is connected and functional"
# Component-specific steps
echo ""
echo "3. Component-Specific Replacement Steps"
echo "---"
case "$COMPONENT" in
disk)
echo " a. Identify the failing disk: /dev/sdX"
echo " b. Mark disk as failed in RAID: mdadm /dev/md0 --fail /dev/sdX"
echo " c. Remove disk from RAID: mdadm /dev/md0 --remove /dev/sdX"
echo " d. Physically replace disk (hot-swap capable)"
echo " e. Add new disk: mdadm /dev/md0 --add /dev/sdX"
echo " f. Monitor rebuild: watch cat /proc/mdstat"
echo " g. Verify SMART on new disk: smartctl -a /dev/sdX"
;;
psu)
echo " a. Verify UPS is connected and functional"
echo " b. Check current PSU power draw: ipmitool sdr type 'Power Supply'"
echo " c. Power down if non-hot-swap: ipmitool power off"
echo " d. Replace PSU (observe ESD precautions)"
echo " e. Power on: ipmitool power on"
echo " f. Verify both PSUs are reporting: ipmitool sdr type 'Power Supply'"
;;
memory)
echo " a. Identify failed DIMM slot via BMC: ipmitool sdr type Memory"
echo " b. Power down the server"
echo " c. Replace DIMM (observe ESD precautions, match speed/capacity)"
echo " d. Power on and verify: dmidecode -t memory"
echo " e. Run memtest86+ if ECC errors persist"
;;
hba)
echo " a. Identify HBA and current paths: multipath -ll"
echo " b. Stop multipath: systemctl stop multipathd"
echo " c. Detach all paths: multipath -f all"
echo " d. Power down if non-hot-swap HBA"
echo " e. Replace HBA card"
echo " f. Power on, reload multipath: systemctl start multipathd"
echo " g. Verify paths: multipath -ll"
echo " h. Update firmware if needed: hpssacli ctrl all show config"
;;
fan)
echo " a. Identify failed fan via BMC: ipmitool sdr type 'Fan'"
echo " b. Hot-swap fan if supported (server must remain powered)"
echo " c. Verify fan speed recovery: ipmitool sdr type 'Fan'"
echo " d. Monitor temperature: ipmitool sdr type 'Temperature'"
;;
cpu)
echo " a. CPU replacement is a major operation"
echo " b. Power down and unplug server"
echo " c. Discharge residual power (hold power button 30s)"
echo " d. Replace CPU (match socket, TDP, stepping)"
echo " e. Apply fresh thermal paste"
echo " f. Power on and verify: lscpu"
echo " g. Run stress test: stress-ng --cpu 0"
;;
*)
echo " Unknown component: $COMPONENT"
echo " Valid components: disk, memory, psu, hba, fan, cpu"
exit 1
;;
esac
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo ""
echo "=== DRY RUN COMPLETE — No changes made ==="
else
echo ""
echo "=== Execute the above steps in your maintenance window ==="
echo "=== Ensure rollback procedures are documented ==="
fi
```
**Checkpoint:** After replacement, run a full hardware health check (step 2) to confirm the new component is recognized, reporting normal metrics, and no error messages appear in SEL or dmesg.
---
## Implementation Patterns
### Pattern 1: IPMI Remote Power Cycle (BAD vs. GOOD)
```bash
# ❌ BAD: Blindly powering cycle without checking health first
ipmitool -I lanplus -H $BMC_IP -U admin chassis power cycle
#
# Problems:
# - No health check before the power cycle
# - No confirmation the right BMC is targeted
# - No audit trail of the action
# - Could power cycle the wrong server in a large fleet
# ✅ GOOD: Safe remote power management with health checks and audit trail
#!/usr/bin/env bash
set -euo pipefail
BMC_IP="${1:?Usage: $0 <bmc_ip> <action>}"
ACTION="${2:-status}"
AUDIT_LOG="/var/log/ipmi-actions.log"
# Validate BMC IP format
if ! [[ "$BMC_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Invalid BMC IP: $BMC_IP" >&2
exit 1
fi
# Check BMC connectivity before acting
echo "Checking BMC connectivity..."
if ! sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" sdr 2>/dev/null | head -1 > /dev/null; then
echo "Error: BMC at $BMC_IP is unreachable" >&2
exit 1
fi
# Get hostname from inventory (correlate BMC to server)
get_hostname() {
local bmc_ip="$1"
grep "^$bmc_ip," /opt/inventory/bmc_hosts.csv | cut -d',' -f1 || echo "unknown-$bmc_ip"
}
HOSTNAME=$(get_hostname "$BMC_IP")
TIMESTAMP=$(date -Iseconds)
case "$ACTION" in
status)
echo "Power status of $HOSTNAME ($BMC_IP):"
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" chassis power status
;;
on)
echo "Powering ON $HOSTNAME..."
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" chassis power on
;;
off)
echo "Gracefully shutting down $HOSTNAME..."
# Prefer OS-level shutdown first (graceful)
ssh -o ConnectTimeout=5 root@"$HOSTNAME" 'poweroff' 2>/dev/null || {
echo "SSH shutdown failed. Using BMC power off."
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" chassis power off
}
;;
cycle)
echo "Power cycling $HOSTNAME..."
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" chassis power off
sleep 5
sudo ipmitool -I lanplus -H "$BMC_IP" -U "$BMC_USER" -P "$BMC_PASS" chassis power on
;;
*)
echo "Usage: $0 <bmc_ip> {status|on|off|cycle}"
exit 1
;;
esac
# Audit log entry
echo "$TIMESTAMP | $HOSTNAME | $BMC_IP | $ACTION | $(whoami)" >> "$AUDIT_LOG"
```
### Pattern 2: PXE Boot Health Check Before Mass Deployment
```bash
#!/usr/bin/env bash
# Validate PXE infrastructure before deploying to production fleet
set -euo pipefail
TFTP_DIR="/var/lib/tftpboot"
DHCPD_CONF="/etc/dhcp/dhcpd.conf"
HTTP_ROOT="/var/www/html"
echo "=== PXE Infrastructure Pre-Flight Check ==="
PASS=0
FAIL=0
check() {
local desc="$1"
local result="$2"
if [[ "$result" == "0" ]]; then
echo " [PASS] $desc"
((PASS++))
else
echo " [FAIL] $desc"
((FAIL++))
fi
}
# Check DHCP service
systemctl is-active --quiet dhcpd 2>/dev/null || systemctl is-active --quiet isc-dhcp-server 2>/dev/null
check "DHCP service is running" $?
# Check TFTP directory exists and has boot files
[[ -d "$TFTP_DIR" ]] && [[ -f "$TFTP_DIR/pxelinux.0" ]]
check "TFTP directory exists with pxelinux.0" $?
# Check PXE menu exists
[[ -f "$TFTP_DIR/pxelinux.cfg/default" ]]
check "PXE boot menu configuration exists" $?
# Check kernel and initrd are present
[[ -f "$TFTP_DIR/kernel/vmlinuz"* ]] && [[ -f "$TFTP_DIR/initrd/initrd"* ]]
check "Kernel and initrd files present" $?
# Check HTTP/HTTPS serve of kickstart files
curl -s -o /dev/null -w "%{http_code}" "http://localhost${HTTP_ROOT}" | grep -q "^200" || curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1${HTTP_ROOT}" | grep -q "^200"
check "Kickstart files are accessible via HTTP" $?
# Check DHCP configuration syntax
dhcpd -t 2>/dev/null
check "DHCP configuration syntax is valid" $?
# Check TFTP server is listening
ss -ulnp | grep -q ':69'
check "TFTP server is listening on UDP 69" $?
echo ""
echo "Results: $PASS passed, $FAIL failed"
if [[ "$FAIL" -gt 0 ]]; then
echo "Fix failures before PXE deployment!"
exit 1
fi
echo "PXE infrastructure is ready for deployment."
```
### Pattern 3: Bulk BMC Health Check Across Fleet
```bash
#!/usr/bin/env bash
# Check health of all BMCs in the datacenter
# Inventory CSV format: hostname,bmc_ip,bmc_user,bmc_pass,location,rack
set -euo pipefail
INVENTORY="/opt/inventory/bmc_hosts.csv"
RESULTS="/tmp/bmc-health-$(date +%Y%m%d-%H%M%S).csv"
TIMEOUT=5
echo "hostname,bmc_ip,status,power,alert_count,last_check" > "$RESULTS"
if [[ ! -f "$INVENTORY" ]]; then
echo "Error: Inventory file not found: $INVENTORY" >&2
exit 1
fi
# Skip header line
tail -n +2 "$INVENTORY" | while IFS=',' read -r hostname bmc_ip bmc_user bmc_pass location rack; do
TIMESTAMP=$(date -Iseconds)
# Test BMC connectivity
if ! sudo ipmitool -I lanplus -H "$bmc_ip" -U "$bmc_user" -P "$bmc_pass" -t "$TIMEOUT" chassis power status &>/dev/null; then
echo "$hostname,$bmc_ip,unreachable,-,-,$TIMESTAMP" >> "$RESULTS"
continue
fi
# Get power status
power=$(sudo ipmitool -I lanplus -H "$bmc_ip" -U "$bmc_user" -P "$bmc_pass" chassis power status 2>/dev/null | grep -oP 'Chassis Power.*?\K.*' || echo "unknown")
# Count recent SEL alerts (last 24h)
alert_count=$(sudo ipmitool -I lanplus -H "$bmc_ip" -U "$bmc_user" -P "$bmc_pass" sel elist 2>/dev/null | wc -l || echo "0")
# Determine status
if [[ "$alert_count" -gt 10 ]]; then
status="degraded"
elif [[ "$power" == "on" ]]; then
status="healthy"
else
status="powered-off"
fi
echo "$hostname,$bmc_ip,$status,$power,$alert_count,$TIMESTAMP" >> "$RESULTS"
done
echo ""
echo "=== BMC Health Summary ==="
echo "Results saved to: $RESULTS"
echo ""
cat "$RESULTS"
```
---
## Constraints
### MUST DO
- **MUST** verify BMC connectivity and power status before any remote power operation — never assume the server is in the expected state
- **MUST** use `multipath-tools` with `ALUA` path priority for all iSCSI and Fibre Channel SAN storage — single-path storage is a single point of failure
- **MUST** configure NFS mounts with `hard` option for database and filesystem workloads — `soft` mounts can cause data corruption if the server temporarily goes unreachable
- **MUST** test PXE boot with a non-production host before any mass deployment — PXE issues can lock out entire server fleets
- **MUST** document datacenter rack position, U slot, cable IDs, and BMC IP for every server in an asset inventory — physical operations require this information
- **MUST** use `set -euo pipefail` in all shell scripts that interact with hardware — unexpected failures can cause data loss or hardware damage
- **MUST** maintain NTP synchronization across all on-prem systems — distributed systems with unsynchronized clocks produce unreliable logs, metrics, and transaction ordering
- **MUST** review SEL (System Event Log) before any hardware replacement — the SEL often reveals the root cause of the failure
### MUST NOT DO
- **MUST NOT** power cycle a server without first attempting a graceful OS-level shutdown via SSH or BMC SOL — abrupt power loss can corrupt filesystems and databases
- **MUST NOT** replace a disk in a RAID array without verifying backup integrity first — if the array fails during rebuild, you lose everything
- **MUST NOT** expose iSCSI or NFS to untrusted networks without authentication (CHAP for iSCSI, IP-based access controls for NFS)
- **MUST NOT** disable multipath failover or set `no_path_retry` to `off` — this creates immediate I/O failure on any path interruption
- **MUST NOT** rely on BMC-only management — always maintain console access (serial/IPMI SOL) as a fallback when IPMI LAN is unavailable
- **MUST NOT** configure PXE boot without validating DHCP, TFTP, and HTTP services first — a broken PXE infrastructure can prevent all servers from booting
- **MUST NOT** ignore thermal warnings before hardware maintenance — high temperatures indicate cooling failures that could worsen during component replacement
---
## Related Skills
| Skill | Purpose |
|-------|---------|
| `hardware-provisioning` | Initial hardware sizing, RAID configuration, and SSD optimization for the provisioned servers |
| `networking` | Bond interfaces, VLANs, and firewall rules that complement on-prem network storage and PXE infrastructure |
| `kernel-tuning` | Tune I/O scheduler, TCP, and filesystem parameters for multipath and NFS performance |
| `linux-security` | Harden the server post-provisioning: SSH hardening, file permissions, and audit logging |
> 📖 skill(local cache): on-prem-infrastructure
Scanned 6/12/2026
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!