Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsviatoslav-gusev <113284446+sviatoslav-gusev@users.noreply.github.com>2026-01-21 18:47:36 +0300
committerGitHub <noreply@github.com>2026-01-21 18:47:36 +0300
commit70b365171f9b40b540be5bff1a9c8b7227a37ac6 (patch)
tree82500efe6608476d53b29b266044dec5228d58c8
parent328ba3b45eb2108abe8a985f9c060ba4187e1596 (diff)
feat: add option to use existing custom SSL certificates (#3688)
-rw-r--r--install.sh66
-rwxr-xr-xupdate.sh68
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}"