diff options
Diffstat (limited to 'x-ui.sh')
| -rw-r--r-- | x-ui.sh | 1423 |
1 files changed, 715 insertions, 708 deletions
@@ -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
|
