From 70b365171f9b40b540be5bff1a9c8b7227a37ac6 Mon Sep 17 00:00:00 2001 From: sviatoslav-gusev <113284446+sviatoslav-gusev@users.noreply.github.com> Date: Wed, 21 Jan 2026 18:47:36 +0300 Subject: [PATCH] feat: add option to use existing custom SSL certificates (#3688) --- install.sh | 66 +++++++++++++++++++++++++++++++++++++++++++++++++--- update.sh | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 128 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 89ddf2a0..62c8ea37 100644 --- a/install.sh +++ b/install.sh @@ -521,12 +521,13 @@ prompt_and_setup_ssl() { echo -e "${yellow}Choose SSL certificate setup method:${plain}" echo -e "${green}1.${plain} Let's Encrypt for Domain (90-day validity, auto-renews)" echo -e "${green}2.${plain} Let's Encrypt for IP Address (6-day validity, auto-renews)" - echo -e "${blue}Note:${plain} Both options require port 80 open. IP certs use shortlived profile." + echo -e "${green}3.${plain} Custom SSL Certificate (Path to existing files)" + echo -e "${blue}Note:${plain} Options 1 & 2 require port 80 open. Option 3 requires manual paths." read -rp "Choose an option (default 2 for IP): " ssl_choice ssl_choice="${ssl_choice// /}" # Trim whitespace - # Default to 2 (IP cert) if not 1 - if [[ "$ssl_choice" != "1" ]]; then + # Default to 2 (IP cert) if input is empty or invalid (not 1 or 3) + if [[ "$ssl_choice" != "1" && "$ssl_choice" != "3" ]]; then ssl_choice="2" fi @@ -569,7 +570,66 @@ prompt_and_setup_ssl() { echo -e "${red}✗ IP certificate setup failed. Please check port 80 is open.${plain}" SSL_HOST="${server_ip}" fi + ;; + 3) + # User chose Custom Paths (User Provided) option + echo -e "${green}Using custom existing certificate...${plain}" + local custom_cert="" + local custom_key="" + local custom_domain="" + + # 3.1 Request Domain to compose Panel URL later + read -rp "Please enter domain name certificate issued for: " custom_domain + custom_domain="${custom_domain// /}" # Убираем пробелы + + # 3.2 Loop for Certificate Path + while true; do + read -rp "Input certificate path (keywords: .crt / fullchain): " custom_cert + # Strip quotes if present + custom_cert=$(echo "$custom_cert" | tr -d '"' | tr -d "'") + + if [[ -f "$custom_cert" && -r "$custom_cert" && -s "$custom_cert" ]]; then + break + elif [[ ! -f "$custom_cert" ]]; then + echo -e "${red}Error: File does not exist! Try again.${plain}" + elif [[ ! -r "$custom_cert" ]]; then + echo -e "${red}Error: File exists but is not readable (check permissions)!${plain}" + else + echo -e "${red}Error: File is empty!${plain}" + fi + done + + # 3.3 Loop for Private Key Path + while true; do + read -rp "Input private key path (keywords: .key / privatekey): " custom_key + # Strip quotes if present + custom_key=$(echo "$custom_key" | tr -d '"' | tr -d "'") + + if [[ -f "$custom_key" && -r "$custom_key" && -s "$custom_key" ]]; then + break + elif [[ ! -f "$custom_key" ]]; then + echo -e "${red}Error: File does not exist! Try again.${plain}" + elif [[ ! -r "$custom_key" ]]; then + echo -e "${red}Error: File exists but is not readable (check permissions)!${plain}" + else + echo -e "${red}Error: File is empty!${plain}" + fi + done + + # 3.4 Apply Settings via x-ui binary + ${xui_folder}/x-ui cert -webCert "$custom_cert" -webCertKey "$custom_key" >/dev/null 2>&1 + # Set SSL_HOST for composing Panel URL + if [[ -n "$custom_domain" ]]; then + SSL_HOST="$custom_domain" + else + SSL_HOST="${server_ip}" + fi + + echo -e "${green}✓ Custom certificate paths applied.${plain}" + echo -e "${yellow}Note: You are responsible for renewing these files externally.${plain}" + + systemctl restart x-ui >/dev/null 2>&1 || rc-service x-ui restart >/dev/null 2>&1 ;; *) echo -e "${red}Invalid option. Skipping SSL setup.${plain}" diff --git a/update.sh b/update.sh index 58206984..3781c365 100755 --- a/update.sh +++ b/update.sh @@ -541,12 +541,13 @@ prompt_and_setup_ssl() { echo -e "${yellow}Choose SSL certificate setup method:${plain}" echo -e "${green}1.${plain} Let's Encrypt for Domain (90-day validity, auto-renews)" echo -e "${green}2.${plain} Let's Encrypt for IP Address (6-day validity, auto-renews)" - echo -e "${blue}Note:${plain} Both options require port 80 open. IP certs use shortlived profile." + echo -e "${green}3.${plain} Custom SSL Certificate (Path to existing files)" + echo -e "${blue}Note:${plain} Options 1 & 2 require port 80 open. Option 3 requires manual paths." read -rp "Choose an option (default 2 for IP): " ssl_choice ssl_choice="${ssl_choice// /}" # Trim whitespace - # Default to 2 (IP cert) if not 1 - if [[ "$ssl_choice" != "1" ]]; then + # Default to 2 (IP cert) if input is empty or invalid (not 1 or 3) + if [[ "$ssl_choice" != "1" && "$ssl_choice" != "3" ]]; then ssl_choice="2" fi @@ -596,6 +597,67 @@ prompt_and_setup_ssl() { else systemctl restart x-ui >/dev/null 2>&1 fi + + ;; + 3) + # User chose Custom Paths (User Provided) option + echo -e "${green}Using custom existing certificate...${plain}" + local custom_cert="" + local custom_key="" + local custom_domain="" + + # 3.1 Request Domain to compose Panel URL later + read -rp "Please enter domain name certificate issued for: " custom_domain + custom_domain="${custom_domain// /}" # Убираем пробелы + + # 3.2 Loop for Certificate Path + while true; do + read -rp "Input certificate path (keywords: .crt / fullchain): " custom_cert + # Strip quotes if present + custom_cert=$(echo "$custom_cert" | tr -d '"' | tr -d "'") + + if [[ -f "$custom_cert" && -r "$custom_cert" && -s "$custom_cert" ]]; then + break + elif [[ ! -f "$custom_cert" ]]; then + echo -e "${red}Error: File does not exist! Try again.${plain}" + elif [[ ! -r "$custom_cert" ]]; then + echo -e "${red}Error: File exists but is not readable (check permissions)!${plain}" + else + echo -e "${red}Error: File is empty!${plain}" + fi + done + + # 3.3 Loop for Private Key Path + while true; do + read -rp "Input private key path (keywords: .key / privatekey): " custom_key + # Strip quotes if present + custom_key=$(echo "$custom_key" | tr -d '"' | tr -d "'") + + if [[ -f "$custom_key" && -r "$custom_key" && -s "$custom_key" ]]; then + break + elif [[ ! -f "$custom_key" ]]; then + echo -e "${red}Error: File does not exist! Try again.${plain}" + elif [[ ! -r "$custom_key" ]]; then + echo -e "${red}Error: File exists but is not readable (check permissions)!${plain}" + else + echo -e "${red}Error: File is empty!${plain}" + fi + done + + # 3.4 Apply Settings via x-ui binary + ${xui_folder}/x-ui cert -webCert "$custom_cert" -webCertKey "$custom_key" >/dev/null 2>&1 + + # Set SSL_HOST for composing Panel URL + if [[ -n "$custom_domain" ]]; then + SSL_HOST="$custom_domain" + else + SSL_HOST="${server_ip}" + fi + + echo -e "${green}✓ Custom certificate paths applied.${plain}" + echo -e "${yellow}Note: You are responsible for renewing these files externally.${plain}" + + systemctl restart x-ui >/dev/null 2>&1 || rc-service x-ui restart >/dev/null 2>&1 ;; *) echo -e "${red}Invalid option. Skipping SSL setup.${plain}"