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:
Diffstat (limited to 'x-ui.sh')
-rw-r--r--x-ui.sh1423
1 files changed, 715 insertions, 708 deletions
diff --git a/x-ui.sh b/x-ui.sh
index d061ff84..73e99195 100644
--- a/x-ui.sh
+++ b/x-ui.sh
@@ -22,16 +22,16 @@ function LOGI() {
# Port helpers: detect listener and owning process (best effort)
is_port_in_use() {
local port="$1"
- if command -v ss >/dev/null 2>&1; then
- ss -ltn 2>/dev/null | awk -v p=":${port}$" '$4 ~ p {exit 0} END {exit 1}'
+ if command -v ss > /dev/null 2>&1; then
+ ss -ltn 2> /dev/null | awk -v p=":${port}$" '$4 ~ p {exit 0} END {exit 1}'
return
fi
- if command -v netstat >/dev/null 2>&1; then
- netstat -lnt 2>/dev/null | awk -v p=":${port} " '$4 ~ p {exit 0} END {exit 1}'
+ if command -v netstat > /dev/null 2>&1; then
+ netstat -lnt 2> /dev/null | awk -v p=":${port} " '$4 ~ p {exit 0} END {exit 1}'
return
fi
- if command -v lsof >/dev/null 2>&1; then
- lsof -nP -iTCP:${port} -sTCP:LISTEN >/dev/null 2>&1 && return 0
+ if command -v lsof > /dev/null 2>&1; then
+ lsof -nP -iTCP:${port} -sTCP:LISTEN > /dev/null 2>&1 && return 0
fi
return 1
}
@@ -221,7 +221,7 @@ reset_user() {
fi
return 0
fi
-
+
read -rp "Please set the login username [default is a random username]: " config_account
[[ -z $config_account ]] && config_account=$(gen_random_string 10)
read -rp "Please set the login password [default is a random password]: " config_password
@@ -229,12 +229,12 @@ reset_user() {
read -rp "Do you want to disable currently configured two-factor authentication? (y/n): " twoFactorConfirm
if [[ $twoFactorConfirm != "y" && $twoFactorConfirm != "Y" ]]; then
- ${xui_folder}/x-ui setting -username "${config_account}" -password "${config_password}" -resetTwoFactor false >/dev/null 2>&1
+ ${xui_folder}/x-ui setting -username "${config_account}" -password "${config_password}" -resetTwoFactor false > /dev/null 2>&1
else
- ${xui_folder}/x-ui setting -username "${config_account}" -password "${config_password}" -resetTwoFactor true >/dev/null 2>&1
+ ${xui_folder}/x-ui setting -username "${config_account}" -password "${config_password}" -resetTwoFactor true > /dev/null 2>&1
echo -e "Two factor authentication has been disabled."
fi
-
+
echo -e "Panel login username has been reset to: ${green} ${config_account} ${plain}"
echo -e "Panel login password has been reset to: ${green} ${config_password} ${plain}"
echo -e "${green} Please use the new login username and password to access the X-UI panel. Also remember them! ${plain}"
@@ -243,7 +243,7 @@ reset_user() {
gen_random_string() {
local length="$1"
- openssl rand -base64 $(( length * 2 )) \
+ openssl rand -base64 $((length * 2)) \
| tr -dc 'a-zA-Z0-9' \
| head -c "$length"
}
@@ -260,7 +260,7 @@ reset_webbasepath() {
config_webBasePath=$(gen_random_string 18)
# Apply the new web base path setting
- ${xui_folder}/x-ui setting -webBasePath "${config_webBasePath}" >/dev/null 2>&1
+ ${xui_folder}/x-ui setting -webBasePath "${config_webBasePath}" > /dev/null 2>&1
echo -e "Web base path has been reset to: ${green}${config_webBasePath}${plain}"
echo -e "${green}Please use the new web base path to access the panel.${plain}"
@@ -310,16 +310,16 @@ check_config() {
echo -e "${yellow}You can get a Let's Encrypt certificate for your IP address (valid ~6 days, auto-renews).${plain}"
read -rp "Generate SSL certificate for IP now? [y/N]: " gen_ssl
if [[ "$gen_ssl" == "y" || "$gen_ssl" == "Y" ]]; then
- stop >/dev/null 2>&1
+ stop > /dev/null 2>&1
ssl_cert_issue_for_ip
if [[ $? -eq 0 ]]; then
echo -e "${green}Access URL: https://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
# ssl_cert_issue_for_ip already restarts the panel, but ensure it's running
- start >/dev/null 2>&1
+ start > /dev/null 2>&1
else
LOGE "IP certificate setup failed."
echo -e "${yellow}You can try again via option 19 (SSL Certificate Management).${plain}"
- start >/dev/null 2>&1
+ start > /dev/null 2>&1
fi
else
echo -e "${yellow}Access URL: http://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
@@ -471,19 +471,19 @@ show_log() {
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- grep -F 'x-ui[' /var/log/messages
- if [[ $# == 0 ]]; then
- before_show_menu
- fi
- ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- show_log
- ;;
+ 0)
+ show_menu
+ ;;
+ 1)
+ grep -F 'x-ui[' /var/log/messages
+ if [[ $# == 0 ]]; then
+ before_show_menu
+ fi
+ ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ show_log
+ ;;
esac
else
echo -e "${green}\t1.${plain} Debug Log"
@@ -492,25 +492,25 @@ show_log() {
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- journalctl -u x-ui -e --no-pager -f -p debug
- if [[ $# == 0 ]]; then
- before_show_menu
- fi
- ;;
- 2)
- sudo journalctl --rotate
- sudo journalctl --vacuum-time=1s
- echo "All Logs cleared."
- restart
- ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- show_log
- ;;
+ 0)
+ show_menu
+ ;;
+ 1)
+ journalctl -u x-ui -e --no-pager -f -p debug
+ if [[ $# == 0 ]]; then
+ before_show_menu
+ fi
+ ;;
+ 2)
+ sudo journalctl --rotate
+ sudo journalctl --vacuum-time=1s
+ echo "All Logs cleared."
+ restart
+ ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ show_log
+ ;;
esac
fi
}
@@ -521,21 +521,21 @@ bbr_menu() {
echo -e "${green}\t0.${plain} Back to Main Menu"
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- enable_bbr
- bbr_menu
- ;;
- 2)
- disable_bbr
- bbr_menu
- ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- bbr_menu
- ;;
+ 0)
+ show_menu
+ ;;
+ 1)
+ enable_bbr
+ bbr_menu
+ ;;
+ 2)
+ disable_bbr
+ bbr_menu
+ ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ bbr_menu
+ ;;
esac
}
@@ -583,7 +583,7 @@ enable_bbr() {
} > "/etc/sysctl.d/99-bbr-x-ui.conf"
if [ -f "/etc/sysctl.conf" ]; then
# Backup old settings from sysctl.conf, if any
- sed -i 's/^net.core.default_qdisc/# &/' /etc/sysctl.conf
+ sed -i 's/^net.core.default_qdisc/# &/' /etc/sysctl.conf
sed -i 's/^net.ipv4.tcp_congestion_control/# &/' /etc/sysctl.conf
fi
sysctl --system
@@ -688,17 +688,17 @@ check_install() {
show_status() {
check_status
case $? in
- 0)
- echo -e "Panel state: ${green}Running${plain}"
- show_enable_status
- ;;
- 1)
- echo -e "Panel state: ${yellow}Not Running${plain}"
- show_enable_status
- ;;
- 2)
- echo -e "Panel state: ${red}Not Installed${plain}"
- ;;
+ 0)
+ echo -e "Panel state: ${green}Running${plain}"
+ show_enable_status
+ ;;
+ 1)
+ echo -e "Panel state: ${yellow}Not Running${plain}"
+ show_enable_status
+ ;;
+ 2)
+ echo -e "Panel state: ${red}Not Installed${plain}"
+ ;;
esac
show_xray_status
}
@@ -741,46 +741,46 @@ firewall_menu() {
echo -e "${green}\t0.${plain} Back to Main Menu"
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- install_firewall
- firewall_menu
- ;;
- 2)
- ufw status numbered
- firewall_menu
- ;;
- 3)
- open_ports
- firewall_menu
- ;;
- 4)
- delete_ports
- firewall_menu
- ;;
- 5)
- ufw enable
- firewall_menu
- ;;
- 6)
- ufw disable
- firewall_menu
- ;;
- 7)
- ufw status verbose
- firewall_menu
- ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- firewall_menu
- ;;
+ 0)
+ show_menu
+ ;;
+ 1)
+ install_firewall
+ firewall_menu
+ ;;
+ 2)
+ ufw status numbered
+ firewall_menu
+ ;;
+ 3)
+ open_ports
+ firewall_menu
+ ;;
+ 4)
+ delete_ports
+ firewall_menu
+ ;;
+ 5)
+ ufw enable
+ firewall_menu
+ ;;
+ 6)
+ ufw disable
+ firewall_menu
+ ;;
+ 7)
+ ufw status verbose
+ firewall_menu
+ ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ firewall_menu
+ ;;
esac
}
install_firewall() {
- if ! command -v ufw &>/dev/null; then
+ if ! command -v ufw &> /dev/null; then
echo "ufw firewall is not installed. Installing now..."
apt-get update
apt-get install -y ufw
@@ -816,7 +816,7 @@ open_ports() {
fi
# Open the specified ports using ufw
- IFS=',' read -ra PORT_LIST <<<"$ports"
+ IFS=',' read -ra PORT_LIST <<< "$ports"
for port in "${PORT_LIST[@]}"; do
if [[ $port == *-* ]]; then
# Split the range into start and end ports
@@ -868,7 +868,7 @@ delete_ports() {
fi
# Split numbers into an array
- IFS=',' read -ra RULE_NUMBERS <<<"$rule_numbers"
+ IFS=',' read -ra RULE_NUMBERS <<< "$rule_numbers"
for rule_number in "${RULE_NUMBERS[@]}"; do
# Delete the rule by number
ufw delete "$rule_number" || echo "Failed to delete rule number $rule_number"
@@ -887,7 +887,7 @@ delete_ports() {
fi
# Split ports into an array
- IFS=',' read -ra PORT_LIST <<<"$ports"
+ IFS=',' read -ra PORT_LIST <<< "$ports"
for port in "${PORT_LIST[@]}"; do
if [[ $port == *-* ]]; then
# Split the port range
@@ -929,9 +929,18 @@ update_all_geofiles() {
update_geofiles() {
case "${1}" in
- "main") dat_files=(geoip geosite); dat_source="Loyalsoldier/v2ray-rules-dat";;
- "IR") dat_files=(geoip_IR geosite_IR); dat_source="chocolate4u/Iran-v2ray-rules" ;;
- "RU") dat_files=(geoip_RU geosite_RU); dat_source="runetfreedom/russia-v2ray-rules-dat";;
+ "main")
+ dat_files=(geoip geosite)
+ dat_source="Loyalsoldier/v2ray-rules-dat"
+ ;;
+ "IR")
+ dat_files=(geoip_IR geosite_IR)
+ dat_source="chocolate4u/Iran-v2ray-rules"
+ ;;
+ "RU")
+ dat_files=(geoip_RU geosite_RU)
+ dat_source="runetfreedom/russia-v2ray-rules-dat"
+ ;;
esac
for dat in "${dat_files[@]}"; do
# Remove suffix for remote filename (e.g., geoip_IR -> geoip)
@@ -950,33 +959,33 @@ update_geo() {
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- update_geofiles "main"
- echo -e "${green}Loyalsoldier datasets have been updated successfully!${plain}"
- restart
- ;;
- 2)
- update_geofiles "IR"
- echo -e "${green}chocolate4u datasets have been updated successfully!${plain}"
- restart
- ;;
- 3)
- update_geofiles "RU"
- echo -e "${green}runetfreedom datasets have been updated successfully!${plain}"
- restart
- ;;
- 4)
- update_all_geofiles
- echo -e "${green}All geo files have been updated successfully!${plain}"
- restart
- ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- update_geo
- ;;
+ 0)
+ show_menu
+ ;;
+ 1)
+ update_geofiles "main"
+ echo -e "${green}Loyalsoldier datasets have been updated successfully!${plain}"
+ restart
+ ;;
+ 2)
+ update_geofiles "IR"
+ echo -e "${green}chocolate4u datasets have been updated successfully!${plain}"
+ restart
+ ;;
+ 3)
+ update_geofiles "RU"
+ echo -e "${green}runetfreedom datasets have been updated successfully!${plain}"
+ restart
+ ;;
+ 4)
+ update_all_geofiles
+ echo -e "${green}All geo files have been updated successfully!${plain}"
+ restart
+ ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ update_geo
+ ;;
esac
before_show_menu
@@ -984,7 +993,7 @@ update_geo() {
install_acme() {
# Check if acme.sh is already installed
- if command -v ~/.acme.sh/acme.sh &>/dev/null; then
+ if command -v ~/.acme.sh/acme.sh &> /dev/null; then
LOGI "acme.sh is already installed."
return 0
fi
@@ -1014,141 +1023,141 @@ ssl_cert_issue_main() {
read -rp "Choose an option: " choice
case "$choice" in
- 0)
- show_menu
- ;;
- 1)
- ssl_cert_issue
- ssl_cert_issue_main
- ;;
- 2)
- local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
- if [ -z "$domains" ]; then
- echo "No certificates found to revoke."
- else
- echo "Existing domains:"
- echo "$domains"
- read -rp "Please enter a domain from the list to revoke the certificate: " domain
- if echo "$domains" | grep -qw "$domain"; then
- ~/.acme.sh/acme.sh --revoke -d ${domain}
- LOGI "Certificate revoked for domain: $domain"
+ 0)
+ show_menu
+ ;;
+ 1)
+ ssl_cert_issue
+ ssl_cert_issue_main
+ ;;
+ 2)
+ local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
+ if [ -z "$domains" ]; then
+ echo "No certificates found to revoke."
else
- echo "Invalid domain entered."
+ echo "Existing domains:"
+ echo "$domains"
+ read -rp "Please enter a domain from the list to revoke the certificate: " domain
+ if echo "$domains" | grep -qw "$domain"; then
+ ~/.acme.sh/acme.sh --revoke -d ${domain}
+ LOGI "Certificate revoked for domain: $domain"
+ else
+ echo "Invalid domain entered."
+ fi
fi
- fi
- ssl_cert_issue_main
- ;;
- 3)
- local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
- if [ -z "$domains" ]; then
- echo "No certificates found to renew."
- else
- echo "Existing domains:"
- echo "$domains"
- read -rp "Please enter a domain from the list to renew the SSL certificate: " domain
- if echo "$domains" | grep -qw "$domain"; then
- ~/.acme.sh/acme.sh --renew -d ${domain} --force
- LOGI "Certificate forcefully renewed for domain: $domain"
+ ssl_cert_issue_main
+ ;;
+ 3)
+ local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
+ if [ -z "$domains" ]; then
+ echo "No certificates found to renew."
else
- echo "Invalid domain entered."
- fi
- fi
- ssl_cert_issue_main
- ;;
- 4)
- local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
- if [ -z "$domains" ]; then
- echo "No certificates found."
- else
- echo "Existing domains and their paths:"
- for domain in $domains; do
- local cert_path="/root/cert/${domain}/fullchain.pem"
- local key_path="/root/cert/${domain}/privkey.pem"
- if [[ -f "${cert_path}" && -f "${key_path}" ]]; then
- echo -e "Domain: ${domain}"
- echo -e "\tCertificate Path: ${cert_path}"
- echo -e "\tPrivate Key Path: ${key_path}"
+ echo "Existing domains:"
+ echo "$domains"
+ read -rp "Please enter a domain from the list to renew the SSL certificate: " domain
+ if echo "$domains" | grep -qw "$domain"; then
+ ~/.acme.sh/acme.sh --renew -d ${domain} --force
+ LOGI "Certificate forcefully renewed for domain: $domain"
else
- echo -e "Domain: ${domain} - Certificate or Key missing."
+ echo "Invalid domain entered."
fi
- done
- fi
- ssl_cert_issue_main
- ;;
- 5)
- local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
- if [ -z "$domains" ]; then
- echo "No certificates found."
- else
- echo "Available domains:"
- echo "$domains"
- read -rp "Please choose a domain to set the panel paths: " domain
-
- if echo "$domains" | grep -qw "$domain"; then
- local webCertFile="/root/cert/${domain}/fullchain.pem"
- local webKeyFile="/root/cert/${domain}/privkey.pem"
-
- if [[ -f "${webCertFile}" && -f "${webKeyFile}" ]]; then
- ${xui_folder}/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile"
- echo "Panel paths set for domain: $domain"
- echo " - Certificate File: $webCertFile"
- echo " - Private Key File: $webKeyFile"
- restart
+ fi
+ ssl_cert_issue_main
+ ;;
+ 4)
+ local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
+ if [ -z "$domains" ]; then
+ echo "No certificates found."
+ else
+ echo "Existing domains and their paths:"
+ for domain in $domains; do
+ local cert_path="/root/cert/${domain}/fullchain.pem"
+ local key_path="/root/cert/${domain}/privkey.pem"
+ if [[ -f "${cert_path}" && -f "${key_path}" ]]; then
+ echo -e "Domain: ${domain}"
+ echo -e "\tCertificate Path: ${cert_path}"
+ echo -e "\tPrivate Key Path: ${key_path}"
+ else
+ echo -e "Domain: ${domain} - Certificate or Key missing."
+ fi
+ done
+ fi
+ ssl_cert_issue_main
+ ;;
+ 5)
+ local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
+ if [ -z "$domains" ]; then
+ echo "No certificates found."
+ else
+ echo "Available domains:"
+ echo "$domains"
+ read -rp "Please choose a domain to set the panel paths: " domain
+
+ if echo "$domains" | grep -qw "$domain"; then
+ local webCertFile="/root/cert/${domain}/fullchain.pem"
+ local webKeyFile="/root/cert/${domain}/privkey.pem"
+
+ if [[ -f "${webCertFile}" && -f "${webKeyFile}" ]]; then
+ ${xui_folder}/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile"
+ echo "Panel paths set for domain: $domain"
+ echo " - Certificate File: $webCertFile"
+ echo " - Private Key File: $webKeyFile"
+ restart
+ else
+ echo "Certificate or private key not found for domain: $domain."
+ fi
else
- echo "Certificate or private key not found for domain: $domain."
+ echo "Invalid domain entered."
fi
- else
- echo "Invalid domain entered."
fi
- fi
- ssl_cert_issue_main
- ;;
- 6)
- echo -e "${yellow}Let's Encrypt SSL Certificate for IP Address${plain}"
- echo -e "This will obtain a certificate for your server's IP using the shortlived profile."
- echo -e "${yellow}Certificate valid for ~6 days, auto-renews via acme.sh cron job.${plain}"
- echo -e "${yellow}Port 80 must be open and accessible from the internet.${plain}"
- confirm "Do you want to proceed?" "y"
- if [[ $? == 0 ]]; then
- ssl_cert_issue_for_ip
- fi
- ssl_cert_issue_main
- ;;
+ ssl_cert_issue_main
+ ;;
+ 6)
+ echo -e "${yellow}Let's Encrypt SSL Certificate for IP Address${plain}"
+ echo -e "This will obtain a certificate for your server's IP using the shortlived profile."
+ echo -e "${yellow}Certificate valid for ~6 days, auto-renews via acme.sh cron job.${plain}"
+ echo -e "${yellow}Port 80 must be open and accessible from the internet.${plain}"
+ confirm "Do you want to proceed?" "y"
+ if [[ $? == 0 ]]; then
+ ssl_cert_issue_for_ip
+ fi
+ ssl_cert_issue_main
+ ;;
- *)
- echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
- ssl_cert_issue_main
- ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ ssl_cert_issue_main
+ ;;
esac
}
ssl_cert_issue_for_ip() {
LOGI "Starting automatic SSL certificate generation for server IP..."
LOGI "Using Let's Encrypt shortlived profile (~6 days validity, auto-renews)"
-
+
local existing_webBasePath=$(${xui_folder}/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
local existing_port=$(${xui_folder}/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
-
+
# Get server IP
local server_ip=$(curl -s --max-time 3 https://api.ipify.org)
if [ -z "$server_ip" ]; then
server_ip=$(curl -s --max-time 3 https://4.ident.me)
fi
-
+
if [ -z "$server_ip" ]; then
LOGE "Failed to get server IP address"
return 1
fi
-
+
LOGI "Server IP detected: ${server_ip}"
-
+
# Ask for optional IPv6
local ipv6_addr=""
read -rp "Do you have an IPv6 address to include? (leave empty to skip): " ipv6_addr
- ipv6_addr="${ipv6_addr// /}" # Trim whitespace
-
+ ipv6_addr="${ipv6_addr// /}" # Trim whitespace
+
# check for acme.sh first
- if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then
+ if ! command -v ~/.acme.sh/acme.sh &> /dev/null; then
LOGI "acme.sh not found, installing..."
install_acme
if [ $? -ne 0 ]; then
@@ -1156,47 +1165,47 @@ ssl_cert_issue_for_ip() {
return 1
fi
fi
-
+
# install socat
case "${release}" in
- ubuntu | debian | armbian)
- apt-get update >/dev/null 2>&1 && apt-get install socat -y >/dev/null 2>&1
- ;;
- fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
- dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
- ;;
- centos)
- if [[ "${VERSION_ID}" =~ ^7 ]]; then
- yum -y update >/dev/null 2>&1 && yum -y install socat >/dev/null 2>&1
- else
- dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
- fi
- ;;
- arch | manjaro | parch)
- pacman -Sy --noconfirm socat >/dev/null 2>&1
- ;;
- opensuse-tumbleweed | opensuse-leap)
- zypper refresh >/dev/null 2>&1 && zypper -q install -y socat >/dev/null 2>&1
- ;;
- alpine)
- apk add socat curl openssl >/dev/null 2>&1
- ;;
- *)
- LOGW "Unsupported OS for automatic socat installation"
- ;;
+ ubuntu | debian | armbian)
+ apt-get update > /dev/null 2>&1 && apt-get install socat -y > /dev/null 2>&1
+ ;;
+ fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
+ dnf -y update > /dev/null 2>&1 && dnf -y install socat > /dev/null 2>&1
+ ;;
+ centos)
+ if [[ "${VERSION_ID}" =~ ^7 ]]; then
+ yum -y update > /dev/null 2>&1 && yum -y install socat > /dev/null 2>&1
+ else
+ dnf -y update > /dev/null 2>&1 && dnf -y install socat > /dev/null 2>&1
+ fi
+ ;;
+ arch | manjaro | parch)
+ pacman -Sy --noconfirm socat > /dev/null 2>&1
+ ;;
+ opensuse-tumbleweed | opensuse-leap)
+ zypper refresh > /dev/null 2>&1 && zypper -q install -y socat > /dev/null 2>&1
+ ;;
+ alpine)
+ apk add socat curl openssl > /dev/null 2>&1
+ ;;
+ *)
+ LOGW "Unsupported OS for automatic socat installation"
+ ;;
esac
-
+
# Create certificate directory
certPath="/root/cert/ip"
mkdir -p "$certPath"
-
+
# Build domain arguments
local domain_args="-d ${server_ip}"
if [[ -n "$ipv6_addr" ]] && is_ipv6 "$ipv6_addr"; then
domain_args="${domain_args} -d ${ipv6_addr}"
LOGI "Including IPv6 address: ${ipv6_addr}"
fi
-
+
# Choose port for HTTP-01 listener (default 80, allow override)
local WebPort=""
read -rp "Port to use for ACME HTTP-01 listener (default 80): " WebPort
@@ -1232,10 +1241,10 @@ ssl_cert_issue_for_ip() {
break
fi
done
-
+
# Reload command - restarts panel after renewal
local reloadCmd="systemctl restart x-ui 2>/dev/null || rc-service x-ui restart 2>/dev/null"
-
+
# issue the certificate for IP with shortlived profile
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt --force
~/.acme.sh/acme.sh --issue \
@@ -1246,19 +1255,19 @@ ssl_cert_issue_for_ip() {
--days 6 \
--httpport ${WebPort} \
--force
-
+
if [ $? -ne 0 ]; then
LOGE "Failed to issue certificate for IP: ${server_ip}"
LOGE "Make sure port ${WebPort} is open and the server is accessible from the internet"
# Cleanup acme.sh data for both IPv4 and IPv6 if specified
- rm -rf ~/.acme.sh/${server_ip} 2>/dev/null
- [[ -n "$ipv6_addr" ]] && rm -rf ~/.acme.sh/${ipv6_addr} 2>/dev/null
- rm -rf ${certPath} 2>/dev/null
+ rm -rf ~/.acme.sh/${server_ip} 2> /dev/null
+ [[ -n "$ipv6_addr" ]] && rm -rf ~/.acme.sh/${ipv6_addr} 2> /dev/null
+ rm -rf ${certPath} 2> /dev/null
return 1
else
LOGI "Certificate issued successfully for IP: ${server_ip}"
fi
-
+
# Install the certificate
# Note: acme.sh may report "Reload error" and exit non-zero if reloadcmd fails,
# but the cert files are still installed. We check for files instead of exit code.
@@ -1266,28 +1275,28 @@ ssl_cert_issue_for_ip() {
--key-file "${certPath}/privkey.pem" \
--fullchain-file "${certPath}/fullchain.pem" \
--reloadcmd "${reloadCmd}" 2>&1 || true
-
+
# Verify certificate files exist (don't rely on exit code - reloadcmd failure causes non-zero)
if [[ ! -f "${certPath}/fullchain.pem" || ! -f "${certPath}/privkey.pem" ]]; then
LOGE "Certificate files not found after installation"
# Cleanup acme.sh data for both IPv4 and IPv6 if specified
- rm -rf ~/.acme.sh/${server_ip} 2>/dev/null
- [[ -n "$ipv6_addr" ]] && rm -rf ~/.acme.sh/${ipv6_addr} 2>/dev/null
- rm -rf ${certPath} 2>/dev/null
+ rm -rf ~/.acme.sh/${server_ip} 2> /dev/null
+ [[ -n "$ipv6_addr" ]] && rm -rf ~/.acme.sh/${ipv6_addr} 2> /dev/null
+ rm -rf ${certPath} 2> /dev/null
return 1
fi
-
+
LOGI "Certificate files installed successfully"
-
+
# enable auto-renew
- ~/.acme.sh/acme.sh --upgrade --auto-upgrade >/dev/null 2>&1
- chmod 600 $certPath/privkey.pem 2>/dev/null
- chmod 644 $certPath/fullchain.pem 2>/dev/null
-
+ ~/.acme.sh/acme.sh --upgrade --auto-upgrade > /dev/null 2>&1
+ chmod 600 $certPath/privkey.pem 2> /dev/null
+ chmod 644 $certPath/fullchain.pem 2> /dev/null
+
# Set certificate paths for the panel
local webCertFile="${certPath}/fullchain.pem"
local webKeyFile="${certPath}/privkey.pem"
-
+
if [[ -f "$webCertFile" && -f "$webKeyFile" ]]; then
${xui_folder}/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile"
LOGI "Certificate configured for panel"
@@ -1308,7 +1317,7 @@ ssl_cert_issue() {
local existing_webBasePath=$(${xui_folder}/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
local existing_port=$(${xui_folder}/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
# check for acme.sh first
- if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then
+ if ! command -v ~/.acme.sh/acme.sh &> /dev/null; then
echo "acme.sh could not be found. we will install it"
install_acme
if [ $? -ne 0 ]; then
@@ -1319,31 +1328,31 @@ ssl_cert_issue() {
# install socat
case "${release}" in
- ubuntu | debian | armbian)
- apt-get update >/dev/null 2>&1 && apt-get install socat -y >/dev/null 2>&1
- ;;
- fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
- dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
- ;;
- centos)
- if [[ "${VERSION_ID}" =~ ^7 ]]; then
- yum -y update >/dev/null 2>&1 && yum -y install socat >/dev/null 2>&1
- else
- dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
- fi
- ;;
- arch | manjaro | parch)
- pacman -Sy --noconfirm socat >/dev/null 2>&1
- ;;
- opensuse-tumbleweed | opensuse-leap)
- zypper refresh >/dev/null 2>&1 && zypper -q install -y socat >/dev/null 2>&1
- ;;
- alpine)
- apk add socat curl openssl >/dev/null 2>&1
- ;;
- *)
- LOGW "Unsupported OS for automatic socat installation"
- ;;
+ ubuntu | debian | armbian)
+ apt-get update > /dev/null 2>&1 && apt-get install socat -y > /dev/null 2>&1
+ ;;
+ fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
+ dnf -y update > /dev/null 2>&1 && dnf -y install socat > /dev/null 2>&1
+ ;;
+ centos)
+ if [[ "${VERSION_ID}" =~ ^7 ]]; then
+ yum -y update > /dev/null 2>&1 && yum -y install socat > /dev/null 2>&1
+ else
+ dnf -y update > /dev/null 2>&1 && dnf -y install socat > /dev/null 2>&1
+ fi
+ ;;
+ arch | manjaro | parch)
+ pacman -Sy --noconfirm socat > /dev/null 2>&1
+ ;;
+ opensuse-tumbleweed | opensuse-leap)
+ zypper refresh > /dev/null 2>&1 && zypper -q install -y socat > /dev/null 2>&1
+ ;;
+ alpine)
+ apk add socat curl openssl > /dev/null 2>&1
+ ;;
+ *)
+ LOGW "Unsupported OS for automatic socat installation"
+ ;;
esac
if [ $? -ne 0 ]; then
LOGE "install socat failed, please check logs"
@@ -1356,18 +1365,18 @@ ssl_cert_issue() {
local domain=""
while true; do
read -rp "Please enter your domain name: " domain
- domain="${domain// /}" # Trim whitespace
-
+ domain="${domain// /}" # Trim whitespace
+
if [[ -z "$domain" ]]; then
LOGE "Domain name cannot be empty. Please try again."
continue
fi
-
+
if ! is_domain "$domain"; then
LOGE "Invalid domain format: ${domain}. Please enter a valid domain name."
continue
fi
-
+
break
done
LOGD "Your domain is: ${domain}, checking it..."
@@ -1375,9 +1384,9 @@ ssl_cert_issue() {
# detect existing certificate and reuse it if present
local cert_exists=0
- if ~/.acme.sh/acme.sh --list 2>/dev/null | awk '{print $1}' | grep -Fxq "${domain}"; then
+ if ~/.acme.sh/acme.sh --list 2> /dev/null | awk '{print $1}' | grep -Fxq "${domain}"; then
cert_exists=1
- local certInfo=$(~/.acme.sh/acme.sh --list 2>/dev/null | grep -F "${domain}")
+ local certInfo=$(~/.acme.sh/acme.sh --list 2> /dev/null | grep -F "${domain}")
LOGI "Existing certificate found for ${domain}, will reuse it."
[[ -n "${certInfo}" ]] && LOGI "${certInfo}"
else
@@ -1428,18 +1437,18 @@ ssl_cert_issue() {
echo -e "${green}\t0.${plain} Keep default reloadcmd"
read -rp "Choose an option: " choice
case "$choice" in
- 1)
- LOGI "Reloadcmd is: systemctl reload nginx ; x-ui restart"
- reloadCmd="systemctl reload nginx ; x-ui restart"
- ;;
- 2)
- LOGD "It's recommended to put x-ui restart at the end, so it won't raise an error if other services fails"
- read -rp "Please enter your reloadcmd (example: systemctl reload nginx ; x-ui restart): " reloadCmd
- LOGI "Your reloadcmd is: ${reloadCmd}"
- ;;
- *)
- LOGI "Keep default reloadcmd"
- ;;
+ 1)
+ LOGI "Reloadcmd is: systemctl reload nginx ; x-ui restart"
+ reloadCmd="systemctl reload nginx ; x-ui restart"
+ ;;
+ 2)
+ LOGD "It's recommended to put x-ui restart at the end, so it won't raise an error if other services fails"
+ read -rp "Please enter your reloadcmd (example: systemctl reload nginx ; x-ui restart): " reloadCmd
+ LOGI "Your reloadcmd is: ${reloadCmd}"
+ ;;
+ *)
+ LOGI "Keep default reloadcmd"
+ ;;
esac
fi
@@ -1456,7 +1465,7 @@ ssl_cert_issue() {
installWroteFiles=1
fi
- if [[ -f "/root/cert/${domain}/privkey.pem" && -f "/root/cert/${domain}/fullchain.pem" && ( ${installRc} -eq 0 || ${installWroteFiles} -eq 1 ) ]]; then
+ if [[ -f "/root/cert/${domain}/privkey.pem" && -f "/root/cert/${domain}/fullchain.pem" && (${installRc} -eq 0 || ${installWroteFiles} -eq 1) ]]; then
LOGI "Installing certificate succeeded, enabling auto renew..."
else
LOGE "Installing certificate failed, exiting."
@@ -1517,7 +1526,7 @@ ssl_cert_issue_CF() {
if [ $? -eq 0 ]; then
# Check for acme.sh first
- if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then
+ if ! command -v ~/.acme.sh/acme.sh &> /dev/null; then
echo "acme.sh could not be found. We will install it."
install_acme
if [ $? -ne 0 ]; then
@@ -1562,7 +1571,7 @@ ssl_cert_issue_CF() {
LOGI "Certificate issued successfully, Installing..."
fi
- # Install the certificate
+ # Install the certificate
certPath="/root/ce