Deploying Static Websites Using Legacy Methods: A Practical Guide with Script Example

In the fast-paced world of CI/CD, automated pipelines have become the go-to solution for deploying applications. Yet, there are scenarios where deploying via traditional methods like FTP, SFTP, or rsync makes more sense — especially for simple static websites or projects hosted on shared servers. In this blog post, we’ll explore why legacy deployment methods are still relevant and share a fully functional bash script to streamline the process.

Why Use Legacy Deployment Methods?

While modern CI/CD pipelines provide robust automation for complex applications, they might be overkill for small-scale projects. Here’s why:

  • Simplicity: Static websites or HTML projects often don’t need the sophistication of CI/CD.
  • Infrastructure Constraints: Shared hosting environments or legacy servers often lack support for modern CI/CD tools.
  • Cost Efficiency: Setting up and maintaining CI/CD pipelines can be resource-intensive for personal or small-scale projects.
  • Rapid Prototyping: Legacy methods allow for quick deployment without complex configurations.

For these reasons, methods like FTP and rsync remain practical when paired with a bit of automation.

Bash Script for Deploying Websites via FTP or rsync

Below is a robust bash script designed to automate the deployment process using legacy methods. It simplifies tasks like building your project, securely transferring files, and handling multiple connection options.

The Deployment Script

#!/bin/bash

# Colors for messages
COLOR_RESET="\033[0m"
COLOR_INFO="\033[32m"
COLOR_WARN="\033[33m"
COLOR_ERROR="\033[31m"

# Function: Print a message
print_message() {
    local color=$1
    local message=$2
    echo -e "${color}${message}${COLOR_RESET}"
}

# Function: Instructions for Using TLS
show_tls_instructions() {
    print_message "$COLOR_INFO" "Before using TLS:"
    echo "1. Ensure the FTP server has a valid SSL/TLS certificate."
    echo "   - If the server uses a self-signed certificate, download and trust it."
    echo "   - Command to download the certificate:"
    echo "     openssl s_client -connect <FTP_HOST>:21 -starttls ftp </dev/null 2>/dev/null | openssl x509 -outform PEM > server-cert.pem"
    echo "   - Move the certificate to /etc/ssl/certs/ (or another trusted directory)."
    echo ""
}

# Function: Build the project
build_project() {
    print_message "$COLOR_INFO" "Building the project..."
    npm run build
    if [ $? -ne 0 ]; then
        print_message "$COLOR_ERROR" "Build failed. Aborting deployment."
        exit 1
    fi
}

# Function: Deploy via FTP
deploy_via_ftp() {
    read -p "Enter FTP username: " FTP_USER
    read -p "Enter FTP host: " FTP_HOST
    read -p "Enter remote directory: " FTP_DIR
    read -s -p "Enter FTP password: " FTP_PASS
    echo  # New line after password input

    print_message "$COLOR_INFO" "Select FTP Connection Option:"
    echo "1. Plain FTP (Insecure)"
    echo "2. FTP with Explicit TLS"
    echo "3. FTP with Implicit TLS"
    read -p "Choose an option (1-3): " FTP_OPTION

    build_project

    case $FTP_OPTION in
        1)
            print_message "$COLOR_INFO" "Deploying via Plain FTP..."
            lftp -u "$FTP_USER","$FTP_PASS" ftp://"$FTP_HOST" <<EOF
mirror -R dist "$FTP_DIR"
bye
EOF
            ;;
        2)
            print_message "$COLOR_INFO" "Deploying via FTP with Explicit TLS..."
            lftp -u "$FTP_USER","$FTP_PASS" ftps://"$FTP_HOST" <<EOF
set ftp:ssl-allow yes
set ftp:ssl-force yes
set ssl:verify-certificate no
mirror -R dist "$FTP_DIR"
bye
EOF
            ;;
        3)
            print_message "$COLOR_INFO" "Deploying via FTP with Implicit TLS..."
            lftp -u "$FTP_USER","$FTP_PASS" ftps://"$FTP_HOST" <<EOF
set ftp:ssl-allow yes
set ftp:ssl-force yes
set ftp:ssl-protect-data yes
set ftp:ssl-protect-list yes
set ssl:verify-certificate no
mirror -R dist "$FTP_DIR"
bye
EOF
            ;;
        *)
            print_message "$COLOR_ERROR" "Invalid option selected."
            exit 1
            ;;
    esac

    if [ $? -ne 0 ]; then
        print_message "$COLOR_ERROR" "FTP deployment failed."
        exit 1
    fi

    print_message "$COLOR_INFO" "FTP Deployment completed successfully!"
}

# Function: Deploy via rsync
deploy_via_rsync() {
    read -p "Enter remote username: " REMOTE_USER
    read -p "Enter remote host: " REMOTE_HOST
    read -p "Enter remote directory: " REMOTE_DIR
    read -p "Enter private key path (default: ~/.ssh/id_rsa): " PRIVATE_KEY
    PRIVATE_KEY=${PRIVATE_KEY:-~/.ssh/id_rsa}

    build_project

    print_message "$COLOR_INFO" "Deploying via rsync using SSH private key..."
    rsync -avz --delete -e "ssh -i $PRIVATE_KEY -o StrictHostKeyChecking=no" dist/ "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR"

    if [ $? -ne 0 ]; then
        print_message "$COLOR_ERROR" "rsync deployment failed."
        exit 1
    fi

    print_message "$COLOR_INFO" "rsync Deployment completed successfully!"
}

# Main Program
print_message "$COLOR_INFO" "Starting Deployment Script..."
echo "-----------------------------------"

show_tls_instructions

print_message "$COLOR_INFO" "Deployment Options:"
echo "1. Deploy via FTP"
echo "2. Deploy via rsync"
read -p "Select a method (1 or 2): " METHOD

if [[ $METHOD == 1 ]]; then
    deploy_via_ftp
elif [[ $METHOD == 2 ]]; then
    deploy_via_rsync
else
    print_message "$COLOR_ERROR" "Invalid deployment method."
    exit 1
fi

How the Script Works

  1. Build Your Project: The script runs npm run build to compile your static website.
  2. Choose Your Deployment Method:
  • FTP: Options include plain FTP (not recommended), FTP with Explicit TLS, or Implicit TLS.
  • rsync: Supports deployment via SSH using private keys.
  1. Automated Transfers: The script synchronizes the local build directory (dist/) with the remote server’s directory.
  2. Security Options: Includes TLS for FTP and SSH for rsync to ensure secure data transfers.

Use Cases for This Script

  • Static Websites: Deploy lightweight HTML/CSS/JS projects quickly.
  • Shared Hosting: Automate deployments on servers with limited access.
  • Small-Scale Projects: Save time without setting up full-fledged CI/CD pipelines.

Conclusion

Legacy deployment methods like FTP and rsync remain practical for specific scenarios. This script combines the simplicity of these methods with the power of automation, ensuring secure and efficient deployments for small projects. Whether you’re a solo developer or managing lightweight websites, this approach helps you deploy faster without compromising reliability or security.