85°F Knoxville
Mon–Fri 9–5 ETAnswered by a human
Automation · IMPLEMENTED

Automating CrushFTP Upgrades and In-Place Updates

Shell scripts for major version upgrades and minor updates. Transform a complex manual process into a single, reliable command.

Summary

To streamline server maintenance, we built two bash scripts for CrushFTP management. The first automates in-place updates through the built-in API, ensuring servers stay patched with minimal downtime. The second handles major version upgrades (v10 to v11), migrating all critical settings, user data, SSH keys, jobs, and custom branding — turning a complex manual process into a single reliable command.

The challenge

Manually updating and upgrading CrushFTP servers is repetitive and error-prone. In-place updates mean logging into the admin console, clicking through prompts, waiting, verifying. Major version upgrades are worse: you're copying a dozen folders and config files by hand, uninstalling the old daemon, installing the new one, and hoping nothing got missed. Done across multiple environments, this is exactly the kind of task where one tired copy-paste turns into a 2 AM support ticket.

The ask was simple: make both operations automated, consistent, and safe enough to run on a cron schedule.

Solution: automation scripts

Two distinct bash scripts — one for minor in-place updates, one for the v10 to v11 major version migration. Different goals, different designs.

Script 1: automated in-place updates

This one leverages the CrushFTP HTTPS API to check for and apply pending updates. Designed to run as a cron job so servers stay current with security patches and bug fixes automatically. Every action writes to /var/log/crushftp_update.log for later auditing.

It hits /?command=checkForUpdate, parses the XML response, and only fires /?command=updateNow if an update is actually available — no unnecessary restarts, no noise when there's nothing to do.

crushftp_update.sh
#!/bin/bash

LOG_FILE="/var/log/crushftp_update.log"
CHECK_UPDATE_URL="https://127.0.0.1:443/?command=checkForUpdate"
UPDATE_URL="https://127.0.0.1:443/?command=updateNow"
USERNAME="crushadmin"
PASSWORD="YOUR_SECRET_PASSWORD" # Use vault in production

{
echo "Starting CrushFTP update check..."
echo "Date/Time: $(date)"

RESPONSE=$(curl -k -s -u $USERNAME:$PASSWORD "$CHECK_UPDATE_URL")
RESULT=$(echo "$RESPONSE" | grep -oPm1 "(?<=<response>)[^<]+")

if [ "$RESULT" == "true" ]; then
    echo "Update available! Updating..."
    UPDATE_RESPONSE=$(curl -k -s -u $USERNAME:$PASSWORD "$UPDATE_URL")
    UPDATE_RESULT=$(echo "$UPDATE_RESPONSE" | grep -oPm1 "(?<=<response>)[^<]+")

    if [ "$UPDATE_RESULT" == "Success" ]; then
        echo "Update successfully completed!"
    else
        echo "Update process failed!"
    fi
else
    echo "No updates available."
fi

echo "CrushFTP update check completed."
} 2>&1 | tee -a "$LOG_FILE"

Script 2: major version upgrade (V10 to v11)

The major upgrade is where manual work really bites. CrushFTP's data is scattered across a lot of folders — users, prefs.XML, SSH host keys, TempAccounts, Previews, logs, jobs (enterprise only), statsDB — and if you miss any of them, the new install comes up wrong in ways that aren't always obvious until a user tries to log in.

This script handles the whole thing: downloads the new version, extracts it next to the old install, copies everything that matters, preserves the custom web interface logo, uninstalls the old daemon, installs the new one.

crushftp_v10_to_v11_upgrade.sh
#!/bin/bash

# Define the old and new CrushFTP installation paths
OLD_CRUSH_PATH="/var/opt/CrushFTP10"
NEW_CRUSH_PATH="/var/opt/CrushFTP11"

# Download the CrushFTP 11 package
echo "Downloading CrushFTP 11..."
wget https://www.crushftp.com/early11/CrushFTP11.zip -O "$NEW_CRUSH_PATH.zip"

# Unzip the package
echo "Unzipping CrushFTP 11 package..."
unzip "$NEW_CRUSH_PATH.zip" -d /var/opt

# Make the initialization script executable
echo "Making initialization script executable..."
chmod +x "$NEW_CRUSH_PATH/crushftp_init.sh"

# Copy over the necessary files and folders
echo "Copying users, prefs, keys, and other critical files..."
cp -R "$OLD_CRUSH_PATH/users" "$NEW_CRUSH_PATH/"
cp "$OLD_CRUSH_PATH/prefs.XML" "$NEW_CRUSH_PATH/"
cp "$OLD_CRUSH_PATH/ssh_host_dsa_key" "$NEW_CRUSH_PATH/"
cp "$OLD_CRUSH_PATH/ssh_host_rsa_key" "$NEW_CRUSH_PATH/"
cp "$OLD_CRUSH_PATH/ssh_host_dsa_key.pub" "$NEW_CRUSH_PATH/"
cp "$OLD_CRUSH_PATH/ssh_host_rsa_key.pub" "$NEW_CRUSH_PATH/"
cp -R "$OLD_CRUSH_PATH/TempAccounts" "$NEW_CRUSH_PATH/"
cp -R "$OLD_CRUSH_PATH/Previews" "$NEW_CRUSH_PATH/"
cp -R "$OLD_CRUSH_PATH/logs" "$NEW_CRUSH_PATH/"
cp -R "$OLD_CRUSH_PATH/jobs" "$NEW_CRUSH_PATH/"
cp -R "$OLD_CRUSH_PATH/statsDB" "$NEW_CRUSH_PATH/"

# Copy custom logo
cp "$OLD_CRUSH_PATH/WebInterface/images/logo.png" "$NEW_CRUSH_PATH/WebInterface/images/"

# Remove old version daemon launch references
echo "Removing old version daemon launch references..."
cd "$NEW_CRUSH_PATH"
./crushftp_init.sh uninstall

# Install new version daemon launch references
echo "Installing new version daemon launch references..."
./crushftp_init.sh install

echo "CrushFTP 11 upgrade complete. Verify services are running."

Security considerations

The in-place update script needs an admin username and password to talk to the API. We've sanitized the version shown here for public view — in production, never hardcode credentials directly.

  • use a secret store (HashiCorp Vault, AWS Secrets Manager, or environment variables injected at runtime) to supply the password
  • lock down script permissions with chmod 700 so only the owner can read or execute
  • license registration for the major upgrade is still a manual step after the script completes — that's intentional

Outcome

These scripts cut the time and effort to maintain CrushFTP infrastructure way down. What used to be a multi-step manual process is now a single reliable command that can be scheduled without worry.

  • drastically reduced manual effort for updates and upgrades
  • consistent application of updates across all environments
  • minimizes risk of human error during migrations (the copy step is where people always miss something)
  • cron-job compatibility means "set-and-forget" security patching