#!/bin/bash ################################################################# # One-click CDN Installation Script v0.1.0 # # Written by shc (https://qing.su) # # Github link: https://github.com/Har-Kuun/OneClickCDN # # Contact me: https://t.me/hsun94 E-mail: hi@qing.su # # # # This script is distributed in the hope that it will be # # useful, but ABSOLUTELY WITHOUT ANY WARRANTY. # # # # Thank you for using this script. # ################################################################# #You can change the Traffic Server source file download link here. #Check https://www.apache.org/dyn/closer.cgi/trafficserver for the latest stable version. TS_DOWNLOAD_LINK="https://downloads.apache.org/trafficserver/trafficserver-8.1.5.tar.bz2" TS_VERSION="8.1.5" #You can enable an experimental feature: reverse proxy for any website. #Please note that this feature is kind of buggy; you might have to manually modify some mapping rules if necessary. #If you wish to turn on this feature, set the value for the variable below to ON, and use the special key in the main function to add reverse proxy instances. REVERSE_PROXY_MODE_ENABLED=OFF #By default, this script only works on Ubuntu 20, Debian 10/11, and CentOS 7/8. #You can disable the OS check switch below and tweak the code yourself to try to install it in other OS versions. #Please do note that if you choose to use this script on OS other than Ubuntu 20, Debian 10, or CentOS 7/8, you might mess up your OS. Please keep a backup of your server before installation. OS_CHECK_ENABLED=ON ######################################################################### # Functions start here. # # Do not change anything below unless you know what you are doing. # ######################################################################### function check_OS { if [ -f /etc/lsb-release ] then cat /etc/lsb-release | grep "DISTRIB_RELEASE=18." >/dev/null if [ $? = 0 ] then OS=UBUNTU18 echo "Support of Ubuntu 18 is experimental. You may get error in TLS handshakes." echo "Please consider upgrading to Ubuntu 20 (simply run \"do-release-upgrade -d\")." echo "Please tweak the OS_CHECK_ENABLED setting if you still wish to install on Ubuntu 18." echo exit 1 else cat /etc/lsb-release | grep "DISTRIB_RELEASE=20." >/dev/null if [ $? = 0 ] then OS=UBUNTU20 else say "Sorry, this script only supports Ubuntu 20 and Debian 10/11." red echo exit 1 fi fi elif [ -f /etc/debian_version ] ; then cat /etc/debian_version | grep "^10." >/dev/null if [ $? = 0 ] ; then OS=DEBIAN10 echo "Support of Debian 10 is experimental. Please report bugs." echo else cat /etc/debian_version | grep "^9." >/dev/null if [ $? = 0 ] ; then OS=DEBIAN9 echo "Support of Debian 9 is experimental. You may get error in TLS handshakes." echo "Please tweak the OS_CHECK_ENABLED setting if you still wish to install on Debian 9." echo exit 1 else cat /etc/debian_version | grep "^11." >/dev/null if [ $? = 0 ] ; then OS=DEBIAN11 echo "Support of Debian 11 is experimental. Please report bugs." echo else say "Sorry, this script only supports Ubuntu 20 and Debian 10/11." red echo exit 1 fi fi fi elif [ -f /etc/redhat-release ] ; then cat /etc/redhat-release | grep " 8." >/dev/null if [ $? = 0 ] ; then OS=CENTOS8 echo "Support of CentOS 8 is experimental. Please report bugs." echo "Please try disabling selinux or firewalld if you cannot visit your website." echo else cat /etc/redhat-release | grep " 7." >/dev/null if [ $? = 0 ] ; then OS=CENTOS7 echo "Support of CentOS 7 is experimental. Please report bugs." echo "Please try disabling selinux or firewalld if you cannot visit your website." echo else echo "Sorry, this script only supports Ubuntu 20, Debian 10/11, and CentOS 7/8." echo exit 1 fi fi else echo "Sorry, this script only supports Ubuntu 20, Debian 10/11, and CentOS 7/8." echo exit 1 fi } function check_TS { if [ -f /usr/local/bin/trafficserver ] ; then TS_INSTALLED=1 else TS_INSTALLED=0 fi } function install_TS { say @B"Starting Traffic Server installation..." green echo "..." echo "..." echo "Removing Nginx and Apache..." apt-get remove nginx apache -y echo "Installing depedencies..." apt-get update && apt-get upgrade -y apt-get install wget curl tar certbot automake libtool pkg-config libmodule-install-perl gcc g++ libssl-dev tcl-dev libpcre3-dev libcap-dev libhwloc-dev libncurses5-dev libcurl4-openssl-dev flex autotools-dev bison debhelper dh-apparmor gettext intltool-debian libbison-dev libexpat1-dev libfl-dev libsigsegv2 libsqlite3-dev m4 po-debconf tcl8.6-dev zlib1g-dev -y wget $TS_DOWNLOAD_LINK tar xjf trafficserver-${TS_VERSION}.tar.bz2 rm -f trafficserver-${TS_VERSION}.tar.bz2 cd ${current_dir}/trafficserver-${TS_VERSION} echo "Start building Traffic Server from source..." ./configure --enable-experimental-plugins if [ -f ${current_dir}/trafficserver-${TS_VERSION}/config.status ] ; then say @B"Dependencies met!" green say @B"Compiling now..." green echo else echo say "Missing dependencies." red echo "Please check log, install required dependencies, and run this script again." echo "Please also consider to report your log here https://github.com/Har-Kuun/OneClickCDN/issues so that I can fix this issue." echo "Thank you!" echo exit 1 fi make make install if [ -f /usr/local/bin/traffic_manager ] ; then echo say @B"Traffic Server successfully installed!" green echo else echo say "Traffic Server installation failed." red echo "Please check the above log for reasons." echo "Please also consider to report your log here https://github.com/Har-Kuun/OneClickCDN/issues so that I can fix this issue." echo "Thank you!" echo exit 1 fi ln -s /usr/local/etc/trafficserver /etc/trafficserver mkdir /etc/trafficserver/ssl chown nobody /etc/trafficserver/ssl chmod 0760 /etc/trafficserver/ssl cd ${current_dir} ldconfig trafficserver start echo say @B"Traffic Server successfully started!" green echo "Domain Type(CDN/RevProxy) OriginIP" > /etc/trafficserver/hostsavailable.sun # echo "trafficserver start" >> /etc/rc.local run_on_startup echo } function install_TS_CentOS { say @B"Starting Traffic Server installation..." green echo "..." echo "..." echo "Removing Nginx and Apache..." yum remove httpd nginx -y echo "Installing depedencies..." yum update -y if [ "x$OS" = "xCENTOS7" ] ; then yum install centos-release-scl -y yum install devtoolset-8 -y scl enable devtoolset-8 yum install wget curl tar openssl-devel pcre-devel tcl-devel gcc-c++ expat-devel libcap-devel hwloc ncurses-devel libcurl-devel pcre-devel tcl-devel expat-devel openssl-devel perl-ExtUtils-MakeMaker bzip2 -y yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y yum install certbot -y source /opt/rh/devtoolset-8/enable else dnf -y group install "Development Tools" dnf -y install wget curl tar openssl-devel pcre-devel tcl-devel expat-devel libcap-devel hwloc ncurses-devel bzip2 libcurl-devel pcre-devel tcl-devel expat-devel openssl-devel perl-ExtUtils-MakeMaker yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm dnf -y install certbot dnf config-manager --set-enabled PowerTools fi wget $TS_DOWNLOAD_LINK tar xjf trafficserver-${TS_VERSION}.tar.bz2 rm -f trafficserver-${TS_VERSION}.tar.bz2 cd ${current_dir}/trafficserver-${TS_VERSION} echo "Start building Traffic Server from source..." ./configure --enable-experimental-plugins if [ -f ${current_dir}/trafficserver-${TS_VERSION}/config.status ] ; then say @B"Dependencies met!" green say @B"Compiling now..." green echo else echo say "Missing dependencies." red echo "Please check log, install required dependencies, and run this script again." echo "Please also consider to report your log here https://github.com/Har-Kuun/OneClickCDN/issues so that I can fix this issue." echo "Thank you!" echo exit 1 fi make make install if [ -f /usr/local/bin/traffic_manager ] ; then echo say @B"Traffic Server successfully installed!" green echo else echo say "Traffic Server installation failed." red echo "Please check the above log for reasons." echo "Please also consider to report your log here https://github.com/Har-Kuun/OneClickCDN/issues so that I can fix this issue." echo "Thank you!" echo exit 1 fi ln -s /usr/local/etc/trafficserver /etc/trafficserver mkdir /etc/trafficserver/ssl chown nobody /etc/trafficserver/ssl chmod 0760 /etc/trafficserver/ssl cd ${current_dir} ldconfig /usr/local/bin/trafficserver start echo say @B"Traffic Server successfully started!" green echo "Domain Type(CDN/RevProxy) OriginIP" > /etc/trafficserver/hostsavailable.sun run_on_startup echo } function config_main_records { cat > /etc/trafficserver/records.config < /etc/trafficserver/cache.config <> /etc/trafficserver/records.config valid_integer=0 while [ ${valid_integer} != 1 ] do disk_cache_size= echo echo "Please specify disk cache size." echo "The unit is MB. Please type an integer only." echo "The recommended value is at least 2048." echo read disk_cache_size if ! [[ ${disk_cache_size} =~ $re ]] ; then say @B"please type an integer only." yellow else valid_integer=1 fi done if [ $disk_cache_size -gt 256 ] ; then echo say @B"Disk cache size set to ${disk_cache_size}M." green echo echo "var/trafficserver ${disk_cache_size}M" > /etc/trafficserver/storage.config else echo say @B"Disk cache size set to 256M." green echo fi } function config_cache_partitioning { echo echo "Performing disk cache partitioning..." for i in 1 2 3 4 do echo "volume=${i} scheme=http size=25%" >> /etc/trafficserver/volume.config done echo "hostname=* volume=1,2,3,4" > /etc/trafficserver/hosting.config say @B"Disk cache partitioned." green echo } function config_cache_dynamic_content { echo echo "CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic INT 1" >> /etc/trafficserver/records.config say @B"Cache rules updated!" green say @B"Traffic Server will cache dynamic content." green echo } function config_mapping_reverse_proxy { proxy_hostname=$1 origin_hostname=$2 origin_scheme=$3 echo echo "Adding mapping rules for ${proxy_hostname} as a reverse proxy of ${origin_hostname}..." echo "redirect http://${proxy_hostname}/ https://${proxy_hostname}/" >> /etc/trafficserver/remap.config echo "map https://${proxy_hostname}/ ${origin_scheme}://${origin_hostname}/" >> /etc/trafficserver/remap.config echo "reverse_map ${origin_scheme}://${origin_hostname}/ https://${proxy_hostname}/" >> /etc/trafficserver/remap.config say @B"3 rules added." green echo } function config_mapping_cdn { cdn_hostname=$1 origin_ip=$2 origin_scheme=$3 origin_port=$4 echo echo "Adding mapping rules for ${cdn_hostname}..." if [ "$origin_scheme" = "https" ] ; then echo "redirect http://${cdn_hostname}/ https://${cdn_hostname}/" >> /etc/trafficserver/remap.config echo "map https://${cdn_hostname}/ ${origin_scheme}://${origin_ip}:${origin_port}/" >> /etc/trafficserver/remap.config else echo "map http://${cdn_hostname}/ ${origin_scheme}://${origin_ip}:${origin_port}/" >> /etc/trafficserver/remap.config fi say @B"2 rules added." green echo } function add_reverse_proxy { echo echo "Please specify your proxy domain name (e.g., proxy.example.com):" read proxy_hostname_add echo "Please specify the origin website domain name (e.g., origin.example.com):" read origin_hostname_add echo "Please specify the origin website IP address (e.g., 88.88.88.88). If it has multiple IPs, any would work:" read origin_ip_add echo "Is the origin website using HTTPS or HTTP? Type 1 for HTTPS, or 2 for HTTP. If both works, then either is fine:" read isHTTPS if [ $isHTTPS = 1 ] ; then config_mapping_reverse_proxy $proxy_hostname_add $origin_hostname_add https else config_mapping_reverse_proxy $proxy_hostname_add $origin_hostname_add http fi echo "${proxy_hostname_add} RevProxy ${origin_hostname_add}" >> /etc/trafficserver/hostsavailable.sun echo "Would you like to configure SSL certificates for domain name ${proxy_hostname_add} now?" echo "We can set up SSL with your own certificates, or can issue a free Let's Encrypt SSL certificate for you, if you have already pointed your domain to this server." echo "How would you like to proceed?" echo "1: I know the absolute path to my certificate files (private key, certificate, CA chain (optional))." echo "2: I have pointed my domain name to this server, and I want a free Let's Encrypt certificate." echo "3: I forgot the path to my certificate files, so I need to go back to SSH and find them; or I do not need SSL certificate for this domain." echo "Please select 1, 2, or 3:" read choice_ssl case $choice_ssl in 1 ) config_ssl_non_le $proxy_hostname_add $origin_ip_add ;; 2 ) config_ssl_le $proxy_hostname_add $origin_ip_add ;; 3 ) config_ssl_later ;; * ) echo "Error!" exit 1 ;; esac } function add_cdn { echo echo "Please specify your website domain name (e.g., example.com):" read cdn_hostname_add echo "Please specify the origin website IP address (e.g., 88.88.88.88). If it has multiple IPs, any would work:" read origin_ip_add echo "Is the origin website using HTTPS or HTTP? Type 1 for HTTPS, or 2 for HTTP. If both works, then either is fine:" read isHTTPS if [ $isHTTPS = 1 ] ; then cdn_port=443 config_mapping_cdn $cdn_hostname_add $origin_ip_add https 443 else cdn_port=80 config_mapping_cdn $cdn_hostname_add $origin_ip_add http 80 fi echo echo "${cdn_hostname_add} CDN ${origin_ip_add}:${cdn_port}" >> /etc/trafficserver/hostsavailable.sun echo "Would you like to configure SSL certificates for domain name ${cdn_hostname_add} now?" echo echo "We can set up SSL with your own certificates, or can issue a free Let's Encrypt SSL certificate for you, if you have already pointed your domain to this server." echo "How would you like to proceed?" echo echo "1: I know the absolute path to my certificate files (private key, certificate, CA chain (optional))." echo "2: I have pointed my domain name to this server, and I want a free Let's Encrypt certificate." echo "3: I forgot the path to my certificate files, so I need to go back to SSH and find them; or I do not need SSL certificate for this domain." echo "Please select 1, 2, or 3:" read choice_ssl case $choice_ssl in 1 ) config_ssl_non_le $cdn_hostname_add $origin_ip_add ;; 2 ) config_ssl_le $cdn_hostname_add $origin_ip_add ;; 3 ) config_ssl_later ;; * ) say "Error!" red exit 1 ;; esac } function config_ssl_selection { # this function is only called from menu option 4. echo "We can set up SSL with your own certificates, or can issue a free Let's Encrypt SSL certificate for you, if you have already pointed your domain to this server." echo "How would you like to proceed?" echo echo "1: I know the absolute path to my certificate files (private key, certificate, CA chain (optional))." echo "2: I have pointed my domain name to this server, and I want a free Let's Encrypt certificate." echo "3: I forgot the path to my certificate files, so I need to go back to SSH and find them; or I do not need SSL certificate for this domain." echo "Please select 1, 2, or 3:" read choice_ssl if [ $choice_ssl = 3 ] ; then config_ssl_later else echo echo "Please specify your domain name (e.g., qing.su): " read ssl_hostname_add echo "Please specify the origin server IP address (e.g., 88.88.88.88): " read ssl_ip_add case $choice_ssl in 1 ) config_ssl_non_le $ssl_hostname_add $ssl_ip_add ;; 2 ) config_ssl_le $ssl_hostname_add $ssl_ip_add ;; 3 ) config_ssl_later ;; * ) say "Error!" red exit 1 ;; esac fi } function config_ssl_later { echo echo "No problem! Please take your time and find your certificates." echo "You can always run this script again and set up SSL certificates for your instances later." echo "Simply choose Option 4 in the main menu." /usr/local/bin/trafficserver restart echo "Thank you for using this script! Have a nice day!" exit 0 } function display_license { echo echo '*******************************************************************' echo '* One-click CDN installation script *' echo '* Version 0.1.0 *' echo '* Author: shc (Har-Kuun) https://qing.su *' echo '* https://github.com/Har-Kuun/OneClickCDN *' echo '* Thank you for using this script. E-mail: hi@qing.su *' echo '*******************************************************************' } function config_ssl_non_le { echo echo "Please specify your private key file location (e.g., /etc/certs/qing.su.key): " read priv_key_file echo "Please specify your certificate file location (e.g., /etc/certs/qing.su.crt): " read cert_file echo "Is your certificate chained? (i.e., are CA-certficates already included in your certificate file?) [Y/N]:" read is_chained if [ "x${is_chained}" != "xY" ] && [ "x${is_chained}" != "xy" ] then echo "Please specify your CA-certificates file location (e.g., /etc/certs/qing.su.ca-bundle): " read ca_cert_file fi # $1 is hostname and $2 is IP echo "Configuring SSL certificates for $2..." cp $priv_key_file /etc/trafficserver/ssl/$1.key cp $cert_file /etc/trafficserver/ssl/$1.crt if [ -f /etc/trafficserver/ssl/$1.crt ] && [ -f /etc/trafficserver/ssl/$1.key ] ; then if [ "x${is_chained}" = "xY" ] || [ "x${is_chained}" = "xy" ] ; then echo "dest_ip=$2 ssl_cert_name=$1.crt ssl_key_name=$1.key" >> /etc/trafficserver/ssl_multicert.config else cp $ca_cert_file /etc/trafficserver/ssl/$1.ca.crt echo "dest_ip=$2 ssl_cert_name=$1.crt ssl_key_name=$1.key ssl_ca_name=$1.ca.crt" >> /etc/trafficserver/ssl_multicert.config fi say @B"SSL certificates successfully configured." green echo "Origin IP: $2" echo "Private key file: /etc/trafficserver/ssl/$1.key" echo "Certificate file: /etc/trafficserver/ssl/$1.crt" if [ "x${is_chained}" != "xY" ] ; then echo "Intermediate certificate: /etc/trafficserver/ssl/$1.ca.crt" fi echo else say "SSL configuration failed!" red echo "Please check the above log." echo exit 1 fi chown -R nobody /etc/trafficserver/ssl/ chmod -R 0760 /etc/trafficserver/ssl/ echo } function config_ssl_le { origin_ip=$2 hostname_le=$1 echo echo "Starting to issue free certificate from Let's Encrypt..." echo "Please keep in mind that this feature is experimental..." echo echo "Stopping trafficserver..." echo "Please input your e-mail address: " read email_le /usr/local/bin/trafficserver stop systemctl stop trafficserver certbot certonly --standalone --agree-tos --email $email_le -d $hostname_le cp /etc/letsencrypt/live/${hostname_le}/fullchain.pem /etc/trafficserver/ssl/${hostname_le}.crt cp /etc/letsencrypt/live/${hostname_le}/privkey.pem /etc/trafficserver/ssl/${hostname_le}.key if [ -f /etc/trafficserver/ssl/${hostname_le}.key ] ; then echo "dest_ip=${origin_ip} ssl_cert_name=${hostname_le}.crt ssl_key_name=${hostname_le}.key" >> /etc/trafficserver/ssl_multicert.config say @B"SSL certificates successfully configured." green echo "Origin IP: ${origin_ip}" echo "Private key file: /etc/trafficserver/ssl/${hostname_le}.key" echo "Certificate file: /etc/trafficserver/ssl/${hostname_le}.crt" echo else say "Let's Encrypt SSL configuration failed!" red echo "Please check the above log." echo exit 1 fi chown -R nobody /etc/trafficserver/ssl/ chmod -R 0760 /etc/trafficserver/ssl/ systemctl start trafficserver /usr/local/bin/trafficserver start echo } function display_config_locations { echo echo "General configurations: /etc/trafficserver/records.config" echo "SSL: /etc/trafficserver/ssl_multicert.config" echo "Mapping rules: /etc/trafficserver/remap.config" echo "Cache rules: /etc/trafficserver/cache.config" echo "Disk cache size: /etc/trafficserver/storage.config" echo echo "Log files location: /usr/local/var/log/trafficserver" echo echo "For other configurations, check the official wiki:" echo "https://docs.trafficserver.apache.org/en/latest/admin-guide/files/records.config.en.html#configuration-variables" echo echo "Do not forget to restart Traffic Server after modifying config files." echo "Simply run: \"trafficserver restart\"" echo "Thank you. Press return key to continue." read catch_all_variable echo } function view_stats { cat /etc/trafficserver/hostsavailable.sun echo echo "Please specify the website that you would like to check stats." echo "Note: type in the Origin IP:Port of the origin website." echo "For example, 88.88.88.88:443." echo "Please specify:" read view_stats_host traffic_logstats -o $view_stats_host echo } function display_useful_commands { echo echo "View Traffic Server stats: traffic_top" echo "Start/stop/restart Traffic Server: trafficserver start/stop/restart" echo "Check whether Traffic Server is running: trafficserver status" echo "Decode via header: traffic_via '[xXxXxX]'" echo "Reload Traffic Server config files: traffic_ctl config reload" echo echo "You can always run this script again to add a CDN website, configure SSL certificates, check stats, etc." echo echo "Press return key to continue." read catch_all_variable } function enable_header_rewriter { echo echo "Setting up header rewriter..." echo "header_rewrite.so /etc/trafficserver/header_rewrite.config" > /etc/trafficserver/plugin.config touch /etc/trafficserver/header_rewrite.config say @B"Header rewriter plugin enabled!" green echo } function enable_CORS { echo echo "Setting up cross-origin resource sharing headers..." echo "rm-header Access-Control-Allow-Origin *" >> /etc/trafficserver/header_rewrite.config echo "add-header Access-Control-Allow-Origin *" >> /etc/trafficserver/header_rewrite.config say @B"CORS header added!" green echo } function customize_server_header { echo echo "How would you like your server to be called?" read cdn_server_header echo "OK. Setting server header now..." echo "cond %\{SEND_RESPONSE_HDR_HOOK\} [AND]" >> /etc/trafficserver/header_rewrite.config echo "cond %{HEADER:server} =ATS/${TS_VERSION}" >> /etc/trafficserver/header_rewrite.config echo "set-header server \"${cdn_server_header}\"" >> /etc/trafficserver/header_rewrite.config say @B"Server header set!" green echo } function clear_all_cache { echo echo "Stopping Traffic Server..." /usr/local/bin/trafficserver stop echo "Purging all cache..." traffic_server -Cclear say @B"Cache purged successfully." green echo "Starting Traffic Server..." /usr/local/bin/trafficserver start echo } function purge_single_object { echo echo "Please input the URL to the object that you'd like to purge from cache." say @B"Please INCLUDE \"http://\" or \"https://\"." yellow echo read purge_object_url read purge_object_domain_name <<< $(echo "$purge_object_url" | awk -F/ '{print $3}') read purge_object_domain_name_protocol <<< $(echo "$purge_object_url" | awk -F: '{print $1}') echo cat /etc/trafficserver/hostsavailable.sun | grep $purge_object_domain_name >/dev/null if [ $? = 0 ] ; then if [ "x$purge_object_domain_name_protocol" = "xhttp" ] ; then purge_object_result=$(curl -vX PURGE --resolve ${purge_object_domain_name}:80:127.0.0.1 ${purge_object_url} 2>&1 | grep " 200") else purge_object_result=$(curl -vX PURGE --resolve ${purge_object_domain_name}:443:127.0.0.1 ${purge_object_url} 2>&1 | grep " 200") fi if [ -n "$purge_object_result" ] ; then say @B"Object ${purge_object_url} successfully purged from cache!" green else say "Purging ${purge_object_url} failed." red say "Object not exist or already purged from cache." red fi else say "Error!" red say "Domain name $purge_object_domain_name does not exist on this server." red fi echo "Press enter to return to the main menu." read catch_all_variable echo } function purge_list_of_objects { echo echo "You are about to purge a list of objects from cache." say @B"Please specify the absolute path to the file containing the URL of objects." yellow echo "One URL per line. Please include \"http://\" or \"https://\"." read purge_object_list_file echo if [ -f $purge_object_list_file ] ; then purge_object_list_result_file="${purge_object_list_file}_result" printf "%-10s %-12s %s\n" "Type" "Status" "URL" > $purge_object_list_result_file while read line; do if [ "x$line" = "x" ] ; then continue fi read purge_object_domain_name <<< $(echo "$line" | awk -F/ '{print $3}') read purge_object_domain_name_protocol <<< $(echo "$line" | awk -F: '{print $1}') cat /etc/trafficserver/hostsavailable.sun | grep $purge_object_domain_name >/dev/null if [ $? = 0 ] ; then if [ "x$purge_object_domain_name_protocol" = "xhttp" ] ; then purge_object_result=$(curl -vX PURGE --resolve ${purge_object_domain_name}:80:127.0.0.1 ${line} 2>&1 | grep " 200") else purge_object_result=$(curl -vX PURGE --resolve ${purge_object_domain_name}:443:127.0.0.1 ${line} 2>&1 | grep " 200") fi if [ -n "$purge_object_result" ] ; then say @B"PURGE SUCCESS ${line}" green say @B"PURGE SUCCESS ${line}" green >> $purge_object_list_result_file else say "PURGE FAILURE ${line}" red say "PURGE FAILURE ${line}" red >> $purge_object_list_result_file fi else say "PURGE WRONG DOMAIN ${line}" red say "PURGE WRONG DOMAIN ${line}" red >> $purge_object_list_result_file fi done < $purge_object_list_file say @B"Completed!" green say @B"Purging results have been saved to ${purge_object_list_result_file}." green say @B"You can use \"cat ${purge_object_list_result_file}\" to display the result file." green else say "The file you specified does not exist." red say "Please check." red fi echo "Press enter to return to the main menu." read catch_all_variable echo } function push_single_object { echo echo "Please input the URL to the object that you'd like to push into cache." say @B"Please INCLUDE \"http://\" or \"https://\"." yellow echo read push_object_url read push_object_domain_name <<< $(echo "$push_object_url" | awk -F/ '{print $3}') echo cat /etc/trafficserver/hostsavailable.sun | grep $push_object_domain_name >/dev/null if [ $? = 0 ] ; then curl -s -i -o temp "$push_object_url" cat temp | grep " 200" >/dev/null if [ $? = 0 ] ; then curl -s -o /dev/null -X PUSH --data-binary temp "$push_object_url" say @B"Object $push_object_url successfully pushed into cache!" green rm -f temp else say "Pushing $push_object_url failed." red say @B"The requested URL cannot be fetched from the Origin server." red rm -f temp fi else say "Error!" red say "Domain name $push_object_domain_name does not exist on this server." red fi echo "Press enter to return to the main menu." read catch_all_variable echo } function push_list_of_objects { echo echo "You are about to push a list of objects into cache." say @B"Please specify the absolute path to the file containing the URL of objects." yellow echo "One URL per line. Please include \"http://\" or \"https://\"." read push_object_list_file echo if [ -f $push_object_list_file ] ; then push_object_list_result_file="${push_object_list_file}_result" printf "%-10s %-12s %s\n" "Type" "Status" "URL" > $push_object_list_result_file while read line; do if [ "x$line" = "x" ] ; then continue fi read push_object_domain_name <<< $(echo "$line" | awk -F/ '{print $3}') cat /etc/trafficserver/hostsavailable.sun | grep $push_object_domain_name >/dev/null if [ $? = 0 ] ; then curl -s -i -o temp "$line" cat temp | grep " 200" >/dev/null if [ $? = 0 ] ; then curl -s -o /dev/null -X PUSH --data-binary temp "$line" say @B"PUSH SUCCESS ${line}" green say @B"PUSH SUCCESS ${line}" green >> $push_object_list_result_file rm -f temp else say "PUSH FAILURE ${line}" red say "PUSH FAILURE ${line}" red >> $push_object_list_result_file rm -f temp fi else say "PUSH WRONG DOMAIN ${line}" red say "PUSH WRONG DOMAIN ${line}" red >> $push_object_list_result_file fi done < $push_object_list_file say @B"Completed!" green say @B"Pushing results have been saved to ${push_object_list_result_file}." green say @B"You can use \"cat ${push_object_list_result_file}\" to display the result file." green else say "The file you specified does not exist." red say "Please check." red fi echo "Press enter to return to the main menu." read catch_all_variable echo } function advanced_cache_control { echo echo "This submenu allows you to add/remove objects to/from cache." while [ $key != 0 ] ; do echo say @B"Advanced cache control." cyan echo "1 - Purge all cache." echo "2 - Remove a single object from cache." echo "3 - Remove a list of objects from cache." # echo "4 - Push a single object into cache. (experimental)" # echo "5 - Push a list of objects into cache. (experimental)" echo "0 - Return to main menu." echo "Please select 1/2/3/4/5/0: " read cache_menu_key case $cache_menu_key in 1 ) clear_all_cache ;; 2 ) purge_single_object ;; 3 ) purge_list_of_objects ;; 4 ) push_single_object ;; 5 ) push_list_of_objects ;; 0 ) break ;; esac done echo } function change_cdn_ip { echo echo "Please tell me your old Origin server IP. No domain name required." read old_ip echo "OK. Then tell me your new Origin server IP. No domain name required." read new_ip sed -i "s/$old_ip/$new_ip/g" /etc/trafficserver/hostsavailable.sun sed -i "s/$old_ip/$new_ip/g" /etc/trafficserver/ssl_multicert.config sed -i "s/$old_ip/$new_ip/g" /etc/trafficserver/remap.config say @B"IP changed from ${old_ip} to ${new_ip}" green echo } function reconfigure_traffic_server { echo echo "Are you sure to reconfigure Traffic Server?" echo "All previous configurations will be cleared." echo "Mapping rules and SSL certificate settings will be kept." say "Would you like to continue? [Y/N]" yellow blue read do_reconfigure_ts if [ "x$do_reconfigure_ts" = "xY" ] ; then echo echo "Configuring Traffic Server..." config_main_records echo echo "Would you like to configure cache rules automatically? [Y/N]" read do_config_cache_rules if [ "x$do_config_cache_rules" = "xY" ] || [ "x$do_config_cache_rules" = "xy" ] ; then echo "Configuring cache rules..." config_cache_rules say @B"Cache rules configured successfully." green else echo "You can configure cache rules manually at /etc/trafficserver/cache.config. Make sure to run \"trafficserver restart\" after changing the cache rules." fi echo echo "Configuring cache size..." config_cache_storage rm -f /etc/trafficserver/volume.config config_cache_partitioning rm -f /etc/trafficserver/header_rewrite.config enable_header_rewriter echo "Would you like Traffic Server to cache dynamic content? [Y/N]" read do_cache_dynamic_content if [ "x$do_cache_dynamic_content" = "xY" ] || [ "x$do_cache_dynamic_content" = "xy" ] ; then echo "Updating cache rules..." config_cache_dynamic_content else say @B"Traffic Server will not cache dynamic content!" yellow echo fi echo "Would you like to enable \"Access-Control-Allow-Origin\" header (CORS)?" echo "Please choose Y if you have no idea what it is. [Y/N]" read do_enable_CORS if [ "x$do_enable_CORS" = "xY" ] || [ "x$do_enable_CORS" = "xy" ] ; then enable_CORS else say @B"CORS not configured." yellow echo fi echo "The \"server\" header can be a short phrase, like \"shc-cdn-server 1.0.0\", or \"Traffic Server 8.0.8\"." echo "If you do not change it, the default value is \"ATS/${TS_VERSION}\"" echo "Would you like to change it? [Y/N]" read do_change_server_header if [ "x$do_change_server_header" = "xY" ] || [ "x$do_change_server_header" = "xy" ] ; then customize_server_header else say @B"Server header tag value not changed." yellow echo fi say @B"Configuration successfully finished!" green echo else echo say @B"Traffic Server not reconfigured." yellow echo fi } function renew_le_certificate { echo echo "What is the domain name that you wish to renew Let's Encrypt certificate?" read renew_le_domain echo "OK. Stopping Traffic Server..." /usr/local/bin/trafficserver stop systemctl stop trafficserver echo echo "Renewing SSL certificate for ${renew_le_domain}..." echo certbot certonly --standalone --agree-tos -d $renew_le_domain cp -f /etc/letsencrypt/live/${renew_le_domain}/fullchain.pem /etc/trafficserver/ssl/${renew_le_domain}.crt cp -f /etc/letsencrypt/live/${renew_le_domain}/privkey.pem /etc/trafficserver/ssl/${renew_le_domain}.key chown -R nobody /etc/trafficserver/ssl/ chmod -R 0760 /etc/trafficserver/ssl/ say @B"SSL certificate for ${renew_le_domain} successfully renewed." green echo echo "Starting Traffic Server..." systemctl start trafficserver /usr/local/bin/trafficserver start echo } function remove_cdn_website { echo cat /etc/trafficserver/hostsavailable.sun echo echo "Please specify the domain name of the website that you would like to remove." echo "Do NOT include \"http\" or \"https\"." echo read website_to_be_deleted echo echo "You are about to delete website ${website_to_be_deleted} from this CDN server." echo "Please note that all configurations, as well as SSL certificate files associated with this domain name will be removed." say "Are you sure to continue? [Y/N]" yellow blue read ready_to_be_deleted if [ "x$ready_to_be_deleted" = "xY" ] || [ "x$ready_to_be_deleted" = "xy" ] ; then echo echo "Removing website from server..." delete_line_in_file $website_to_be_deleted /etc/trafficserver/hostsavailable.sun delete_line_in_file $website_to_be_deleted /etc/trafficserver/remap.config delete_line_in_file $website_to_be_deleted /etc/trafficserver/ssl_multicert.config rm -f /etc/trafficserver/ssl/${website_to_be_deleted}.key rm -f /etc/trafficserver/ssl/${website_to_be_deleted}.crt if [ -f /etc/trafficserver/ssl/${website_to_be_deleted}.ca.crt ] ; then rm -f /etc/trafficserver/ssl/${website_to_be_deleted}.ca.crt fi echo say @B"Website removed!" green echo "Restarting Traffic Server..." echo /usr/local/bin/trafficserver restart echo else echo say @B"Website not removed!" yellow echo fi } function say_goodbye { echo if [ $restart_switch = 1 ] ; then echo "Restarting Traffic Server now..." /usr/local/bin/trafficserver restart fi echo echo "Thank you for using this script written by https://qing.su" echo "You can always run this script again to add a CDN website, configure SSL certificates, list current websites, check stats, etc." echo echo "Bye! Have a nice day." echo key=0 } function say { #This function is a colored version of the built-in "echo." #https://github.com/Har-Kuun/useful-shell-functions/blob/master/colored-echo.sh echo_content=$1 case $2 in black | k ) colorf=0 ;; red | r ) colorf=1 ;; green | g ) colorf=2 ;; yellow | y ) colorf=3 ;; blue | b ) colorf=4 ;; magenta | m ) colorf=5 ;; cyan | c ) colorf=6 ;; white | w ) colorf=7 ;; * ) colorf=N ;; esac case $3 in black | k ) colorb=0 ;; red | r ) colorb=1 ;; green | g ) colorb=2 ;; yellow | y ) colorb=3 ;; blue | b ) colorb=4 ;; magenta | m ) colorb=5 ;; cyan | c ) colorb=6 ;; white | w ) colorb=7 ;; * ) colorb=N ;; esac if [ "x${colorf}" != "xN" ] ; then tput setaf $colorf fi if [ "x${colorb}" != "xN" ] ; then tput setab $colorb fi printf "${echo_content}" | sed -e "s/@B/$(tput bold)/g" tput sgr 0 printf "\n" } function delete_line_in_file { delete_pattern=$1 delete_file=$2 grep -v $delete_pattern $delete_file > temp mv temp $delete_file } function run_on_startup { cat > /etc/systemd/system/trafficserver.service <