Skip to content

Instantly share code, notes, and snippets.

@itxtoledo
Last active September 26, 2025 23:35
Show Gist options
  • Save itxtoledo/27ca1e73e08c9ee4433a54480d4f57d3 to your computer and use it in GitHub Desktop.
Save itxtoledo/27ca1e73e08c9ee4433a54480d4f57d3 to your computer and use it in GitHub Desktop.

Revisions

  1. itxtoledo revised this gist Jun 10, 2025. 1 changed file with 0 additions and 22 deletions.
    22 changes: 0 additions & 22 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -17,28 +17,6 @@ log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
    }

    # Function to keep SSH connection alive during long operations
    keep_alive() {
    local message="$1"
    local duration=${2:-300} # Default 5 minutes
    local interval=30
    local count=0
    local max_count=$((duration / interval))

    log "$message - This operation may take up to $((duration/60)) minutes..."

    while [ $count -lt $max_count ]; do
    sleep $interval
    count=$((count + 1))
    echo "Progress: $((count * interval))s / ${duration}s - Keeping connection alive..."

    # Check if background process is still running
    if ! jobs %1 &>/dev/null 2>&1; then
    break
    fi
    done
    }

    # Function to check if a command exists
    check_command() {
    if ! command -v "$1" &> /dev/null; then
  2. itxtoledo revised this gist Jun 10, 2025. 1 changed file with 24 additions and 63 deletions.
    87 changes: 24 additions & 63 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -25,12 +25,12 @@ keep_alive() {
    local count=0
    local max_count=$((duration / interval))

    log "$message - Esta operação pode demorar até $((duration/60)) minutos..."
    log "$message - This operation may take up to $((duration/60)) minutes..."

    while [ $count -lt $max_count ]; do
    sleep $interval
    count=$((count + 1))
    echo "Progresso: $((count * interval))s / ${duration}s - Mantendo conexão ativa..."
    echo "Progress: $((count * interval))s / ${duration}s - Keeping connection alive..."

    # Check if background process is still running
    if ! jobs %1 &>/dev/null 2>&1; then
    @@ -49,12 +49,10 @@ check_command() {

    # Function to detect package manager
    get_package_manager() {
    if command -v dnf &> /dev/null; then
    echo "dnf"
    elif command -v yum &> /dev/null; then
    if command -v yum &> /dev/null; then
    echo "yum"
    else
    log "Error: No supported package manager (dnf/yum) found."
    log "Error: yum package manager not found."
    exit 1
    fi
    }
    @@ -107,9 +105,6 @@ setup_swapfile() {

    # Function to install Docker with optimizations for low-resource servers
    install_docker() {
    local pkg_manager
    pkg_manager=$(get_package_manager)

    # Check if Docker is already installed
    if command -v docker &> /dev/null; then
    log "Docker is already installed. Checking if it's running..."
    @@ -125,64 +120,30 @@ install_docker() {
    fi
    fi

    log "Installing Docker with CPU-friendly settings..."
    log "Installing Docker with CPU-friendly settings using yum..."

    # Set CPU-friendly nice priority for package manager
    # Set environment for non-interactive installation
    export DEBIAN_FRONTEND=noninteractive

    if [[ "$pkg_manager" == "dnf" ]]; then
    log "Installing dnf-plugins-core (this may take a few minutes)..."
    nice -n 10 dnf install -y dnf-plugins-core --setopt=max_parallel_downloads=2 >> "$LOG_FILE" 2>&1 || {
    log "Error installing dnf-plugins-core."
    exit 1
    }

    log "Adding Docker repository..."
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "Error adding Docker repository."
    exit 1
    }

    log "Installing Docker CE (this may take several minutes, please be patient)..."
    echo "Note: The installation process is running with reduced CPU priority to prevent connection timeouts."

    # Use nice to reduce CPU priority and limit parallel downloads
    nice -n 10 dnf install -y docker-ce --setopt=max_parallel_downloads=1 --setopt=throttle=50k >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    log "Retrying with even more conservative settings..."
    sleep 5
    nice -n 15 dnf install -y docker-ce --setopt=max_parallel_downloads=1 --setopt=throttle=25k >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker after retry."
    exit 1
    }
    }
    else
    log "Installing yum-utils (this may take a few minutes)..."
    nice -n 10 yum install -y yum-utils >> "$LOG_FILE" 2>&1 || {
    log "Error installing yum-utils."
    exit 1
    }

    log "Adding Docker repository..."
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "Error adding Docker repository."
    log "Adding Docker repository..."
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "Error adding Docker repository."
    exit 1
    }

    log "Installing Docker CE (this may take several minutes, please be patient)..."
    echo "Note: The installation process is running with reduced CPU priority to prevent connection timeouts."

    # Use nice to reduce CPU priority
    nice -n 10 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    log "Retrying with more conservative settings..."
    sleep 5
    nice -n 15 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker after retry."
    exit 1
    }

    log "Installing Docker CE (this may take several minutes, please be patient)..."
    echo "Note: The installation process is running with reduced CPU priority to prevent connection timeouts."

    # Use nice to reduce CPU priority
    nice -n 10 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    log "Retrying with even more conservative settings..."
    sleep 5
    nice -n 15 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker after retry."
    exit 1
    }
    }
    fi
    }

    log "Starting and enabling Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "Error starting Docker."; exit 1; }
    @@ -423,7 +384,7 @@ main() {
    echo "This script will:"
    echo "1. Set up a 4GB swapfile"
    echo "2. Install Docker"
    echo "3. Configure iptable_nat module"
    echo "3. Configure iptables modules"
    echo "4. Run the wg-easy container"
    answer=$(read_from_terminal "Proceed with installation? (y/n): " "")
    case $answer in
  3. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 101 additions and 13 deletions.
    114 changes: 101 additions & 13 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -17,6 +17,28 @@ log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
    }

    # Function to keep SSH connection alive during long operations
    keep_alive() {
    local message="$1"
    local duration=${2:-300} # Default 5 minutes
    local interval=30
    local count=0
    local max_count=$((duration / interval))

    log "$message - Esta operação pode demorar até $((duration/60)) minutos..."

    while [ $count -lt $max_count ]; do
    sleep $interval
    count=$((count + 1))
    echo "Progresso: $((count * interval))s / ${duration}s - Mantendo conexão ativa..."

    # Check if background process is still running
    if ! jobs %1 &>/dev/null 2>&1; then
    break
    fi
    done
    }

    # Function to check if a command exists
    check_command() {
    if ! command -v "$1" &> /dev/null; then
    @@ -37,7 +59,7 @@ get_package_manager() {
    fi
    }

    # Function to set up the swapfile
    # Function to set up the swapfile with optimizations
    setup_swapfile() {
    local swap_size="4G"
    local swap_file="/swapfile"
    @@ -56,14 +78,19 @@ setup_swapfile() {
    fi
    fi

    # Create and configure swapfile
    # Create and configure swapfile with progress indication
    log "Creating swapfile - this may take a few minutes for better performance..."
    if ! fallocate -l "$swap_size" "$swap_file" 2>> "$LOG_FILE"; then
    log "Warning: fallocate failed. Trying dd instead..."
    if ! dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" 2>> "$LOG_FILE"; then
    log "Warning: fallocate failed. Using dd with progress indication..."
    echo "Creating swapfile with dd (this will take several minutes)..."

    # Use dd with progress and reduced I/O priority
    if ! nice -n 10 ionice -c 3 dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" status=progress 2>> "$LOG_FILE"; then
    log "Error creating swapfile with dd."
    exit 1
    fi
    fi

    chmod 600 "$swap_file" 2>> "$LOG_FILE" || { log "Error setting swapfile permissions."; exit 1; }
    mkswap "$swap_file" >> "$LOG_FILE" 2>&1 || { log "Error formatting swapfile."; exit 1; }
    swapon "$swap_file" >> "$LOG_FILE" 2>&1 || { log "Error activating swapfile."; exit 1; }
    @@ -78,44 +105,105 @@ setup_swapfile() {
    log "Swapfile configured successfully!"
    }

    # Function to install Docker
    # Function to install Docker with optimizations for low-resource servers
    install_docker() {
    local pkg_manager
    pkg_manager=$(get_package_manager)

    log "Installing Docker..."
    # Check if Docker is already installed
    if command -v docker &> /dev/null; then
    log "Docker is already installed. Checking if it's running..."
    if systemctl is-active --quiet docker; then
    log "Docker is already installed and running. Skipping installation."
    return 0
    else
    log "Docker is installed but not running. Starting Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "Error starting Docker."; exit 1; }
    systemctl enable docker >> "$LOG_FILE" 2>&1 || { log "Error enabling Docker."; exit 1; }
    log "Docker started successfully!"
    return 0
    fi
    fi

    log "Installing Docker with CPU-friendly settings..."

    # Set CPU-friendly nice priority for package manager
    export DEBIAN_FRONTEND=noninteractive

    if [[ "$pkg_manager" == "dnf" ]]; then
    dnf install -y dnf-plugins-core >> "$LOG_FILE" 2>&1 || {
    log "Installing dnf-plugins-core (this may take a few minutes)..."
    nice -n 10 dnf install -y dnf-plugins-core --setopt=max_parallel_downloads=2 >> "$LOG_FILE" 2>&1 || {
    log "Error installing dnf-plugins-core."
    exit 1
    }

    log "Adding Docker repository..."
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "Error adding Docker repository."
    exit 1
    }
    dnf install -y docker-ce >> "$LOG_FILE" 2>&1 || {

    log "Installing Docker CE (this may take several minutes, please be patient)..."
    echo "Note: The installation process is running with reduced CPU priority to prevent connection timeouts."

    # Use nice to reduce CPU priority and limit parallel downloads
    nice -n 10 dnf install -y docker-ce --setopt=max_parallel_downloads=1 --setopt=throttle=50k >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    exit 1
    log "Retrying with even more conservative settings..."
    sleep 5
    nice -n 15 dnf install -y docker-ce --setopt=max_parallel_downloads=1 --setopt=throttle=25k >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker after retry."
    exit 1
    }
    }
    else
    yum install -y yum-utils >> "$LOG_FILE" 2>&1 || {
    log "Installing yum-utils (this may take a few minutes)..."
    nice -n 10 yum install -y yum-utils >> "$LOG_FILE" 2>&1 || {
    log "Error installing yum-utils."
    exit 1
    }

    log "Adding Docker repository..."
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "Error adding Docker repository."
    exit 1
    }
    yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {

    log "Installing Docker CE (this may take several minutes, please be patient)..."
    echo "Note: The installation process is running with reduced CPU priority to prevent connection timeouts."

    # Use nice to reduce CPU priority
    nice -n 10 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    exit 1
    log "Retrying with even more conservative settings..."
    sleep 5
    nice -n 15 yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker after retry."
    exit 1
    }
    }
    fi

    log "Starting and enabling Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "Error starting Docker."; exit 1; }
    systemctl enable docker >> "$LOG_FILE" 2>&1 || { log "Error enabling Docker."; exit 1; }
    log "Docker installed and configured successfully!"

    # Wait a moment for Docker to fully initialize
    sleep 3

    # Verify Docker is working
    if docker --version >> "$LOG_FILE" 2>&1; then
    log "Docker installed and configured successfully!"
    else
    log "Warning: Docker installed but may not be fully ready. Waiting a bit longer..."
    sleep 5
    if docker --version >> "$LOG_FILE" 2>&1; then
    log "Docker is now working correctly!"
    else
    log "Error: Docker installation may have issues. Check manually with 'docker --version'"
    exit 1
    fi
    fi
    }

    # Function to set up the iptable_nat module - ENHANCED
  4. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 18 additions and 4 deletions.
    22 changes: 18 additions & 4 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -118,10 +118,24 @@ install_docker() {
    log "Docker installed and configured successfully!"
    }

    # Function to set up the iptable_nat module - FIXED
    # Function to set up the iptable_nat module - ENHANCED
    setup_iptables() {
    log "Configuring iptables/NAT functionality..."

    # First, explicitly load the critical modules
    log "Loading essential iptables modules..."
    if modprobe iptable_nat 2>>"$LOG_FILE"; then
    log "Successfully loaded iptable_nat module."
    else
    log "Warning: Could not load iptable_nat module (may be built-in)."
    fi

    if modprobe ip_tables 2>>"$LOG_FILE"; then
    log "Successfully loaded ip_tables module."
    else
    log "Warning: Could not load ip_tables module (may be built-in)."
    fi

    # On modern systems, modules are often built-in or loaded automatically
    # when needed. First, check if iptables works (most important test)

    @@ -131,10 +145,10 @@ setup_iptables() {
    return 0
    fi

    log "iptables NAT not accessible, attempting to load modules..."
    log "iptables NAT not accessible, attempting to load additional modules..."

    # List of modules that might be needed
    modules=("iptable_nat" "nf_nat" "ip_tables" "nf_conntrack" "iptable_filter")
    # List of additional modules that might be needed
    modules=("nf_nat" "nf_conntrack" "iptable_filter")

    for module in "${modules[@]}"; do
    log "Trying to load module: $module"
  5. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 18 additions and 2 deletions.
    20 changes: 18 additions & 2 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -233,11 +233,27 @@ run_wg_easy() {

    password=$(read_from_terminal "Enter password for wg-easy [default: admin123]: " "admin123")
    log "Generating password hash..."
    password_hash=$(docker run --rm ghcr.io/wg-easy/wg-easy:14 wgpw "$password" 2>> "$LOG_FILE") || {
    password_hash_output=$(docker run ghcr.io/wg-easy/wg-easy:14 wgpw "$password" 2>> "$LOG_FILE") || {
    log "Error generating password hash."
    exit 1
    }
    log "Password hash generated successfully."

    # Extract just the hash from the output (removes PASSWORD_HASH=' and trailing ')
    password_hash=$(echo "$password_hash_output" | sed "s/PASSWORD_HASH='\(.*\)'/\1/")

    # Fallback: if sed didn't work, try alternative extraction methods
    if [[ -z "$password_hash" ]] || [[ "$password_hash" == "$password_hash_output" ]]; then
    # Try extracting everything between single quotes
    password_hash=$(echo "$password_hash_output" | grep -o "'[^']*'" | sed "s/'//g")
    fi

    # Final validation
    if [[ -z "$password_hash" ]] || [[ "$password_hash" == PASSWORD_HASH* ]]; then
    log "Error: Could not extract password hash from output: $password_hash_output"
    exit 1
    fi

    log "Password hash generated and extracted successfully."

    panel_port=$(read_from_terminal "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " "80")
    if ! validate_port "$panel_port"; then
  6. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 53 additions and 10 deletions.
    63 changes: 53 additions & 10 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -118,19 +118,62 @@ install_docker() {
    log "Docker installed and configured successfully!"
    }

    # Function to set up the iptable_nat module
    # Function to set up the iptable_nat module - FIXED
    setup_iptables() {
    log "Loading iptable_nat module..."
    if ! modprobe iptable_nat >> "$LOG_FILE" 2>&1; then
    log "Error loading iptable_nat module."
    exit 1
    log "Configuring iptables/NAT functionality..."

    # On modern systems, modules are often built-in or loaded automatically
    # when needed. First, check if iptables works (most important test)

    if iptables -t nat -L >/dev/null 2>&1; then
    log "iptables NAT functionality is working correctly."
    log "Modules are either built-in or loaded automatically."
    return 0
    fi
    if lsmod | grep -q iptable_nat; then
    log "iptable_nat module loaded successfully!"
    else
    log "Error: iptable_nat module not loaded."
    exit 1

    log "iptables NAT not accessible, attempting to load modules..."

    # List of modules that might be needed
    modules=("iptable_nat" "nf_nat" "ip_tables" "nf_conntrack" "iptable_filter")

    for module in "${modules[@]}"; do
    log "Trying to load module: $module"
    if modprobe "$module" 2>/dev/null; then
    log "Successfully loaded module: $module"
    else
    log "Module $module not loaded (may be built-in or not needed)"
    fi
    done

    # Wait a moment and test again
    sleep 2

    # Final test: check if iptables works now
    if iptables -t nat -L >/dev/null 2>&1; then
    log "iptables NAT functionality verified successfully!"
    return 0
    fi

    # If still not working, check if basic iptables is ok
    if iptables -L >/dev/null 2>&1; then
    log "Basic iptables working. NAT may be handled by Docker automatically."
    log "Proceeding with installation..."
    return 0
    fi

    # Last resort: check kernel networking capabilities
    log "Checking kernel networking capabilities..."
    if [[ -f /proc/net/ip_tables_names ]] || [[ -d /proc/sys/net/netfilter ]] || [[ -f /proc/net/nf_conntrack ]]; then
    log "Kernel networking support detected. Proceeding..."
    return 0
    fi

    # If we got here, something might be wrong, but let's try to continue
    log "Warning: Could not fully verify iptables/NAT support."
    log "This may be normal on some systems where Docker handles networking."
    log "Installation will continue - Docker will manage port forwarding."

    return 0
    }

    # Function to validate port
  7. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -93,7 +93,7 @@ install_docker() {
    log "Error adding Docker repository."
    exit 1
    }
    dnf install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    dnf install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    exit 1
    }
    @@ -106,7 +106,7 @@ install_docker() {
    log "Error adding Docker repository."
    exit 1
    }
    yum install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    yum install -y docker-ce >> "$LOG_FILE" 2>&1 || {
    log "Error installing Docker."
    exit 1
    }
  8. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 34 additions and 39 deletions.
    73 changes: 34 additions & 39 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -2,18 +2,13 @@

    # Check if running as root
    if [[ $EUID -ne 0 ]]; then
    echo -e "\033[0;31mError: This script must be run as root. Use sudo.\033[0m"
    echo "Error: This script must be run as root. Use sudo."
    exit 1
    fi

    # Initial settings
    set -euo pipefail

    # Colors for feedback
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    NC='\033[0m'

    # Log file
    LOG_FILE="/var/log/install_wg_easy.log"

    @@ -25,7 +20,7 @@ log() {
    # Function to check if a command exists
    check_command() {
    if ! command -v "$1" &> /dev/null; then
    log "${RED}Error: $1 not found. Please install it first.${NC}"
    log "Error: $1 not found. Please install it first."
    exit 1
    fi
    }
    @@ -37,7 +32,7 @@ get_package_manager() {
    elif command -v yum &> /dev/null; then
    echo "yum"
    else
    log "${RED}Error: No supported package manager (dnf/yum) found.${NC}"
    log "Error: No supported package manager (dnf/yum) found."
    exit 1
    fi
    }
    @@ -53,10 +48,10 @@ setup_swapfile() {
    # Check if swapfile already exists
    if [[ -f "$swap_file" ]]; then
    if swapon --show | grep -q "$swap_file"; then
    log "${GREEN}Swapfile already exists and active at $swap_file.${NC}"
    log "Swapfile already exists and active at $swap_file."
    return
    else
    log "${RED}Swapfile exists at $swap_file but is not active. Please check configuration.${NC}"
    log "Swapfile exists at $swap_file but is not active. Please check configuration."
    exit 1
    fi
    fi
    @@ -65,13 +60,13 @@ setup_swapfile() {
    if ! fallocate -l "$swap_size" "$swap_file" 2>> "$LOG_FILE"; then
    log "Warning: fallocate failed. Trying dd instead..."
    if ! dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" 2>> "$LOG_FILE"; then
    log "${RED}Error creating swapfile with dd.${NC}"
    log "Error creating swapfile with dd."
    exit 1
    fi
    fi
    chmod 600 "$swap_file" 2>> "$LOG_FILE" || { log "${RED}Error setting swapfile permissions.${NC}"; exit 1; }
    mkswap "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error formatting swapfile.${NC}"; exit 1; }
    swapon "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error activating swapfile.${NC}"; exit 1; }
    chmod 600 "$swap_file" 2>> "$LOG_FILE" || { log "Error setting swapfile permissions."; exit 1; }
    mkswap "$swap_file" >> "$LOG_FILE" 2>&1 || { log "Error formatting swapfile."; exit 1; }
    swapon "$swap_file" >> "$LOG_FILE" 2>&1 || { log "Error activating swapfile."; exit 1; }

    # Add to fstab if not already present
    if ! grep -q "$swap_file" /etc/fstab; then
    @@ -80,7 +75,7 @@ setup_swapfile() {
    else
    log "Swapfile already present in /etc/fstab."
    fi
    log "${GREEN}Swapfile configured successfully!${NC}"
    log "Swapfile configured successfully!"
    }

    # Function to install Docker
    @@ -91,49 +86,49 @@ install_docker() {
    log "Installing Docker..."
    if [[ "$pkg_manager" == "dnf" ]]; then
    dnf install -y dnf-plugins-core >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing dnf-plugins-core.${NC}"
    log "Error installing dnf-plugins-core."
    exit 1
    }
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    log "Error adding Docker repository."
    exit 1
    }
    dnf install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    log "Error installing Docker."
    exit 1
    }
    else
    yum install -y yum-utils >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing yum-utils.${NC}"
    log "Error installing yum-utils."
    exit 1
    }
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    log "Error adding Docker repository."
    exit 1
    }
    yum install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    log "Error installing Docker."
    exit 1
    }
    fi

    log "Starting and enabling Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "${RED}Error starting Docker.${NC}"; exit 1; }
    systemctl enable docker >> "$LOG_FILE" 2>&1 || { log "${RED}Error enabling Docker.${NC}"; exit 1; }
    log "${GREEN}Docker installed and configured successfully!${NC}"
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "Error starting Docker."; exit 1; }
    systemctl enable docker >> "$LOG_FILE" 2>&1 || { log "Error enabling Docker."; exit 1; }
    log "Docker installed and configured successfully!"
    }

    # Function to set up the iptable_nat module
    setup_iptables() {
    log "Loading iptable_nat module..."
    if ! modprobe iptable_nat >> "$LOG_FILE" 2>&1; then
    log "${RED}Error loading iptable_nat module.${NC}"
    log "Error loading iptable_nat module."
    exit 1
    fi
    if lsmod | grep -q iptable_nat; then
    log "${GREEN}iptable_nat module loaded successfully!${NC}"
    log "iptable_nat module loaded successfully!"
    else
    log "${RED}Error: iptable_nat module not loaded.${NC}"
    log "Error: iptable_nat module not loaded."
    exit 1
    fi
    }
    @@ -177,7 +172,7 @@ run_wg_easy() {

    # Check if Docker is running
    if ! systemctl is-active --quiet docker; then
    log "${RED}Error: Docker is not running. Please check Docker installation.${NC}"
    log "Error: Docker is not running. Please check Docker installation."
    exit 1
    fi

    @@ -187,7 +182,7 @@ run_wg_easy() {
    log "Warning: Could not fetch public IP automatically."
    wg_host=$(read_from_terminal "Enter public IP or hostname: " "")
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error: No IP or hostname provided.${NC}"
    log "Error: No IP or hostname provided."
    exit 1
    fi
    fi
    @@ -196,14 +191,14 @@ run_wg_easy() {
    password=$(read_from_terminal "Enter password for wg-easy [default: admin123]: " "admin123")
    log "Generating password hash..."
    password_hash=$(docker run --rm ghcr.io/wg-easy/wg-easy:14 wgpw "$password" 2>> "$LOG_FILE") || {
    log "${RED}Error generating password hash.${NC}"
    log "Error generating password hash."
    exit 1
    }
    log "Password hash generated successfully."

    panel_port=$(read_from_terminal "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " "80")
    if ! validate_port "$panel_port"; then
    log "${RED}Error: Invalid port number. Using default port 80.${NC}"
    log "Error: Invalid port number. Using default port 80."
    panel_port=80
    fi
    log "Using panel port: $panel_port"
    @@ -227,18 +222,18 @@ run_wg_easy() {
    --restart unless-stopped \
    -v ~/.wg-easy:/etc/wireguard \
    ghcr.io/wg-easy/wg-easy:14 >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error starting wg-easy container.${NC}"
    log "Error starting wg-easy container."
    exit 1
    }

    # Wait a moment and check if container is running
    sleep 5
    if ! docker ps --format 'table {{.Names}}' | grep -q "^$container_name$"; then
    log "${RED}Error: wg-easy container failed to start. Check logs with: docker logs $container_name${NC}"
    log "Error: wg-easy container failed to start. Check logs with: docker logs $container_name"
    exit 1
    fi

    log "${GREEN}wg-easy container started successfully!${NC}"
    log "wg-easy container started successfully!"

    # Store variables in memory for final output
    export WG_HOST="$wg_host"
    @@ -251,7 +246,7 @@ main() {
    mkdir -p "$(dirname "$LOG_FILE")"

    # Display welcome message
    echo -e "${GREEN}Welcome to the wg-easy Installation Script!${NC}"
    echo "Welcome to the wg-easy Installation Script!"
    echo "This script was created by Gustavo Toledo (@itxtoledo) to simplify setting up wg-easy on Oracle Linux."
    echo "Enjoy a seamless installation experience!"
    echo "Check out more tech content on Gustavo's YouTube channel: https://www.youtube.com/c/itxToledo"
    @@ -273,7 +268,7 @@ main() {
    case $answer in
    [Yy]* ) log "Starting installation...";;
    [Nn]* ) log "Installation canceled."; exit 0;;
    * ) log "${RED}Invalid response.${NC}"; exit 1;;
    * ) log "Invalid response."; exit 1;;
    esac

    # Execute installation steps
    @@ -283,7 +278,7 @@ main() {
    run_wg_easy

    # Display final message
    echo -e "${GREEN}Installation completed successfully!${NC}"
    echo "Installation completed successfully!"
    echo "Access the wg-easy panel at: http://$WG_HOST:$PANEL_PORT"
    echo "----------------------------------------"
    echo "Important:"
    @@ -297,11 +292,11 @@ main() {
    echo "4. Download the WireGuard client from: https://www.wireguard.com/install/"
    echo "5. Check container status with: docker logs wg-easy"
    echo "----------------------------------------"
    log "${GREEN}Installation completed successfully! Access wg-easy at http://$WG_HOST:$PANEL_PORT${NC}"
    log "Installation completed successfully! Access wg-easy at http://$WG_HOST:$PANEL_PORT"
    }

    # Set trap for errors
    trap 'log "${RED}Error on line $LINENO in command: $BASH_COMMAND${NC}"; exit 1' ERR
    trap 'log "Error on line $LINENO in command: $BASH_COMMAND"; exit 1' ERR

    # Run the script
    main
  9. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 5 additions and 6 deletions.
    11 changes: 5 additions & 6 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -154,13 +154,12 @@ read_from_terminal() {
    local default="$2"
    local response

    # Try to read from /dev/tty first (direct terminal access)
    if [ -t 0 ]; then
    # Running interactively
    read -p "$prompt" response
    # Always try to read from /dev/tty for interactive input
    if [[ -r /dev/tty ]]; then
    echo -n "$prompt" >/dev/tty
    read response </dev/tty
    else
    # Running via pipe, redirect input from terminal
    exec < /dev/tty
    # Fallback to regular read if /dev/tty not available
    read -p "$prompt" response
    fi

  10. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 24 additions and 6 deletions.
    30 changes: 24 additions & 6 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -148,6 +148,26 @@ validate_port() {
    fi
    }

    # Function to read input from terminal (works with pipes)
    read_from_terminal() {
    local prompt="$1"
    local default="$2"
    local response

    # Try to read from /dev/tty first (direct terminal access)
    if [ -t 0 ]; then
    # Running interactively
    read -p "$prompt" response
    else
    # Running via pipe, redirect input from terminal
    exec < /dev/tty
    read -p "$prompt" response
    fi

    # Use default if response is empty
    echo "${response:-$default}"
    }

    # Function to run wg-easy container
    run_wg_easy() {
    local wg_host
    @@ -166,25 +186,23 @@ run_wg_easy() {
    wg_host=$(curl -s --connect-timeout 10 ifconfig.me || echo "")
    if [[ -z "$wg_host" ]]; then
    log "Warning: Could not fetch public IP automatically."
    read -p "Enter public IP or hostname: " wg_host
    wg_host=$(read_from_terminal "Enter public IP or hostname: " "")
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error: No IP or hostname provided.${NC}"
    exit 1
    fi
    fi
    log "Using WG_HOST=$wg_host"

    read -p "Enter password for wg-easy [default: admin123]: " password
    password=${password:-admin123}
    password=$(read_from_terminal "Enter password for wg-easy [default: admin123]: " "admin123")
    log "Generating password hash..."
    password_hash=$(docker run --rm ghcr.io/wg-easy/wg-easy:14 wgpw "$password" 2>> "$LOG_FILE") || {
    log "${RED}Error generating password hash.${NC}"
    exit 1
    }
    log "Password hash generated successfully."

    read -p "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " panel_port
    panel_port=${panel_port:-80}
    panel_port=$(read_from_terminal "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " "80")
    if ! validate_port "$panel_port"; then
    log "${RED}Error: Invalid port number. Using default port 80.${NC}"
    panel_port=80
    @@ -252,7 +270,7 @@ main() {
    echo "2. Install Docker"
    echo "3. Configure iptable_nat module"
    echo "4. Run the wg-easy container"
    read -p "Proceed with installation? (y/n): " answer
    answer=$(read_from_terminal "Proceed with installation? (y/n): " "")
    case $answer in
    [Yy]* ) log "Starting installation...";;
    [Nn]* ) log "Installation canceled."; exit 0;;
  11. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 31 additions and 9 deletions.
    40 changes: 31 additions & 9 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -63,7 +63,7 @@ setup_swapfile() {

    # Create and configure swapfile
    if ! fallocate -l "$swap_size" "$swap_file" 2>> "$LOG_FILE"; then
    log "${RED}Error creating swapfile with fallocate. Trying dd...${NC}"
    log "Warning: fallocate failed. Trying dd instead..."
    if ! dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" 2>> "$LOG_FILE"; then
    log "${RED}Error creating swapfile with dd.${NC}"
    exit 1
    @@ -135,7 +135,7 @@ setup_iptables() {
    else
    log "${RED}Error: iptable_nat module not loaded.${NC}"
    exit 1
    }
    fi
    }

    # Function to validate port
    @@ -156,10 +156,16 @@ run_wg_easy() {
    local password_hash
    local container_name="wg-easy"

    # Check if Docker is running
    if ! systemctl is-active --quiet docker; then
    log "${RED}Error: Docker is not running. Please check Docker installation.${NC}"
    exit 1
    fi

    log "Fetching public IP address..."
    wg_host=$(curl -s ifconfig.me || true)
    wg_host=$(curl -s --connect-timeout 10 ifconfig.me || echo "")
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error fetching public IP. Enter manually:${NC}"
    log "Warning: Could not fetch public IP automatically."
    read -p "Enter public IP or hostname: " wg_host
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error: No IP or hostname provided.${NC}"
    @@ -185,6 +191,13 @@ run_wg_easy() {
    fi
    log "Using panel port: $panel_port"

    # Stop and remove existing container if it exists
    if docker ps -a --format 'table {{.Names}}' | grep -q "^$container_name$"; then
    log "Stopping and removing existing wg-easy container..."
    docker stop "$container_name" >> "$LOG_FILE" 2>&1 || true
    docker rm "$container_name" >> "$LOG_FILE" 2>&1 || true
    fi

    log "Starting wg-easy container..."
    docker run -d --name "$container_name" \
    -e WG_HOST="$wg_host" \
    @@ -195,13 +208,22 @@ run_wg_easy() {
    --cap-add=SYS_MODULE \
    --sysctl net.ipv4.ip_forward=1 \
    --restart unless-stopped \
    -v ~/.wg-easy:/etc/wireguard \
    ghcr.io/wg-easy/wg-easy:14 >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error starting wg-easy container.${NC}"
    exit 1
    }

    # Wait a moment and check if container is running
    sleep 5
    if ! docker ps --format 'table {{.Names}}' | grep -q "^$container_name$"; then
    log "${RED}Error: wg-easy container failed to start. Check logs with: docker logs $container_name${NC}"
    exit 1
    fi

    log "${GREEN}wg-easy container started successfully!${NC}"

    # Store variables in memory instead of files
    # Store variables in memory for final output
    export WG_HOST="$wg_host"
    export PANEL_PORT="$panel_port"
    }
    @@ -219,10 +241,9 @@ main() {
    echo "----------------------------------------"
    log "Starting wg-easy installation script at $(date)..."

    # Check prerequisites
    # Check prerequisites (Docker check is optional here since we install it)
    check_command curl
    check_command systemctl
    check_command docker || true # Docker might not be installed yet
    check_command $(get_package_manager)

    # Prompt user for confirmation
    @@ -249,14 +270,15 @@ main() {
    echo "Access the wg-easy panel at: http://$WG_HOST:$PANEL_PORT"
    echo "----------------------------------------"
    echo "Important:"
    echo "1. Ensure the web port ($PANEL_PORT/tcp) is open каш your firewall."
    echo "1. Ensure the web port ($PANEL_PORT/tcp) is open in your firewall."
    echo "2. Ensure the VPN port (51820/udp) is open in your firewall."
    echo " Example for firewalld (if installed):"
    echo " sudo firewall-cmd --add-port=$PANEL_PORT/tcp --permanent"
    echo " sudo firewall-cmd --add-port=51820/udp --permanent"
    echo " sudo firewall-cmd --reload"
    echo "3. If using Oracle Cloud, open ports $PANEL_PORT/tcp and 51820/udp in the OCI console (VirtualCloud Network > Security List)."
    echo "3. If using Oracle Cloud, open ports $PANEL_PORT/tcp and 51820/udp in the OCI console (Virtual Cloud Network > Security List)."
    echo "4. Download the WireGuard client from: https://www.wireguard.com/install/"
    echo "5. Check container status with: docker logs wg-easy"
    echo "----------------------------------------"
    log "${GREEN}Installation completed successfully! Access wg-easy at http://$WG_HOST:$PANEL_PORT${NC}"
    }
  12. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 87 additions and 40 deletions.
    127 changes: 87 additions & 40 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ GREEN='\033[0;32m'
    NC='\033[0m'

    # Log file
    LOG_FILE="install_wg_easy.log"
    LOG_FILE="/var/log/install_wg_easy.log"

    # Function to log messages
    log() {
    @@ -30,28 +30,46 @@ check_command() {
    fi
    }

    # Function to detect package manager
    get_package_manager() {
    if command -v dnf &> /dev/null; then
    echo "dnf"
    elif command -v yum &> /dev/null; then
    echo "yum"
    else
    log "${RED}Error: No supported package manager (dnf/yum) found.${NC}"
    exit 1
    fi
    }

    # Function to set up the swapfile
    setup_swapfile() {
    local swap_size="4G"
    local swap_file="/swapfile"
    local swap_size_mb=4096 # 4GB in MB for dd fallback

    log "Setting up swapfile of $swap_size..."

    # Check if swapfile already exists
    if [[ -f "$swap_file" ]]; then
    log "${RED}Swapfile already exists at $swap_file. Skipping creation.${NC}"
    return
    if swapon --show | grep -q "$swap_file"; then
    log "${GREEN}Swapfile already exists and active at $swap_file.${NC}"
    return
    else
    log "${RED}Swapfile exists at $swap_file but is not active. Please check configuration.${NC}"
    exit 1
    fi
    fi

    # Create and configure swapfile
    fallocate -l "$swap_size" "$swap_file" || {
    if ! fallocate -l "$swap_size" "$swap_file" 2>> "$LOG_FILE"; then
    log "${RED}Error creating swapfile with fallocate. Trying dd...${NC}"
    dd if=/dev/zero of="$swap_file" bs=1M count=4096 || {
    if ! dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" 2>> "$LOG_FILE"; then
    log "${RED}Error creating swapfile with dd.${NC}"
    exit 1
    }
    }
    chmod 600 "$swap_file" || { log "${RED}Error setting swapfile permissions.${NC}"; exit 1; }
    fi
    fi
    chmod 600 "$swap_file" 2>> "$LOG_FILE" || { log "${RED}Error setting swapfile permissions.${NC}"; exit 1; }
    mkswap "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error formatting swapfile.${NC}"; exit 1; }
    swapon "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error activating swapfile.${NC}"; exit 1; }

    @@ -67,17 +85,37 @@ setup_swapfile() {

    # Function to install Docker
    install_docker() {
    log "Configuring Docker repository..."
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    exit 1
    }
    local pkg_manager
    pkg_manager=$(get_package_manager)

    log "Installing Docker..."
    yum install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    exit 1
    }
    if [[ "$pkg_manager" == "dnf" ]]; then
    dnf install -y dnf-plugins-core >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing dnf-plugins-core.${NC}"
    exit 1
    }
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    exit 1
    }
    dnf install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    exit 1
    }
    else
    yum install -y yum-utils >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing yum-utils.${NC}"
    exit 1
    }
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    exit 1
    }
    yum install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    exit 1
    }
    fi

    log "Starting and enabling Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "${RED}Error starting Docker.${NC}"; exit 1; }
    @@ -88,10 +126,10 @@ install_docker() {
    # Function to set up the iptable_nat module
    setup_iptables() {
    log "Loading iptable_nat module..."
    modprobe iptable_nat >> "$LOG_FILE" 2>&1 || {
    if ! modprobe iptable_nat >> "$LOG_FILE" 2>&1; then
    log "${RED}Error loading iptable_nat module.${NC}"
    exit 1
    }
    fi
    if lsmod | grep -q iptable_nat; then
    log "${GREEN}iptable_nat module loaded successfully!${NC}"
    else
    @@ -100,6 +138,16 @@ setup_iptables() {
    }
    }

    # Function to validate port
    validate_port() {
    local port=$1
    if [[ "$port" =~ ^[0-9]+$ ]] && [ "$port" -ge 1 ] && [ "$port" -le 65535 ]; then
    return 0
    else
    return 1
    fi
    }

    # Function to run wg-easy container
    run_wg_easy() {
    local wg_host
    @@ -109,14 +157,15 @@ run_wg_easy() {
    local container_name="wg-easy"

    log "Fetching public IP address..."
    wg_host=$(curl -s ifconfig.me) || {
    wg_host=$(curl -s ifconfig.me || true)
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error fetching public IP. Enter manually:${NC}"
    read -p "Enter public IP or hostname: " wg_host
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error: No IP or hostname provided.${NC}"
    exit 1
    }
    }
    fi
    fi
    log "Using WG_HOST=$wg_host"

    read -p "Enter password for wg-easy [default: admin123]: " password
    @@ -130,7 +179,7 @@ run_wg_easy() {

    read -p "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " panel_port
    panel_port=${panel_port:-80}
    if [[ ! $panel_port =~ ^[0-9]+$ ]]; then
    if ! validate_port "$panel_port"; then
    log "${RED}Error: Invalid port number. Using default port 80.${NC}"
    panel_port=80
    fi
    @@ -152,13 +201,16 @@ run_wg_easy() {
    }
    log "${GREEN}wg-easy container started successfully!${NC}"

    # Export variables for final message
    echo "$wg_host" > /tmp/wg_host
    echo "$panel_port" > /tmp/panel_port
    # Store variables in memory instead of files
    export WG_HOST="$wg_host"
    export PANEL_PORT="$panel_port"
    }

    # Main function
    main() {
    # Create log directory if it doesn't exist
    mkdir -p "$(dirname "$LOG_FILE")"

    # Display welcome message
    echo -e "${GREEN}Welcome to the wg-easy Installation Script!${NC}"
    echo "This script was created by Gustavo Toledo (@itxtoledo) to simplify setting up wg-easy on Oracle Linux."
    @@ -169,9 +221,9 @@ main() {

    # Check prerequisites
    check_command curl
    check_command yum
    check_command systemctl
    check_command docker
    check_command docker || true # Docker might not be installed yet
    check_command $(get_package_manager)

    # Prompt user for confirmation
    echo "This script will:"
    @@ -192,30 +244,25 @@ main() {
    setup_iptables
    run_wg_easy

    # Retrieve variables for final message
    wg_host=$(cat /tmp/wg_host)
    panel_port=$(cat /tmp/panel_port)
    rm -f /tmp/wg_host /tmp/panel_port

    # Display final message
    echo -e "${GREEN}Installation completed successfully!${NC}"
    echo "Access the wg-easy panel at: http://$wg_host:$panel_port"
    echo "Access the wg-easy panel at: http://$WG_HOST:$PANEL_PORT"
    echo "----------------------------------------"
    echo "Important:"
    echo "1. Ensure the web port ($panel_port/tcp) is open in your firewall."
    echo "1. Ensure the web port ($PANEL_PORT/tcp) is open каш your firewall."
    echo "2. Ensure the VPN port (51820/udp) is open in your firewall."
    echo " Example for firewalld:"
    echo " sudo firewall-cmd --add-port=$panel_port/tcp --permanent"
    echo " Example for firewalld (if installed):"
    echo " sudo firewall-cmd --add-port=$PANEL_PORT/tcp --permanent"
    echo " sudo firewall-cmd --add-port=51820/udp --permanent"
    echo " sudo firewall-cmd --reload"
    echo "3. If using Oracle Cloud, open ports $panel_port/tcp and 51820/udp in the OCI console (Virtual Cloud Network > Security List)."
    echo "3. If using Oracle Cloud, open ports $PANEL_PORT/tcp and 51820/udp in the OCI console (VirtualCloud Network > Security List)."
    echo "4. Download the WireGuard client from: https://www.wireguard.com/install/"
    echo "----------------------------------------"
    log "${GREEN}Installation completed successfully! Access wg-easy at http://$wg_host:$panel_port${NC}"
    log "${GREEN}Installation completed successfully! Access wg-easy at http://$WG_HOST:$PANEL_PORT${NC}"
    }

    # Set trap for errors
    trap 'log "${RED}Error on line $LINENO${NC}"; rm -f /tmp/wg_host /tmp/panel_port; exit 1' ERR
    trap 'log "${RED}Error on line $LINENO in command: $BASH_COMMAND${NC}"; exit 1' ERR

    # Run the script
    main
  13. itxtoledo revised this gist Jun 9, 2025. 1 changed file with 216 additions and 89 deletions.
    305 changes: 216 additions & 89 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -1,94 +1,221 @@
    #!/bin/bash

    # Optimized script to install wg-easy on Oracle Linux (Oracle Cloud) in a VPS with 1 GB of RAM
    # Asks for the web interface password, separates installation commands, and explains the process

    echo "Welcome to the optimized wg-easy installation script!"
    echo "This script installs Docker and wg-easy, a simple interface to manage a WireGuard VPN."
    echo "The installation is split into steps to avoid excessive memory usage on a 1 GB RAM VPS."
    echo "You will be able to access a web interface to create VPN clients and download configurations."
    echo

    # Ask the user for the password
    read -sp "Enter the password you want to use for the wg-easy web interface: " PASSWORD
    echo

    # Check if the password is empty
    if [ -z "$PASSWORD" ]; then
    echo "Error: The password cannot be empty!"
    # Check if running as root
    if [[ $EUID -ne 0 ]]; then
    echo -e "\033[0;31mError: This script must be run as root. Use sudo.\033[0m"
    exit 1
    fi

    echo "Starting the installation in steps. Follow the instructions and wait for each step to complete."
    echo "To monitor memory usage, open another terminal and run: watch -n 1 free -m"
    echo

    # Step 1: Install dnf plugins
    echo "Step 1: Installing dnf plugins..."
    sudo dnf -y install dnf-plugins-core
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 1 completed."
    echo

    # Step 2: Add the Docker repository
    echo "Step 2: Adding the Docker repository..."
    sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 2 completed."
    echo

    # Step 3: Install Docker
    echo "Step 3: Installing Docker..."
    sudo dnf -y install docker-ce docker-ce-cli containerd.io
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 3 completed."
    echo

    # Step 4: Enable and start the Docker service
    echo "Step 4: Enabling and starting Docker..."
    sudo systemctl enable docker
    sudo systemctl start docker
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 4 completed."
    echo

    # Step 5: Run the wg-easy container
    echo "Step 5: Starting the wg-easy container..."
    docker run -d --name=wg-easy \
    -e WG_HOST=$(curl -s ifconfig.me) \
    -e PASSWORD="$PASSWORD" \
    -v ~/.wg-easy:/etc/wireguard \
    -p 51820:51820/udp \
    -p 51821:51821/tcp \
    --cap-add=NET_ADMIN \
    --cap-add=SYS_MODULE \
    --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
    --sysctl="net.ipv4.ip_forward=1" \
    --restart unless-stopped \
    ghcr.io/wg-easy/wg-easy

    # Check if the container started successfully
    if [ $? -eq 0 ]; then
    echo "Installation completed successfully!"
    echo
    echo "Next steps:"
    echo "1. Access the web interface at: http://$(curl -s ifconfig.me):51821"
    echo "2. Log in with the password you set."
    echo "3. Create a client in the web interface and download the configuration file (.conf) or QR code."
    echo "4. Use the WireGuard app (available for Windows, macOS, Linux, iOS, Android) to connect to the VPN."
    echo
    echo "IMPORTANT: In Oracle Cloud, configure the VCN security rules to open the ports:"
    echo " - 51820/UDP (for WireGuard)"
    echo " - 51821/TCP (for the web interface)"
    echo "You can use the commands below to open the ports in the local firewall:"
    echo " sudo firewall-cmd --permanent --add-port=51820/udp"
    echo " sudo firewall-cmd --permanent --add-port=51821/tcp"
    echo " sudo firewall-cmd --reload"
    else
    echo "Error starting the wg-easy container. Check the logs with: docker logs wg-easy"
    exit 1
    fi
    # Initial settings
    set -euo pipefail

    # Colors for feedback
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    NC='\033[0m'

    # Log file
    LOG_FILE="install_wg_easy.log"

    # Function to log messages
    log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
    }

    # Function to check if a command exists
    check_command() {
    if ! command -v "$1" &> /dev/null; then
    log "${RED}Error: $1 not found. Please install it first.${NC}"
    exit 1
    fi
    }

    # Function to set up the swapfile
    setup_swapfile() {
    local swap_size="4G"
    local swap_file="/swapfile"

    log "Setting up swapfile of $swap_size..."

    # Check if swapfile already exists
    if [[ -f "$swap_file" ]]; then
    log "${RED}Swapfile already exists at $swap_file. Skipping creation.${NC}"
    return
    fi

    # Create and configure swapfile
    fallocate -l "$swap_size" "$swap_file" || {
    log "${RED}Error creating swapfile with fallocate. Trying dd...${NC}"
    dd if=/dev/zero of="$swap_file" bs=1M count=4096 || {
    log "${RED}Error creating swapfile with dd.${NC}"
    exit 1
    }
    }
    chmod 600 "$swap_file" || { log "${RED}Error setting swapfile permissions.${NC}"; exit 1; }
    mkswap "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error formatting swapfile.${NC}"; exit 1; }
    swapon "$swap_file" >> "$LOG_FILE" 2>&1 || { log "${RED}Error activating swapfile.${NC}"; exit 1; }

    # Add to fstab if not already present
    if ! grep -q "$swap_file" /etc/fstab; then
    echo "$swap_file none swap sw 0 0" >> /etc/fstab
    log "Swapfile added to /etc/fstab."
    else
    log "Swapfile already present in /etc/fstab."
    fi
    log "${GREEN}Swapfile configured successfully!${NC}"
    }

    # Function to install Docker
    install_docker() {
    log "Configuring Docker repository..."
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error adding Docker repository.${NC}"
    exit 1
    }

    log "Installing Docker..."
    yum install -y docker-ce docker-ce-cli containerd.io >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error installing Docker.${NC}"
    exit 1
    }

    log "Starting and enabling Docker..."
    systemctl start docker >> "$LOG_FILE" 2>&1 || { log "${RED}Error starting Docker.${NC}"; exit 1; }
    systemctl enable docker >> "$LOG_FILE" 2>&1 || { log "${RED}Error enabling Docker.${NC}"; exit 1; }
    log "${GREEN}Docker installed and configured successfully!${NC}"
    }

    # Function to set up the iptable_nat module
    setup_iptables() {
    log "Loading iptable_nat module..."
    modprobe iptable_nat >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error loading iptable_nat module.${NC}"
    exit 1
    }
    if lsmod | grep -q iptable_nat; then
    log "${GREEN}iptable_nat module loaded successfully!${NC}"
    else
    log "${RED}Error: iptable_nat module not loaded.${NC}"
    exit 1
    }
    }

    # Function to run wg-easy container
    run_wg_easy() {
    local wg_host
    local panel_port
    local password
    local password_hash
    local container_name="wg-easy"

    log "Fetching public IP address..."
    wg_host=$(curl -s ifconfig.me) || {
    log "${RED}Error fetching public IP. Enter manually:${NC}"
    read -p "Enter public IP or hostname: " wg_host
    if [[ -z "$wg_host" ]]; then
    log "${RED}Error: No IP or hostname provided.${NC}"
    exit 1
    }
    }
    log "Using WG_HOST=$wg_host"

    read -p "Enter password for wg-easy [default: admin123]: " password
    password=${password:-admin123}
    log "Generating password hash..."
    password_hash=$(docker run --rm ghcr.io/wg-easy/wg-easy:14 wgpw "$password" 2>> "$LOG_FILE") || {
    log "${RED}Error generating password hash.${NC}"
    exit 1
    }
    log "Password hash generated successfully."

    read -p "Enter port for wg-easy panel (commonly used: 80) [default: 80]: " panel_port
    panel_port=${panel_port:-80}
    if [[ ! $panel_port =~ ^[0-9]+$ ]]; then
    log "${RED}Error: Invalid port number. Using default port 80.${NC}"
    panel_port=80
    fi
    log "Using panel port: $panel_port"

    log "Starting wg-easy container..."
    docker run -d --name "$container_name" \
    -e WG_HOST="$wg_host" \
    -e PASSWORD_HASH="$password_hash" \
    -p 51820:51820/udp \
    -p "$panel_port":51821/tcp \
    --cap-add=NET_ADMIN \
    --cap-add=SYS_MODULE \
    --sysctl net.ipv4.ip_forward=1 \
    --restart unless-stopped \
    ghcr.io/wg-easy/wg-easy:14 >> "$LOG_FILE" 2>&1 || {
    log "${RED}Error starting wg-easy container.${NC}"
    exit 1
    }
    log "${GREEN}wg-easy container started successfully!${NC}"

    # Export variables for final message
    echo "$wg_host" > /tmp/wg_host
    echo "$panel_port" > /tmp/panel_port
    }

    # Main function
    main() {
    # Display welcome message
    echo -e "${GREEN}Welcome to the wg-easy Installation Script!${NC}"
    echo "This script was created by Gustavo Toledo (@itxtoledo) to simplify setting up wg-easy on Oracle Linux."
    echo "Enjoy a seamless installation experience!"
    echo "Check out more tech content on Gustavo's YouTube channel: https://www.youtube.com/c/itxToledo"
    echo "----------------------------------------"
    log "Starting wg-easy installation script at $(date)..."

    # Check prerequisites
    check_command curl
    check_command yum
    check_command systemctl
    check_command docker

    # Prompt user for confirmation
    echo "This script will:"
    echo "1. Set up a 4GB swapfile"
    echo "2. Install Docker"
    echo "3. Configure iptable_nat module"
    echo "4. Run the wg-easy container"
    read -p "Proceed with installation? (y/n): " answer
    case $answer in
    [Yy]* ) log "Starting installation...";;
    [Nn]* ) log "Installation canceled."; exit 0;;
    * ) log "${RED}Invalid response.${NC}"; exit 1;;
    esac

    # Execute installation steps
    setup_swapfile
    install_docker
    setup_iptables
    run_wg_easy

    # Retrieve variables for final message
    wg_host=$(cat /tmp/wg_host)
    panel_port=$(cat /tmp/panel_port)
    rm -f /tmp/wg_host /tmp/panel_port

    # Display final message
    echo -e "${GREEN}Installation completed successfully!${NC}"
    echo "Access the wg-easy panel at: http://$wg_host:$panel_port"
    echo "----------------------------------------"
    echo "Important:"
    echo "1. Ensure the web port ($panel_port/tcp) is open in your firewall."
    echo "2. Ensure the VPN port (51820/udp) is open in your firewall."
    echo " Example for firewalld:"
    echo " sudo firewall-cmd --add-port=$panel_port/tcp --permanent"
    echo " sudo firewall-cmd --add-port=51820/udp --permanent"
    echo " sudo firewall-cmd --reload"
    echo "3. If using Oracle Cloud, open ports $panel_port/tcp and 51820/udp in the OCI console (Virtual Cloud Network > Security List)."
    echo "4. Download the WireGuard client from: https://www.wireguard.com/install/"
    echo "----------------------------------------"
    log "${GREEN}Installation completed successfully! Access wg-easy at http://$wg_host:$panel_port${NC}"
    }

    # Set trap for errors
    trap 'log "${RED}Error on line $LINENO${NC}"; rm -f /tmp/wg_host /tmp/panel_port; exit 1' ERR

    # Run the script
    main
  14. itxtoledo created this gist Jun 6, 2025.
    94 changes: 94 additions & 0 deletions wg-easy-setup-oracle-vm.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    #!/bin/bash

    # Optimized script to install wg-easy on Oracle Linux (Oracle Cloud) in a VPS with 1 GB of RAM
    # Asks for the web interface password, separates installation commands, and explains the process

    echo "Welcome to the optimized wg-easy installation script!"
    echo "This script installs Docker and wg-easy, a simple interface to manage a WireGuard VPN."
    echo "The installation is split into steps to avoid excessive memory usage on a 1 GB RAM VPS."
    echo "You will be able to access a web interface to create VPN clients and download configurations."
    echo

    # Ask the user for the password
    read -sp "Enter the password you want to use for the wg-easy web interface: " PASSWORD
    echo

    # Check if the password is empty
    if [ -z "$PASSWORD" ]; then
    echo "Error: The password cannot be empty!"
    exit 1
    fi

    echo "Starting the installation in steps. Follow the instructions and wait for each step to complete."
    echo "To monitor memory usage, open another terminal and run: watch -n 1 free -m"
    echo

    # Step 1: Install dnf plugins
    echo "Step 1: Installing dnf plugins..."
    sudo dnf -y install dnf-plugins-core
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 1 completed."
    echo

    # Step 2: Add the Docker repository
    echo "Step 2: Adding the Docker repository..."
    sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 2 completed."
    echo

    # Step 3: Install Docker
    echo "Step 3: Installing Docker..."
    sudo dnf -y install docker-ce docker-ce-cli containerd.io
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 3 completed."
    echo

    # Step 4: Enable and start the Docker service
    echo "Step 4: Enabling and starting Docker..."
    sudo systemctl enable docker
    sudo systemctl start docker
    sync
    sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
    echo "Step 4 completed."
    echo

    # Step 5: Run the wg-easy container
    echo "Step 5: Starting the wg-easy container..."
    docker run -d --name=wg-easy \
    -e WG_HOST=$(curl -s ifconfig.me) \
    -e PASSWORD="$PASSWORD" \
    -v ~/.wg-easy:/etc/wireguard \
    -p 51820:51820/udp \
    -p 51821:51821/tcp \
    --cap-add=NET_ADMIN \
    --cap-add=SYS_MODULE \
    --sysctl="net.ipv4.conf.all.src_valid_mark=1" \
    --sysctl="net.ipv4.ip_forward=1" \
    --restart unless-stopped \
    ghcr.io/wg-easy/wg-easy

    # Check if the container started successfully
    if [ $? -eq 0 ]; then
    echo "Installation completed successfully!"
    echo
    echo "Next steps:"
    echo "1. Access the web interface at: http://$(curl -s ifconfig.me):51821"
    echo "2. Log in with the password you set."
    echo "3. Create a client in the web interface and download the configuration file (.conf) or QR code."
    echo "4. Use the WireGuard app (available for Windows, macOS, Linux, iOS, Android) to connect to the VPN."
    echo
    echo "IMPORTANT: In Oracle Cloud, configure the VCN security rules to open the ports:"
    echo " - 51820/UDP (for WireGuard)"
    echo " - 51821/TCP (for the web interface)"
    echo "You can use the commands below to open the ports in the local firewall:"
    echo " sudo firewall-cmd --permanent --add-port=51820/udp"
    echo " sudo firewall-cmd --permanent --add-port=51821/tcp"
    echo " sudo firewall-cmd --reload"
    else
    echo "Error starting the wg-easy container. Check the logs with: docker logs wg-easy"
    exit 1
    fi