Skip to content

itiligent/RSYNC-ESXi

Repository files navigation

RSYNC for VMware ESXi

Build and use rsync on VMware ESXi hosts

Rsync is a lightweight, proven tool for reliable file replication, migration, and backup. It is also a Linux staple.

Unfortunately, VMware never offered rsync in ESXi, perhaps in favour of commercial backup solutions. This project reinstates that fundamental Linux functionality with a clean and ESXi-compatible static rsync build.


🔨 Build Instructions

💡 If you don’t want to build your own, you can download a prebuilt binary here:

➡️ Latest version: rsync v3.4.1 for ESXi

➡️ For older ESXi6: rsync v3.2.7 for ESXi

Prerequisites

Any RedHat flavored OS that offers ALL the following packages: curl python3-pip automake perl gcc glibc-static.

As of Sept '25 the list of RedHat derived OS with these packages includes:

Alama Linux 8,9,10
Amazon Linux 2 & 2023
Centos 9
Centos 10
Fedora 41 & 42
OpenSuse 15.6 & Tumbleweed
Oracle Linux 8,9,10
Rocky Linux 8,9,10

Building the portable (static) rsync binary

  1. On a fresh supported system, run the build script (not as sudo or root):

    ./rsync-esxi-builder-multiOS.sh
  2. When the script completes, copy the compiled rsync binary from $HOME/build-static/rsync/bin to all ESXi hosts (note the install path of each - you will need this later).

  3. On each ESXi host, set execute permissions on the binary:

    chmod 755 /path/to/rsync
  4. ESXi 8 and above only – allow execution of non-native binaries:

    esxcli system settings advanced set -o /User/execInstalledOnly -i 0
  5. Configure RSA SSH keys for passwordless host-to-host authentication. (VMware does not currently support Ed25519 keys for Esxi host to host sessions.)

  6. See below usage Examples for host-to-host and datastore-to-datastore rsync replication.


🚀 Usage Examples

Local datastore to datastore rsync syntax:

rsync -rltDv --progress --sparse --partial --append-verify /vmfs/source_path/* /vmfs/destination_path

Fully configurable ESXi to ESXi replication script:

# =============================================================================================================
#!/bin/sh
# ESXi host to host network backup with rsync
# Run this script on the SOURCE ESXi host
# =============================================================================================================

# Paths & hosts
SOURCE_DIR="/vmfs/volumes/Host1SourceDatastore/"              # Source location SOURCE esxi host
DEST_DIR="/vmfs/volumes/Host2DestDatastore/"                  # Destination location on DEST host
ESXI_DEST_HOST="[email protected]"                            # Destination Esxi host
PRIVKEY="/vmfs/volumes/Host1SourceDatastore/privkey"          # SSH private sshkey stored on SOURCE to access DEST ESXi host
SOURCE_RSYNC_BIN="/vmfs/volumes/Host1SourceDatastore/rsync"   # SORCE rsync binary location
DEST_RSYNC_BIN="/vmfs/volumes/Host2DestDatastore/rsync"       # DEST rsync binary location				
EXCLUDE_FILE="/vmfs/volumes/Datastore1/rsync_excludes.txt"    # Optional filter, one entry per line
LOG_DIR="/vmfs/volumes/Datastore1/rsync_logs"                 # SOURCE host log location
LOG_FILE="${LOG_DIR}/rsync_$(date '+%Y%m%d_%H%M%S').log"	     # Log file name and format 

# Preliminary checks
[ -x "$SOURCE_RSYNC_BIN" ] || { echo && echo "Source rsync not found: $SOURCE_RSYNC_BIN" && echo; exit 1; }
[ -f "$PRIVKEY" ] || { echo && echo "SSH private key not found: $PRIVKEY" && echo; exit 1; }
[ -f "$EXCLUDE_FILE" ] && RSYNC_EXCLUDES="--exclude-from=${EXCLUDE_FILE}" && echo && echo "Using exclude file: ${EXCLUDE_FILE}" | tee -a "$LOG_FILE"
mkdir -p "${LOG_DIR}" || { echo && echo "Failed to create log directory ${LOG_DIR}" && echo; exit 1; }

# Ensure remote directory exists
ssh -i "${PRIVKEY}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
    "${ESXI_DEST_HOST}" "mkdir -p \"${DEST_DIR}\"" || {
    echo "Failed to create destination directory on remote host" | tee -a "${LOG_FILE}"
    exit 1
}

# Cleanup any lingering rsync processes on error or interrupt (local + remote) ---
cleanup() {
    echo "Cleaning up rsync processes (local + remote)..." | tee -a "$LOG_FILE"

    # Kill local rsync
    for pid in $(ps | grep '[r]sync' | awk '{print $1}'); do
	echo "Killing local rsync PID $pid" | tee -a "$LOG_FILE"
        kill -9 "$pid" 2>/dev/null
    done

    # Kill remote rsync
    ssh -i "$PRIVKEY" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR "$ESXI_DEST_HOST" "
        for pid in \$(ps | grep '[r]sync' | awk '{print \$1}'); do
            echo \"Killing remote rsync PID \$pid\"
            kill -9 \"\$pid\" 2>/dev/null
        done
    "
	echo
    exit 1
}
trap cleanup INT TERM

# Perform the rsync copy operation
echo
echo "Starting rsync copy from ${SOURCE_DIR} to ${ESXI_DEST_HOST}:${DEST_DIR} on $(date)" | tee -a "${LOG_FILE}"
echo
{
    "${SOURCE_RSYNC_BIN}" -rltDv --progress --sparse --partial --append-verify \
        ${RSYNC_EXCLUDES} \
        -e "ssh -i \"${PRIVKEY}\" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR" \
        --rsync-path="${DEST_RSYNC_BIN}" \
        "${SOURCE_DIR}" "${ESXI_DEST_HOST}:${DEST_DIR}"
    echo $? > /tmp/rsync_exit.$$
} 2>&1 | tee -a "${LOG_FILE}"

RSYNC_EXIT=$?
cleanup

if [ "$RSYNC_EXIT" -ne 0 ]; then
    cleanup    
    echo
    echo "Rsync failed with exit code $RSYNC_EXIT" | tee -a "${LOG_FILE}"
    echo
    exit "$RSYNC_EXIT"
fi

cleanup
echo
echo "Rsync copy completed successfully at $(date)" | tee -a "${LOG_FILE}"
echo
exit 0

About

ESXi rsync binary (build script or download)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages