diff --git a/apps/openlitespeed/1.7.17-lsphp74/.env.sample b/apps/openlitespeed/1.7.17-lsphp74/.env.sample new file mode 100644 index 00000000..0902e645 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/.env.sample @@ -0,0 +1,6 @@ +CONTAINER_NAME="openlitespeed" +DATA_PATH="./data" +PANEL_APP_PORT_CONSOLE="40113" +PANEL_APP_PORT_HTTP="80" +PANEL_APP_PORT_HTTPS="443" +TIME_ZONE="Asia/Shanghai" diff --git a/apps/openlitespeed/1.7.17-lsphp74/data.yml b/apps/openlitespeed/1.7.17-lsphp74/data.yml new file mode 100644 index 00000000..2c19e306 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data.yml @@ -0,0 +1,40 @@ +additionalProperties: + formFields: + - default: 80 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP端口 + required: true + rule: paramPort + type: number + - default: 443 + edit: true + envKey: PANEL_APP_PORT_HTTPS + labelEn: HTTPS Port + labelZh: HTTPS端口 + required: true + rule: paramPort + type: number + - default: 40113 + edit: true + envKey: PANEL_APP_PORT_CONSOLE + labelEn: Console Port + labelZh: 控制台端口 + required: true + rule: paramPort + type: number + - default: ./data + disabled: true + envKey: DATA_PATH + labelEn: Data folder path + labelZh: 数据文件夹路径 + required: true + type: text + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + required: true + type: text diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/acme.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/acme.sh new file mode 100644 index 00000000..2804e217 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/acme.sh @@ -0,0 +1,293 @@ +#!/usr/bin/env bash +EMAIL='' +NO_EMAIL='' +DOMAIN='' +INSTALL='' +UNINSTALL='' +TYPE=0 +CONT_NAME='litespeed' +ACME_SRC='https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh' +EPACE=' ' +RENEW='' +RENEW_ALL='' +FORCE='' +REVOKE='' +REMOVE='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echo 'You will need to install acme script at the first time.' + echo 'Please run acme.sh --install --email example@example.com' + ;; + "2") + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: acme.sh --domain example.com" + echo "${EPACE}${EPACE}will auto detect and apply for both example.com and www.example.com domains." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + echo -e "\033[1m Only for the First time\033[0m" + echow '--install --email [EMAIL_ADDR]' + echo "${EPACE}${EPACE}Will install ACME with the Email provided" + echow '-r, --renew' + echo "${EPACE}${EPACE}Renew a specific domain with -D or --domain parameter if posibile. To force renew, use -f parameter." + echow '-R, --renew-all' + echo "${EPACE}${EPACE}Renew all domains if possible. To force renew, use -f parameter." + echow '-f, -F, --force' + echo "${EPACE}${EPACE}Force renew for a specific domain or all domains." + echow '-v, --revoke' + echo "${EPACE}${EPACE}Revoke a domain." + echow '-V, --remove' + echo "${EPACE}${EPACE}Remove a domain." + exit 0 + ;; + "3") + echo 'Please run acme.sh --domain [DOMAIN_NAME] to apply certificate' + exit 0 + ;; + esac +} + +check_input(){ + if [ -z "${1}" ]; then + help_message 2 + fi +} + +domain_filter(){ + if [ -z "${1}" ]; then + help_message 3 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +email_filter(){ + CKREG="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$" + if [[ "${1}" =~ ${CKREG} ]] ; then + echo -e "[O] The E-mail \033[32m${1}\033[0m is valid." + else + echo -e "[X] The E-mail \e[31m${1}\e[39m is invalid" + exit 1 + fi +} + +cert_hook(){ + echo '[Start] Adding ACME hook' + docker compose exec ${CONT_NAME} su -s /bin/bash -c "certhookctl.sh" + echo '[End] Adding ACME hook' +} + +www_domain(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + DOMAIN=$(echo ${1} | cut -c 5-) + else + DOMAIN=${1} + fi + WWW_DOMAIN="www.${DOMAIN}" +} + +domain_verify(){ + curl -Is http://${DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${DOMAIN}\033[0m is accessible." + TYPE=1 + curl -Is http://${WWW_DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${WWW_DOMAIN}\033[0m is accessible." + TYPE=2 + else + echo -e "[!] The domain name ${WWW_DOMAIN} is inaccessible." + fi + else + echo -e "[X] The domain name \e[31m${DOMAIN}\e[39m is inaccessible, please verify." + exit 1 + fi +} + +install_acme(){ + echo '[Start] Install ACME' + if [ "${1}" = 'true' ]; then + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs; \ + rm ~/acme.sh" + elif [ "${2}" != '' ]; then + email_filter "${2}" + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs --accountemail ${2}; \ + rm ~/acme.sh" + else + help_message 1 + exit 1 + fi + echo '[End] Install ACME' +} + +uninstall_acme(){ + echo '[Start] Uninstall ACME' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --uninstall" + echo '[End] Uninstall ACME' + exit 0 +} + +check_acme(){ + echo '[Start] Checking ACME' + docker compose exec ${CONT_NAME} su -c "test -f /root/.acme.sh/acme.sh" + if [ ${?} != 0 ]; then + install_acme "${NO_EMAIL}" "${EMAIL}" + cert_hook + help_message 3 + fi + echo '[End] Checking ACME' +} + +lsws_restart(){ + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +doc_root_verify(){ + if [ "${DOC_ROOT}" = '' ]; then + DOC_PATH="/var/www/vhosts/${1}/html" + else + DOC_PATH="${DOC_ROOT}" + fi + docker compose exec ${CONT_NAME} su -c "[ -e ${DOC_PATH} ]" + if [ ${?} -eq 0 ]; then + echo -e "[O] The document root folder \033[32m${DOC_PATH}\033[0m does exist." + else + echo -e "[X] The document root folder \e[31m${DOC_PATH}\e[39m does not exist!" + exit 1 + fi +} + +install_cert(){ + echo '[Start] Apply Lets Encrypt Certificate' + if [ ${TYPE} = 1 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -w ${DOC_PATH}" + elif [ ${TYPE} = 2 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -d www.${1} -w ${DOC_PATH}" + else + echo 'unknown Type!' + exit 2 + fi + echo '[End] Apply Lets Encrypt Certificate' +} + +renew_acme(){ + echo '[Start] Renew ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1} --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1}" + fi + echo '[End] Renew ACME' + lsws_restart +} + +renew_all_acme(){ + echo '[Start] Renew all ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all" + fi + echo '[End] Renew all ACME' + lsws_restart +} + +revoke(){ + echo '[Start] Revoke a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --revoke --domain ${1}" + echo '[End] Revoke a domain' + lsws_restart +} + +remove(){ + echo '[Start] Remove a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --remove --domain ${1}" + echo '[End] Remove a domain' + lsws_restart +} + +main(){ + if [ "${RENEW_ALL}" = 'true' ]; then + renew_all_acme + exit 0 + elif [ "${RENEW}" = 'true' ]; then + renew_acme ${DOMAIN} + exit 0 + elif [ "${REVOKE}" = 'true' ]; then + revoke ${DOMAIN} + exit 0 + elif [ "${REMOVE}" = 'true' ]; then + remove ${DOMAIN} + exit 0 + fi + + check_acme + domain_filter ${DOMAIN} + www_domain ${DOMAIN} + domain_verify + doc_root_verify ${DOMAIN} + install_cert ${DOMAIN} + lsws_restart +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 2 + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -[iI] | --install ) + INSTALL=true + ;; + -[uU] | --uninstall ) + UNINSTALL=true + uninstall_acme + ;; + -[fF] | --force ) + FORCE=true + ;; + -[r] | --renew ) + RENEW=true + ;; + -[R] | --renew-all ) + RENEW_ALL=true + ;; + -[v] | --revoke ) + REVOKE=true + ;; + -[V] | --remove ) + REMOVE=true + ;; + -[eE] | --email ) shift + check_input "${1}" + EMAIL="${1}" + ;; + *) + help_message 2 + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/appinstall.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/appinstall.sh new file mode 100644 index 00000000..ba67d52d --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/appinstall.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +APP_NAME='' +DOMAIN='' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --app [app_name] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstall.sh -A wordpress -D example.com" + echo "${EPACE}${EPACE}Will install WordPress CMS under the example.com domain" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +app_download(){ + docker compose exec litespeed su -c "appinstallctl.sh --app ${1} --domain ${2}" + bash bin/webadmin.sh -r + exit 0 +} + +main(){ + app_download ${APP_NAME} ${DOMAIN} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + *) + help_message + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/appinstallctl.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/appinstallctl.sh new file mode 100644 index 00000000..d79c63f1 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/appinstallctl.sh @@ -0,0 +1,660 @@ +#!/bin/bash +DEFAULT_VH_ROOT='/var/www/vhosts' +VH_DOC_ROOT='' +VHNAME='' +APP_NAME='' +DOMAIN='' +WWW_UID='' +WWW_GID='' +WP_CONST_CONF='' +PUB_IP=$(curl -s http://checkip.amazonaws.com) +DB_HOST='mysql' +PLUGINLIST="litespeed-cache.zip" +THEME='twentytwenty' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, -app [wordpress] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstallctl.sh --app wordpress --domain example.com" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +linechange(){ + LINENUM=$(grep -n "${1}" ${2} | cut -d: -f 1) + if [ -n "${LINENUM}" ] && [ "${LINENUM}" -eq "${LINENUM}" ] 2>/dev/null; then + sed -i "${LINENUM}d" ${2} + sed -i "${LINENUM}i${3}" ${2} + fi +} + +ck_ed(){ + if [ ! -f /bin/ed ]; then + echo "Install ed package.." + apt-get install ed -y > /dev/null 2>&1 + fi +} + +ck_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo "Install unzip package.." + apt-get install unzip -y > /dev/null 2>&1 + fi +} + +get_owner(){ + WWW_UID=$(stat -c "%u" ${DEFAULT_VH_ROOT}) + WWW_GID=$(stat -c "%g" ${DEFAULT_VH_ROOT}) + if [ ${WWW_UID} -eq 0 ] || [ ${WWW_GID} -eq 0 ]; then + WWW_UID=1000 + WWW_GID=1000 + echo "Set owner to ${WWW_UID}" + fi +} + +get_db_pass(){ + if [ -f ${DEFAULT_VH_ROOT}/${1}/.db_pass ]; then + SQL_DB=$(grep -i Database ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_USER=$(grep -i Username ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_PASS=$(grep -i Password ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + else + echo 'db pass file can not locate, skip wp-config pre-config.' + fi +} + +set_vh_docroot(){ + if [ "${VHNAME}" != '' ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + elif [ -d ${DEFAULT_VH_ROOT}/${1}/html ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${1}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${1}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + else + echo "${DEFAULT_VH_ROOT}/${1}/html does not exist, please add domain first! Abort!" + exit 1 + fi +} + +check_sql_native(){ + local COUNTER=0 + local LIMIT_NUM=100 + until [ "$(curl -v mysql:3306 2>&1 | grep -i 'native\|Connected')" ]; do + echo "Counter: ${COUNTER}/${LIMIT_NUM}" + COUNTER=$((COUNTER+1)) + if [ ${COUNTER} = 10 ]; then + echo '--- MySQL is starting, please wait... ---' + elif [ ${COUNTER} = ${LIMIT_NUM} ]; then + echo '--- MySQL is timeout, exit! ---' + exit 1 + fi + sleep 1 + done +} + +install_wp_plugin(){ + for PLUGIN in ${PLUGINLIST}; do + wget -q -P ${VH_DOC_ROOT}/wp-content/plugins/ https://downloads.wordpress.org/plugin/${PLUGIN} + if [ ${?} = 0 ]; then + ck_unzip + unzip -qq -o ${VH_DOC_ROOT}/wp-content/plugins/${PLUGIN} -d ${VH_DOC_ROOT}/wp-content/plugins/ + else + echo "${PLUGINLIST} FAILED to download" + fi + done + rm -f ${VH_DOC_ROOT}/wp-content/plugins/*.zip +} + +set_htaccess(){ + if [ ! -f ${VH_DOC_ROOT}/.htaccess ]; then + touch ${VH_DOC_ROOT}/.htaccess + fi + cat << EOM > ${VH_DOC_ROOT}/.htaccess +# BEGIN WordPress + +RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + +# END WordPress +EOM +} + +get_theme_name(){ + THEME_NAME=$(grep WP_DEFAULT_THEME ${VH_DOC_ROOT}/wp-includes/default-constants.php | grep -v '!' | awk -F "'" '{print $4}') + echo "${THEME_NAME}" | grep 'twenty' >/dev/null 2>&1 + if [ ${?} = 0 ]; then + THEME="${THEME_NAME}" + fi +} + +set_lscache(){ + cat << EOM > "${WP_CONST_CONF}" +; +; This is the predefined default LSCWP configuration file +; +; All the keys and values please refer \`src/const.cls.php\` +; +; Comments start with \`;\` +; +;; -------------------------------------------------- ;; +;; -------------- General ----------------- ;; +;; -------------------------------------------------- ;; +; O_AUTO_UPGRADE +auto_upgrade = false +; O_API_KEY +api_key = '' +; O_SERVER_IP +server_ip = '' +; O_NEWS +news = false +;; -------------------------------------------------- ;; +;; -------------- Cache ----------------- ;; +;; -------------------------------------------------- ;; +cache-priv = true +cache-commenter = true +cache-rest = true +cache-page_login = true +cache-favicon = true +cache-resources = true +cache-browser = false +cache-mobile = false +cache-mobile_rules = 'Mobile +Android +Silk/ +Kindle +BlackBerry +Opera Mini +Opera Mobi' +cache-exc_useragents = '' +cache-exc_cookies = '' +cache-exc_qs = '' +cache-exc_cat = '' +cache-exc_tag = '' +cache-force_uri = '' +cache-force_pub_uri = '' +cache-priv_uri = '' +cache-exc = '' +cache-exc_roles = '' +cache-drop_qs = 'fbclid +gclid +utm* +_ga' +cache-ttl_pub = 604800 +cache-ttl_priv = 1800 +cache-ttl_frontpage = 604800 +cache-ttl_feed = 604800 +; O_CACHE_TTL_REST +cache-ttl_rest = 604800 +cache-ttl_browser = 31557600 +cache-login_cookie = '' +cache-vary_group = '' +cache-ttl_status = '403 3600 +404 3600 +500 3600' +;; -------------------------------------------------- ;; +;; -------------- Purge ----------------- ;; +;; -------------------------------------------------- ;; +; O_PURGE_ON_UPGRADE +purge-upgrade = true +; O_PURGE_STALE +purge-stale = true +purge-post_all = false +purge-post_f = true +purge-post_h = true +purge-post_p = true +purge-post_pwrp = true +purge-post_a = true +purge-post_y = false +purge-post_m = true +purge-post_d = false +purge-post_t = true +purge-post_pt = true +purge-timed_urls = '' +purge-timed_urls_time = '' +purge-hook_all = 'switch_theme +wp_create_nav_menu +wp_update_nav_menu +wp_delete_nav_menu +create_term +edit_terms +delete_term +add_link +edit_link +delete_link' +;; -------------------------------------------------- ;; +;; -------------- ESI ----------------- ;; +;; -------------------------------------------------- ;; +; O_ESI +esi = false +; O_ESI_CACHE_ADMBAR +esi-cache_admbar = true +; O_ESI_CACHE_COMMFORM +esi-cache_commform = true +; O_ESI_NONCE +esi-nonce = 'stats_nonce +subscribe_nonce' +;; -------------------------------------------------- ;; +;; -------------- Utilities ----------------- ;; +;; -------------------------------------------------- ;; +util-heartbeat = true +util-instant_click = false +util-check_advcache = true +util-no_https_vary = false +;; -------------------------------------------------- ;; +;; -------------- Debug ----------------- ;; +;; -------------------------------------------------- ;; +; O_DEBUG_DISABLE_ALL +debug-disable_all = false +; O_DEBUG +debug = false +; O_DEBUG_IPS +debug-ips = '127.0.0.1' +; O_DEBUG_LEVEL +debug-level = false +; O_DEBUG_FILESIZE +debug-filesize = 3 +; O_DEBUG_COOKIE +debug-cookie = false +; O_DEBUG_COLLAPS_QS +debug-collaps_qs = false +; O_DEBUG_INC +debug-inc = '' +; O_DEBUG_EXC +debug-exc = '' +;; -------------------------------------------------- ;; +;; -------------- DB Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_DB_OPTM_REVISIONS_MAX +db_optm-revisions_max = 0 +; O_DB_OPTM_REVISIONS_AGE +db_optm-revisions_age = 0 +;; -------------------------------------------------- ;; +;; -------------- HTML Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_OPTM_CSS_MIN +optm-css_min = false +optm-css_inline_min = false +; O_OPTM_CSS_COMB +optm-css_comb = false +optm-css_comb_priority = false +; O_OPTM_CSS_HTTP2 +optm-css_http2 = false +optm-css_exc = '' +; O_OPTM_JS_MIN +optm-js_min = false +optm-js_inline_min = false +; O_OPTM_JS_COMB +optm-js_comb = false +optm-js_comb_priority = false +; O_OPTM_JS_HTTP2 +optm-js_http2 = false +; O_OPTM_EXC_JQ +optm-js_exc = '' +optm-ttl = 604800 +optm-html_min = false +optm-qs_rm = false +optm-ggfonts_rm = false +; O_OPTM_CSS_ASYNC +optm-css_async = false +; O_OPTM_CCSS_GEN +optm-ccss_gen = true +; O_OPTM_CCSS_ASYNC +optm-ccss_async = true +; O_OPTM_CSS_ASYNC_INLINE +optm-css_async_inline = true +; O_OPTM_CSS_FONT_DISPLAY +optm-css_font_display = false +; O_OPTM_JS_DEFER +optm-js_defer = false +; O_OPTM_JS_INLINE_DEFER +optm-js_inline_defer = false +optm-emoji_rm = false +optm-exc_jq = true +optm-ggfonts_async = false +optm-max_size = 2 +optm-rm_comment = false +optm-exc_roles = '' +optm-ccss_con = '' +optm-js_defer_exc = '' +; O_OPTM_DNS_PREFETCH +optm-dns_prefetch = '' +; O_OPTM_DNS_PREFETCH_CTRL +optm-dns_prefetch_ctrl = false +optm-exc = '' +; O_OPTM_CCSS_SEP_POSTTYPE +optm-ccss_sep_posttype = '' +; O_OPTM_CCSS_SEP_URI +optm-ccss_sep_uri = '' +;; -------------------------------------------------- ;; +;; -------------- Object Cache ----------------- ;; +;; -------------------------------------------------- ;; +object = true +object-kind = false +;object-host = 'localhost' +object-host = '/var/www/memcached.sock' +;object-port = 11211 +cache_object_port = '' +object-life = 360 +object-persistent = true +object-admin = true +object-transients = true +object-db_id = 0 +object-user = '' +object-pswd = '' +object-global_groups = 'users +userlogins +usermeta +user_meta +site-transient +site-options +site-lookup +blog-lookup +blog-details +rss +global-posts +blog-id-cache' +object-non_persistent_groups = 'comment +counts +plugins +wc_session_id' +;; -------------------------------------------------- ;; +;; -------------- Discussion ----------------- ;; +;; -------------------------------------------------- ;; +; O_DISCUSS_AVATAR_CACHE +discuss-avatar_cache = false +; O_DISCUSS_AVATAR_CRON +discuss-avatar_cron = false +; O_DISCUSS_AVATAR_CACHE_TTL +discuss-avatar_cache_ttl = 604800 +;; -------------------------------------------------- ;; +;; -------------- Media ----------------- ;; +;; -------------------------------------------------- ;; +; O_MEDIA_LAZY +media-lazy = false +; O_MEDIA_LAZY_PLACEHOLDER +media-lazy_placeholder = '' +; O_MEDIA_PLACEHOLDER_RESP +media-placeholder_resp = false +; O_MEDIA_PLACEHOLDER_RESP_COLOR +media-placeholder_resp_color = '#cfd4db' +; O_MEDIA_PLACEHOLDER_RESP_GENERATOR +media-placeholder_resp_generator = false +; O_MEDIA_PLACEHOLDER_RESP_SVG +media-placeholder_resp_svg = '' +; O_MEDIA_PLACEHOLDER_LQIP +media-placeholder_lqip = false +; O_MEDIA_PLACEHOLDER_LQIP_QUAL +media-placeholder_lqip_qual = 4 +; O_MEDIA_PLACEHOLDER_RESP_ASYNC +media-placeholder_resp_async = true +; O_MEDIA_IFRAME_LAZY +media-iframe_lazy = false +; O_MEDIA_LAZYJS_INLINE +media-lazyjs_inline = false +; O_MEDIA_LAZY_EXC +media-lazy_exc = '' +; O_MEDIA_LAZY_CLS_EXC +media-lazy_cls_exc = '' +; O_MEDIA_LAZY_PARENT_CLS_EXC +media-lazy_parent_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_CLS_EXC +media-iframe_lazy_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_PARENT_CLS_EXC +media-iframe_lazy_parent_cls_exc = '' +; O_MEDIA_LAZY_URI_EXC +media-lazy_uri_exc = '' +;; -------------------------------------------------- ;; +;; -------------- Image Optm ----------------- ;; +;; -------------------------------------------------- ;; +img_optm-auto = false +img_optm-cron = true +img_optm-ori = true +img_optm-rm_bkup = false +img_optm-webp = false +img_optm-lossless = false +img_optm-exif = false +img_optm-webp_replace = false +img_optm-webp_attr = 'img.src +div.data-thumb +img.data-src +div.data-large_image +img.retina_logo_url +div.data-parallax-image +video.poster' +img_optm-webp_replace_srcset = false +img_optm-jpg_quality = 82 +;; -------------------------------------------------- ;; +;; -------------- Crawler ----------------- ;; +;; -------------------------------------------------- ;; +crawler = false +crawler-inc_posts = true +crawler-inc_pages = true +crawler-inc_cats = true +crawler-inc_tags = true +crawler-exc_cpt = '' +crawler-order_links = 'date_desc' +crawler-usleep = 500 +crawler-run_duration = 400 +crawler-run_interval = 600 +crawler-crawl_interval = 302400 +crawler-threads = 3 +crawler-timeout = 30 +crawler-load_limit = 1 +; O_CRAWLER_SITEMAP +crawler-sitemap = '' +; O_CRAWLER_DROP_DOMAIN +crawler-drop_domain = true +crawler-roles = '' +crawler-cookies = '' +;; -------------------------------------------------- ;; +;; -------------- Misc ----------------- ;; +;; -------------------------------------------------- ;; +; O_MISC_HTACCESS_FRONT +misc-htaccess_front = '' +; O_MISC_HTACCESS_BACK +misc-htaccess_back = '' +; O_MISC_HEARTBEAT_FRONT +misc-heartbeat_front = false +; O_MISC_HEARTBEAT_FRONT_TTL +misc-heartbeat_front_ttl = 60 +; O_MISC_HEARTBEAT_BACK +misc-heartbeat_back = false +; O_MISC_HEARTBEAT_BACK_TTL +misc-heartbeat_back_ttl = 60 +; O_MISC_HEARTBEAT_EDITOR +misc-heartbeat_editor = false +; O_MISC_HEARTBEAT_EDITOR_TTL +misc-heartbeat_editor_ttl = 15 +;; -------------------------------------------------- ;; +;; -------------- CDN ----------------- ;; +;; -------------------------------------------------- ;; +cdn = false +cdn-ori = '' +cdn-ori_dir = '' +cdn-exc = '' +cdn-remote_jq = false +cdn-quic = false +cdn-quic_email = '' +cdn-quic_key = '' +cdn-cloudflare = false +cdn-cloudflare_email = '' +cdn-cloudflare_key = '' +cdn-cloudflare_name = '' +cdn-cloudflare_zone = '' +; \`cdn-mapping\` needs to be put in the end with a section tag +;; -------------------------------------------------- ;; +;; -------------- CDN 2 ----------------- ;; +;; -------------------------------------------------- ;; +; <------------ CDN Mapping Example BEGIN --------------------> +; Need to keep the section tag \`[cdn-mapping]\` before list. +; +; NOTE 1) Need to set all child options to make all resources to be replaced without missing. +; NOTE 2) \`url[n]\` option must have to enable the row setting of \`n\`. +; NOTE 3) This section needs to be put in the end of this .ini file +; +; To enable the 2nd mapping record by default, please remove the \`;;\` in the related lines. +[cdn-mapping] +url[0] = '' +inc_js[0] = true +inc_css[0] = true +inc_img[0] = true +filetype[0] = '.aac +.css +.eot +.gif +.jpeg +.js +.jpg +.less +.mp3 +.mp4 +.ogg +.otf +.pdf +.png +.svg +.ttf +.woff' +;;url[1] = 'https://2nd_CDN_url.com/' +;;filetype[1] = '.webm' +; <------------ CDN Mapping Example END ------------------> +EOM + + THEME_PATH="${VH_DOC_ROOT}/wp-content/themes/${THEME}" + if [ ! -f ${THEME_PATH}/functions.php ]; then + cat >> "${THEME_PATH}/functions.php" <>/dev/null 2>&1 +2i +require_once( WP_CONTENT_DIR.'/../wp-admin/includes/plugin.php' ); +\$path = 'litespeed-cache/litespeed-cache.php' ; +if (!is_plugin_active( \$path )) { + activate_plugin( \$path ) ; + rename( __FILE__ . '.bk', __FILE__ ); +} +. +w +q +END + fi +} + +preinstall_wordpress(){ + if [ "${VHNAME}" != '' ]; then + get_db_pass ${VHNAME} + else + get_db_pass ${DOMAIN} + fi + if [ ! -f ${VH_DOC_ROOT}/wp-config.php ] && [ -f ${VH_DOC_ROOT}/wp-config-sample.php ]; then + cp ${VH_DOC_ROOT}/wp-config-sample.php ${VH_DOC_ROOT}/wp-config.php + NEWDBPWD="define('DB_PASSWORD', '${SQL_PASS}');" + linechange 'DB_PASSWORD' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_USER', '${SQL_USER}');" + linechange 'DB_USER' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_NAME', '${SQL_DB}');" + linechange 'DB_NAME' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + #NEWDBPWD="define('DB_HOST', '${PUB_IP}');" + NEWDBPWD="define('DB_HOST', '${DB_HOST}');" + linechange 'DB_HOST' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + elif [ -f ${VH_DOC_ROOT}/wp-config.php ]; then + echo "${VH_DOC_ROOT}/wp-config.php already exist, exit !" + exit 1 + else + echo 'Skip!' + exit 2 + fi +} + +app_wordpress_dl(){ + if [ ! -f "${VH_DOC_ROOT}/wp-config.php" ] && [ ! -f "${VH_DOC_ROOT}/wp-config-sample.php" ]; then + wp core download \ + --allow-root \ + --quiet + else + echo 'wordpress already exist, abort!' + exit 1 + fi +} + +change_owner(){ + if [ "${VHNAME}" != '' ]; then + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${VHNAME} + else + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${DOMAIN} + fi +} + +main(){ + set_vh_docroot ${DOMAIN} + get_owner + cd ${VH_DOC_ROOT} + if [ "${APP_NAME}" = 'wordpress' ] || [ "${APP_NAME}" = 'wp' ]; then + check_sql_native + app_wordpress_dl + preinstall_wordpress + install_wp_plugin + set_htaccess + get_theme_name + set_lscache + change_owner + exit 0 + else + echo "APP: ${APP_NAME} not support, exit!" + exit 1 + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -vhname | --vhname) shift + VHNAME="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/certhookctl.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/certhookctl.sh new file mode 100644 index 00000000..18be0965 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/certhookctl.sh @@ -0,0 +1,18 @@ +#!/bin/bash +BOTCRON='/var/spool/cron/crontabs/root' + +cert_hook(){ + grep 'acme' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + grep 'lswsctrl' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + echo 'Hook already exist, skip!' + else + sed -i 's/--cron/--cron --renew-hook "\/usr\/local\/lsws\/bin\/lswsctrl restart"/g' ${BOTCRON} + fi + else + echo "[X] ${BOTCRON} does not exist, please check it later!" + fi +} + +cert_hook \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/domainctl.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/domainctl.sh new file mode 100644 index 00000000..75539ef0 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/domainctl.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +CK_RESULT='' +LSDIR='/usr/local/lsws' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --add [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will add domain to listener and creat a virtual host from template" + echow '-D, --del [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will delete domain from listener" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help." +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +dot_escape(){ + ESCAPE=$(echo ${1} | sed 's/\./\\./g') +} + +check_duplicate(){ + CK_RESULT=$(grep -E "${1}" ${2}) +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 ${1} ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +check_www(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + echo 'www domain shoudnt be passed!' + exit 1 + fi +} + +www_domain(){ + check_www ${1} + WWW_DOMAIN=$(echo www.${1}) +} + +add_ls_domain(){ + fst_match_line 'docker.xml' ${LS_HTTPD_CONF} + NEWNUM=$((FIRST_LINE_NUM+2)) + sed -i "${NEWNUM}i \ \ \ \ \ \ \n \ \ \ \ \ \ \ ${DOMAIN}\n \ \ \ \ \ \ \ ${DOMAIN},${WWW_DOMAIN}\n \ \ \ \ \ \ " ${LS_HTTPD_CONF} +} + +add_ols_domain(){ + perl -0777 -p -i -e 's/(vhTemplate docker \{[^}]+)\}*(^.*listeners.*$)/\1$2 + member '${DOMAIN}' { + vhDomain '${DOMAIN},${WWW_DOMAIN}' + }/gmi' ${OLS_HTTPD_CONF} +} + +add_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + www_domain ${1} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + add_ls_domain + add_ols_domain +} + +del_ls_domain(){ + fst_match_line "*${1}" ${LS_HTTPD_CONF} + FIRST_LINE_NUM=$((FIRST_LINE_NUM-1)) + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} +} + +del_ols_domain(){ + fst_match_line ${1} ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} +} + +del_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + del_ls_domain ${1} + del_ols_domain ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/owaspctl.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/owaspctl.sh new file mode 100644 index 00000000..72fd8e59 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/owaspctl.sh @@ -0,0 +1,236 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +OWASP_DIR="${LSDIR}/conf/owasp" +RULE_FILE='modsec_includes.conf' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' +OWASP_V='3.3.4' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-E, --enable' + echo "${EPACE}${EPACE}Will Enable mod_secure module with latest OWASP version of rules" + echow '-D, --disable' + echo "${EPACE}${EPACE}Will Disable mod_secure module with latest OWASP version of rules" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +mk_owasp_dir(){ + if [ -d ${OWASP_DIR} ] ; then + rm -rf ${OWASP_DIR} + fi + mkdir -p ${OWASP_DIR} + if [ ${?} -ne 0 ] ; then + echo "Unable to create directory: ${OWASP_DIR}, exit!" + exit 1 + fi +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 "${1}" ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +enable_ols_modsec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "Already configured for modsecurity." + else + echo 'Enable modsecurity' + sed -i "s=module cache=module mod_security {\nmodsecurity on\ + \nmodsecurity_rules \`\nSecRuleEngine On\n\`\nmodsecurity_rules_file \ + ${OWASP_DIR}/${RULE_FILE}\n ls_enabled 1\n}\ + \n\nmodule cache=" ${OLS_HTTPD_CONF} + fi +} + +enable_ls_modsec(){ + grep '1' ${LS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "LSWS already configured for modsecurity" + else + echo 'Enable modsecurity' + sed -i \ + "s=0=1=" ${LS_HTTPD_CONF} + sed -i \ + "s==\n\ + \n\ + ModSec\n\ + 1\n\ + include ${OWASP_DIR}/modsec_includes.conf\n\ + =" ${LS_HTTPD_CONF} + fi +} + +enable_modsec(){ + if [ "${LSV}" = 'lsws' ]; then + enable_ls_modsec + elif [ "${LSV}" = 'openlitespeed' ]; then + enable_ols_modsec + fi +} + +disable_ols_modesec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo 'Disable modsecurity' + fst_match_line 'module mod_security' ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} + else + echo 'Already disabled for modsecurity' + fi +} + +disable_ls_modesec(){ + grep '0' ${LS_HTTPD_CONF} + if [ ${?} -eq 0 ] ; then + echo 'Already disabled for modsecurity' + else + echo 'Disable modsecurity' + sed -i \ + "s=1=0=" ${LS_HTTPD_CONF} + fst_match_line 'censorshipRuleSet' ${LS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '/censorshipRuleSet' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} + fi +} + +disable_modsec(){ + check_lsv + if [ "${LSV}" = 'lsws' ]; then + disable_ls_modesec + elif [ "${LSV}" = 'openlitespeed' ]; then + disable_ols_modesec + fi +} + +install_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo 'Install Unzip' + apt update >/dev/null 2>&1 + apt-get install unzip -y >/dev/null 2>&1 + fi +} + +install_owasp(){ + cd ${OWASP_DIR} + echo 'Download OWASP rules' + wget -q https://github.com/coreruleset/coreruleset/archive/refs/tags/v${OWASP_V}.zip + unzip -qq v${OWASP_V}.zip + rm -f v${OWASP_V}.zip + mv coreruleset-* owasp-modsecurity-crs +} + +configure_owasp(){ + echo 'Config OWASP rules.' + cd ${OWASP_DIR} + echo "include modsecurity.conf +include owasp-modsecurity-crs/crs-setup.conf +include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf +include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf +include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf +include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf +include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf +include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf +include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf +include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf +include owasp-modsecurity-crs/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf +include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf +include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf +include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf +include owasp-modsecurity-crs/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf +include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf +include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf +include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf +include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf +include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf +include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf">modsec_includes.conf + echo "SecRuleEngine On">modsecurity.conf + cd ${OWASP_DIR}/owasp-modsecurity-crs + if [ -f crs-setup.conf.example ]; then + mv crs-setup.conf.example crs-setup.conf + fi + cd ${OWASP_DIR}/owasp-modsecurity-crs/rules + if [ -f REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example ]; then + mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf + fi + if [ -f RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example ]; then + mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf + fi +} + +main_owasp(){ + mk_owasp_dir + install_unzip + install_owasp + configure_owasp + check_lsv + enable_modsec +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[eE] | -enable | --enable) + main_owasp + ;; + -[dD] | -disable | --disable) + disable_modsec + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/serialctl.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/serialctl.sh new file mode 100644 index 00000000..42e312dc --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/container/serialctl.sh @@ -0,0 +1,84 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply and register the serial to LSWS." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +backup_old(){ + if [ -f ${1} ] && [ ! -f ${1}_old ]; then + mv ${1} ${1}_old + fi +} + +detect_ols(){ + if [ -e ${LSDIR}/bin/openlitespeed ]; then + echo '[X] Detect OpenLiteSpeed, abort!' + exit 1 + fi +} + +apply_serial(){ + detect_ols + check_input ${1} + echo ${1} | grep -i 'trial' >/dev/null + if [ ${?} = 0 ]; then + echo 'Apply Trial License' + if [ ! -e ${LSDIR}/conf/serial.no ] && [ ! -e ${LSDIR}/conf/license.key ]; then + rm -f ${LSDIR}/conf/trial.key* + wget -P ${LSDIR}/conf -q http://license.litespeedtech.com/reseller/trial.key + echo 'Apply trial finished' + else + echo "Please backup and remove your existing license, apply abort!" + exit 1 + fi + else + echo "Apply Serial number: ${1}" + backup_old ${LSDIR}/conf/serial.no + backup_old ${LSDIR}/conf/license.key + backup_old ${LSDIR}/conf/trial.key + echo "${1}" > ${LSDIR}/conf/serial.no + ${LSDIR}/bin/lshttpd -r + if [ -f ${LSDIR}/conf/license.key ]; then + echo '[O] Apply success' + else + echo '[X] Apply failed, please check!' + exit 1 + fi + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[sS] | -serial | --serial) shift + apply_serial "${1}" + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/database.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/database.sh new file mode 100644 index 00000000..ec1462d4 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/database.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +source .env + +DOMAIN='' +SQL_DB='' +SQL_USER='' +SQL_PASS='' +ANY="'%'" +SET_OK=0 +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com" + echo "${EPACE}${EPACE}Will auto generate Database/username/password for the domain" + echow '-D, --domain [DOMAIN_NAME] -U, --user [xxx] -P, --password [xxx] -DB, --database [xxx]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com -U USERNAME -P PASSWORD -DB DATABASENAME" + echo "${EPACE}${EPACE}Will create Database/username/password by given" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +specify_name(){ + check_input ${SQL_USER} + check_input ${SQL_PASS} + check_input ${SQL_DB} +} + +auto_name(){ + SQL_DB="${TRANSNAME}" + SQL_USER="${TRANSNAME}" + SQL_PASS="'${RANDOM_PASS}'" +} + +gen_pass(){ + RANDOM_PASS="$(openssl rand -base64 12)" +} + +trans_name(){ + TRANSNAME=$(echo ${1} | tr -d '.&&-') +} + +display_credential(){ + if [ ${SET_OK} = 0 ]; then + echo "Database: ${SQL_DB}" + echo "Username: ${SQL_USER}" + echo "Password: $(echo ${SQL_PASS} | tr -d "'")" + fi +} + +store_credential(){ + if [ -d "./sites/${1}" ]; then + if [ -f ./sites/${1}/.db_pass ]; then + mv ./sites/${1}/.db_pass ./sites/${1}/.db_pass.bk + fi + cat > "./sites/${1}/.db_pass" << EOT +"Database":"${SQL_DB}" +"Username":"${SQL_USER}" +"Password":"$(echo ${SQL_PASS} | tr -d "'")" +EOT + else + echo "./sites/${1} not found, abort credential store!" + fi +} + +check_db_access(){ + docker compose exec -T mysql su -c "mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e 'status'" >/dev/null 2>&1 + if [ ${?} != 0 ]; then + echo '[X] DB access failed, please check!' + exit 1 + fi +} + +check_db_exist(){ + docker compose exec -T mysql su -c "test -e /var/lib/mysql/${1}" + if [ ${?} = 0 ]; then + echo "Database ${1} already exist, skip DB creation!" + exit 0 + fi +} + +db_setup(){ + docker compose exec -T mysql su -c 'mysql -uroot -p${MYSQL_ROOT_PASSWORD} \ + -e "CREATE DATABASE '${SQL_DB}';" \ + -e "GRANT ALL PRIVILEGES ON '${SQL_DB}'.* TO '${SQL_USER}'@'${ANY}' IDENTIFIED BY '${SQL_PASS}';" \ + -e "FLUSH PRIVILEGES;"' + SET_OK=${?} +} + +auto_setup_main(){ + check_input ${DOMAIN} + gen_pass + trans_name ${DOMAIN} + auto_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +specify_setup_main(){ + specify_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +main(){ + if [ "${SQL_USER}" != '' ] && [ "${SQL_PASS}" != '' ] && [ "${SQL_DB}" != '' ]; then + specify_setup_main + else + auto_setup_main + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[dD] | -domain| --domain) shift + DOMAIN="${1}" + ;; + -[uU] | -user | --user) shift + SQL_USER="${1}" + ;; + -[pP] | -password| --password) shift + SQL_PASS="'${1}'" + ;; + -db | -DB | -database| --database) shift + SQL_DB="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/demosite.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/demosite.sh new file mode 100644 index 00000000..91474647 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/demosite.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +source .env +APP_NAME='wordpress' +CONT_NAME='litespeed' +DOC_FD='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echow "Script will get 'DOMAIN' and 'database' info from .env file, then auto setup virtual host and the wordpress site for you." + exit 0 + ;; + "2") + echow 'Service finished, enjoy your accelarated LiteSpeed server!' + ;; + esac +} + +domain_filter(){ + if [ ! -n "${DOMAIN}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +gen_root_fd(){ + DOC_FD="./sites/${1}/" + if [ -d "./sites/${1}" ]; then + echo -e "[O] The root folder \033[32m${DOC_FD}\033[0m exist." + else + echo "Creating - document root." + bash bin/domain.sh -add ${1} + echo "Finished - document root." + fi +} + +create_db(){ + if [ ! -n "${MYSQL_DATABASE}" ] || [ ! -n "${MYSQL_USER}" ] || [ ! -n "${MYSQL_PASSWORD}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + else + bash bin/database.sh -D ${1} -U ${MYSQL_USER} -P ${MYSQL_PASSWORD} -DB ${MYSQL_DATABASE} + fi +} + +store_credential(){ + if [ -f ${DOC_FD}/.db_pass ]; then + echo '[O] db file exist!' + else + echo 'Storing database parameter' + cat > "${DOC_FD}/.db_pass" << EOT +"Database":"${MYSQL_DATABASE}" +"Username":"${MYSQL_USER}" +"Password":"$(echo ${MYSQL_PASSWORD} | tr -d "'")" +EOT + fi +} + +app_download(){ + docker compose exec -T ${CONT_NAME} su -c "appinstallctl.sh --app ${1} --domain ${2}" +} + +lsws_restart(){ + bash bin/webadmin.sh -r +} + +main(){ + domain_filter ${DOMAIN} + gen_root_fd ${DOMAIN} + create_db ${DOMAIN} + store_credential + app_download ${APP_NAME} ${DOMAIN} + lsws_restart + help_message 2 +} + +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 1 + ;; + *) + help_message 1 + ;; + esac + shift +done +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/list-flagged-files.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/list-flagged-files.sh new file mode 100644 index 00000000..bde4f25f --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/list-flagged-files.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +git ls-files -v|grep '^S' diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/no-skip-worktree-conf.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/no-skip-worktree-conf.sh new file mode 100644 index 00000000..9bf83e7c --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/no-skip-worktree-conf.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --no-skip-worktree" \; diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/skip-worktree-conf.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/skip-worktree-conf.sh new file mode 100644 index 00000000..18b16184 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/dev/skip-worktree-conf.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --skip-worktree" \; + diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/domain.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/domain.sh new file mode 100644 index 00000000..d99dca40 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/domain.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow "-A, --add [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -A example.com, will add the domain to Listener and auto create a new virtual host." + echow "-D, --del [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -D example.com, will delete the domain from Listener." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +add_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --add ${1}" + if [ ! -d "./sites/${1}" ]; then + mkdir -p ./sites/${1}/{html,logs,certs} + fi + bash bin/webadmin.sh -r +} + +del_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --del ${1}" + bash bin/webadmin.sh -r +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done + \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/bin/webadmin.sh b/apps/openlitespeed/1.7.17-lsphp74/data/bin/webadmin.sh new file mode 100644 index 00000000..18e108ec --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/bin/webadmin.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '[Enter Your PASSWORD]' + echo "${EPACE}${EPACE}Example: webadmin.sh MY_SECURE_PASS, to update web admin password immediatly." + echow '-R, --restart' + echo "${EPACE}${EPACE}Will gracefully restart LiteSpeed Web Server." + echow '-M, --mod-secure [enable|disable]' + echo "${EPACE}${EPACE}Example: webadmin.sh -M enable, will enable and apply Mod_Secure OWASP rules on server" + echow '-U, --upgrade' + echo "${EPACE}${EPACE}Will upgrade web server to latest stable version" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply your serial number to LiteSpeed Web Server." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +lsws_restart(){ + docker compose exec -T ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +apply_serial(){ + docker compose exec ${CONT_NAME} su -c "serialctl.sh --serial ${1}" + lsws_restart +} + +mod_secure(){ + if [ "${1}" = 'enable' ] || [ "${1}" = 'Enable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --enable" + lsws_restart + elif [ "${1}" = 'disable' ] || [ "${1}" = 'Disable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --disable" + lsws_restart + else + help_message + fi +} + +ls_upgrade(){ + echo 'Upgrade web server to latest stable version.' + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/admin/misc/lsup.sh 2>/dev/null' +} + +set_web_admin(){ + echo 'Update web admin password.' + local LSADPATH='/usr/local/lsws/admin' + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c \ + 'if [ -e /usr/local/lsws/admin/fcgi-bin/admin_php ]; then \ + echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + else echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php5 -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + fi'; +} + +main(){ + set_web_admin ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[rR] | -restart | --restart) + lsws_restart + ;; + -M | -mode-secure | --mod-secure) shift + mod_secure ${1} + ;; + -lsup | --lsup | --upgrade | -U) shift + ls_upgrade + ;; + -[sS] | -serial | --serial) shift + apply_serial ${1} + ;; + *) + main ${1} + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp74/data/sites/.gitignore b/apps/openlitespeed/1.7.17-lsphp74/data/sites/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/data/sites/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/apps/openlitespeed/1.7.17-lsphp74/docker-compose.yml b/apps/openlitespeed/1.7.17-lsphp74/docker-compose.yml new file mode 100644 index 00000000..0a5bef3c --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp74/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' +services: + litespeed: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + logging: + driver: none + volumes: + - ${DATA_PATH}/lsws/conf:/usr/local/lsws/conf + - ${DATA_PATH}/lsws/admin-conf:/usr/local/lsws/admin/conf + - ${DATA_PATH}/bin/container:/usr/local/bin + - ${DATA_PATH}/sites:/var/www/vhosts/ + - ${DATA_PATH}/acme:/root/.acme.sh/ + - ${DATA_PATH}/logs:/usr/local/lsws/logs/ + ports: + - "${PANEL_APP_PORT_HTTP}:80" + - "${PANEL_APP_PORT_HTTPS}:443" + - "${PANEL_APP_PORT_HTTPS}:443/udp" + - "${PANEL_APP_PORT_CONSOLE}:7080" + environment: + - TZ=${TIME_ZONE} + image: litespeedtech/openlitespeed:1.7.17-lsphp74 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/openlitespeed/1.7.17-lsphp81/.env.sample b/apps/openlitespeed/1.7.17-lsphp81/.env.sample new file mode 100644 index 00000000..0902e645 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/.env.sample @@ -0,0 +1,6 @@ +CONTAINER_NAME="openlitespeed" +DATA_PATH="./data" +PANEL_APP_PORT_CONSOLE="40113" +PANEL_APP_PORT_HTTP="80" +PANEL_APP_PORT_HTTPS="443" +TIME_ZONE="Asia/Shanghai" diff --git a/apps/openlitespeed/1.7.17-lsphp81/data.yml b/apps/openlitespeed/1.7.17-lsphp81/data.yml new file mode 100644 index 00000000..2c19e306 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data.yml @@ -0,0 +1,40 @@ +additionalProperties: + formFields: + - default: 80 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP端口 + required: true + rule: paramPort + type: number + - default: 443 + edit: true + envKey: PANEL_APP_PORT_HTTPS + labelEn: HTTPS Port + labelZh: HTTPS端口 + required: true + rule: paramPort + type: number + - default: 40113 + edit: true + envKey: PANEL_APP_PORT_CONSOLE + labelEn: Console Port + labelZh: 控制台端口 + required: true + rule: paramPort + type: number + - default: ./data + disabled: true + envKey: DATA_PATH + labelEn: Data folder path + labelZh: 数据文件夹路径 + required: true + type: text + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + required: true + type: text diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/acme.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/acme.sh new file mode 100644 index 00000000..2804e217 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/acme.sh @@ -0,0 +1,293 @@ +#!/usr/bin/env bash +EMAIL='' +NO_EMAIL='' +DOMAIN='' +INSTALL='' +UNINSTALL='' +TYPE=0 +CONT_NAME='litespeed' +ACME_SRC='https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh' +EPACE=' ' +RENEW='' +RENEW_ALL='' +FORCE='' +REVOKE='' +REMOVE='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echo 'You will need to install acme script at the first time.' + echo 'Please run acme.sh --install --email example@example.com' + ;; + "2") + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: acme.sh --domain example.com" + echo "${EPACE}${EPACE}will auto detect and apply for both example.com and www.example.com domains." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + echo -e "\033[1m Only for the First time\033[0m" + echow '--install --email [EMAIL_ADDR]' + echo "${EPACE}${EPACE}Will install ACME with the Email provided" + echow '-r, --renew' + echo "${EPACE}${EPACE}Renew a specific domain with -D or --domain parameter if posibile. To force renew, use -f parameter." + echow '-R, --renew-all' + echo "${EPACE}${EPACE}Renew all domains if possible. To force renew, use -f parameter." + echow '-f, -F, --force' + echo "${EPACE}${EPACE}Force renew for a specific domain or all domains." + echow '-v, --revoke' + echo "${EPACE}${EPACE}Revoke a domain." + echow '-V, --remove' + echo "${EPACE}${EPACE}Remove a domain." + exit 0 + ;; + "3") + echo 'Please run acme.sh --domain [DOMAIN_NAME] to apply certificate' + exit 0 + ;; + esac +} + +check_input(){ + if [ -z "${1}" ]; then + help_message 2 + fi +} + +domain_filter(){ + if [ -z "${1}" ]; then + help_message 3 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +email_filter(){ + CKREG="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$" + if [[ "${1}" =~ ${CKREG} ]] ; then + echo -e "[O] The E-mail \033[32m${1}\033[0m is valid." + else + echo -e "[X] The E-mail \e[31m${1}\e[39m is invalid" + exit 1 + fi +} + +cert_hook(){ + echo '[Start] Adding ACME hook' + docker compose exec ${CONT_NAME} su -s /bin/bash -c "certhookctl.sh" + echo '[End] Adding ACME hook' +} + +www_domain(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + DOMAIN=$(echo ${1} | cut -c 5-) + else + DOMAIN=${1} + fi + WWW_DOMAIN="www.${DOMAIN}" +} + +domain_verify(){ + curl -Is http://${DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${DOMAIN}\033[0m is accessible." + TYPE=1 + curl -Is http://${WWW_DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${WWW_DOMAIN}\033[0m is accessible." + TYPE=2 + else + echo -e "[!] The domain name ${WWW_DOMAIN} is inaccessible." + fi + else + echo -e "[X] The domain name \e[31m${DOMAIN}\e[39m is inaccessible, please verify." + exit 1 + fi +} + +install_acme(){ + echo '[Start] Install ACME' + if [ "${1}" = 'true' ]; then + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs; \ + rm ~/acme.sh" + elif [ "${2}" != '' ]; then + email_filter "${2}" + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs --accountemail ${2}; \ + rm ~/acme.sh" + else + help_message 1 + exit 1 + fi + echo '[End] Install ACME' +} + +uninstall_acme(){ + echo '[Start] Uninstall ACME' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --uninstall" + echo '[End] Uninstall ACME' + exit 0 +} + +check_acme(){ + echo '[Start] Checking ACME' + docker compose exec ${CONT_NAME} su -c "test -f /root/.acme.sh/acme.sh" + if [ ${?} != 0 ]; then + install_acme "${NO_EMAIL}" "${EMAIL}" + cert_hook + help_message 3 + fi + echo '[End] Checking ACME' +} + +lsws_restart(){ + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +doc_root_verify(){ + if [ "${DOC_ROOT}" = '' ]; then + DOC_PATH="/var/www/vhosts/${1}/html" + else + DOC_PATH="${DOC_ROOT}" + fi + docker compose exec ${CONT_NAME} su -c "[ -e ${DOC_PATH} ]" + if [ ${?} -eq 0 ]; then + echo -e "[O] The document root folder \033[32m${DOC_PATH}\033[0m does exist." + else + echo -e "[X] The document root folder \e[31m${DOC_PATH}\e[39m does not exist!" + exit 1 + fi +} + +install_cert(){ + echo '[Start] Apply Lets Encrypt Certificate' + if [ ${TYPE} = 1 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -w ${DOC_PATH}" + elif [ ${TYPE} = 2 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -d www.${1} -w ${DOC_PATH}" + else + echo 'unknown Type!' + exit 2 + fi + echo '[End] Apply Lets Encrypt Certificate' +} + +renew_acme(){ + echo '[Start] Renew ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1} --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1}" + fi + echo '[End] Renew ACME' + lsws_restart +} + +renew_all_acme(){ + echo '[Start] Renew all ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all" + fi + echo '[End] Renew all ACME' + lsws_restart +} + +revoke(){ + echo '[Start] Revoke a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --revoke --domain ${1}" + echo '[End] Revoke a domain' + lsws_restart +} + +remove(){ + echo '[Start] Remove a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --remove --domain ${1}" + echo '[End] Remove a domain' + lsws_restart +} + +main(){ + if [ "${RENEW_ALL}" = 'true' ]; then + renew_all_acme + exit 0 + elif [ "${RENEW}" = 'true' ]; then + renew_acme ${DOMAIN} + exit 0 + elif [ "${REVOKE}" = 'true' ]; then + revoke ${DOMAIN} + exit 0 + elif [ "${REMOVE}" = 'true' ]; then + remove ${DOMAIN} + exit 0 + fi + + check_acme + domain_filter ${DOMAIN} + www_domain ${DOMAIN} + domain_verify + doc_root_verify ${DOMAIN} + install_cert ${DOMAIN} + lsws_restart +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 2 + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -[iI] | --install ) + INSTALL=true + ;; + -[uU] | --uninstall ) + UNINSTALL=true + uninstall_acme + ;; + -[fF] | --force ) + FORCE=true + ;; + -[r] | --renew ) + RENEW=true + ;; + -[R] | --renew-all ) + RENEW_ALL=true + ;; + -[v] | --revoke ) + REVOKE=true + ;; + -[V] | --remove ) + REMOVE=true + ;; + -[eE] | --email ) shift + check_input "${1}" + EMAIL="${1}" + ;; + *) + help_message 2 + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/appinstall.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/appinstall.sh new file mode 100644 index 00000000..ba67d52d --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/appinstall.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +APP_NAME='' +DOMAIN='' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --app [app_name] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstall.sh -A wordpress -D example.com" + echo "${EPACE}${EPACE}Will install WordPress CMS under the example.com domain" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +app_download(){ + docker compose exec litespeed su -c "appinstallctl.sh --app ${1} --domain ${2}" + bash bin/webadmin.sh -r + exit 0 +} + +main(){ + app_download ${APP_NAME} ${DOMAIN} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + *) + help_message + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/appinstallctl.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/appinstallctl.sh new file mode 100644 index 00000000..d79c63f1 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/appinstallctl.sh @@ -0,0 +1,660 @@ +#!/bin/bash +DEFAULT_VH_ROOT='/var/www/vhosts' +VH_DOC_ROOT='' +VHNAME='' +APP_NAME='' +DOMAIN='' +WWW_UID='' +WWW_GID='' +WP_CONST_CONF='' +PUB_IP=$(curl -s http://checkip.amazonaws.com) +DB_HOST='mysql' +PLUGINLIST="litespeed-cache.zip" +THEME='twentytwenty' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, -app [wordpress] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstallctl.sh --app wordpress --domain example.com" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +linechange(){ + LINENUM=$(grep -n "${1}" ${2} | cut -d: -f 1) + if [ -n "${LINENUM}" ] && [ "${LINENUM}" -eq "${LINENUM}" ] 2>/dev/null; then + sed -i "${LINENUM}d" ${2} + sed -i "${LINENUM}i${3}" ${2} + fi +} + +ck_ed(){ + if [ ! -f /bin/ed ]; then + echo "Install ed package.." + apt-get install ed -y > /dev/null 2>&1 + fi +} + +ck_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo "Install unzip package.." + apt-get install unzip -y > /dev/null 2>&1 + fi +} + +get_owner(){ + WWW_UID=$(stat -c "%u" ${DEFAULT_VH_ROOT}) + WWW_GID=$(stat -c "%g" ${DEFAULT_VH_ROOT}) + if [ ${WWW_UID} -eq 0 ] || [ ${WWW_GID} -eq 0 ]; then + WWW_UID=1000 + WWW_GID=1000 + echo "Set owner to ${WWW_UID}" + fi +} + +get_db_pass(){ + if [ -f ${DEFAULT_VH_ROOT}/${1}/.db_pass ]; then + SQL_DB=$(grep -i Database ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_USER=$(grep -i Username ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_PASS=$(grep -i Password ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + else + echo 'db pass file can not locate, skip wp-config pre-config.' + fi +} + +set_vh_docroot(){ + if [ "${VHNAME}" != '' ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + elif [ -d ${DEFAULT_VH_ROOT}/${1}/html ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${1}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${1}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + else + echo "${DEFAULT_VH_ROOT}/${1}/html does not exist, please add domain first! Abort!" + exit 1 + fi +} + +check_sql_native(){ + local COUNTER=0 + local LIMIT_NUM=100 + until [ "$(curl -v mysql:3306 2>&1 | grep -i 'native\|Connected')" ]; do + echo "Counter: ${COUNTER}/${LIMIT_NUM}" + COUNTER=$((COUNTER+1)) + if [ ${COUNTER} = 10 ]; then + echo '--- MySQL is starting, please wait... ---' + elif [ ${COUNTER} = ${LIMIT_NUM} ]; then + echo '--- MySQL is timeout, exit! ---' + exit 1 + fi + sleep 1 + done +} + +install_wp_plugin(){ + for PLUGIN in ${PLUGINLIST}; do + wget -q -P ${VH_DOC_ROOT}/wp-content/plugins/ https://downloads.wordpress.org/plugin/${PLUGIN} + if [ ${?} = 0 ]; then + ck_unzip + unzip -qq -o ${VH_DOC_ROOT}/wp-content/plugins/${PLUGIN} -d ${VH_DOC_ROOT}/wp-content/plugins/ + else + echo "${PLUGINLIST} FAILED to download" + fi + done + rm -f ${VH_DOC_ROOT}/wp-content/plugins/*.zip +} + +set_htaccess(){ + if [ ! -f ${VH_DOC_ROOT}/.htaccess ]; then + touch ${VH_DOC_ROOT}/.htaccess + fi + cat << EOM > ${VH_DOC_ROOT}/.htaccess +# BEGIN WordPress + +RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + +# END WordPress +EOM +} + +get_theme_name(){ + THEME_NAME=$(grep WP_DEFAULT_THEME ${VH_DOC_ROOT}/wp-includes/default-constants.php | grep -v '!' | awk -F "'" '{print $4}') + echo "${THEME_NAME}" | grep 'twenty' >/dev/null 2>&1 + if [ ${?} = 0 ]; then + THEME="${THEME_NAME}" + fi +} + +set_lscache(){ + cat << EOM > "${WP_CONST_CONF}" +; +; This is the predefined default LSCWP configuration file +; +; All the keys and values please refer \`src/const.cls.php\` +; +; Comments start with \`;\` +; +;; -------------------------------------------------- ;; +;; -------------- General ----------------- ;; +;; -------------------------------------------------- ;; +; O_AUTO_UPGRADE +auto_upgrade = false +; O_API_KEY +api_key = '' +; O_SERVER_IP +server_ip = '' +; O_NEWS +news = false +;; -------------------------------------------------- ;; +;; -------------- Cache ----------------- ;; +;; -------------------------------------------------- ;; +cache-priv = true +cache-commenter = true +cache-rest = true +cache-page_login = true +cache-favicon = true +cache-resources = true +cache-browser = false +cache-mobile = false +cache-mobile_rules = 'Mobile +Android +Silk/ +Kindle +BlackBerry +Opera Mini +Opera Mobi' +cache-exc_useragents = '' +cache-exc_cookies = '' +cache-exc_qs = '' +cache-exc_cat = '' +cache-exc_tag = '' +cache-force_uri = '' +cache-force_pub_uri = '' +cache-priv_uri = '' +cache-exc = '' +cache-exc_roles = '' +cache-drop_qs = 'fbclid +gclid +utm* +_ga' +cache-ttl_pub = 604800 +cache-ttl_priv = 1800 +cache-ttl_frontpage = 604800 +cache-ttl_feed = 604800 +; O_CACHE_TTL_REST +cache-ttl_rest = 604800 +cache-ttl_browser = 31557600 +cache-login_cookie = '' +cache-vary_group = '' +cache-ttl_status = '403 3600 +404 3600 +500 3600' +;; -------------------------------------------------- ;; +;; -------------- Purge ----------------- ;; +;; -------------------------------------------------- ;; +; O_PURGE_ON_UPGRADE +purge-upgrade = true +; O_PURGE_STALE +purge-stale = true +purge-post_all = false +purge-post_f = true +purge-post_h = true +purge-post_p = true +purge-post_pwrp = true +purge-post_a = true +purge-post_y = false +purge-post_m = true +purge-post_d = false +purge-post_t = true +purge-post_pt = true +purge-timed_urls = '' +purge-timed_urls_time = '' +purge-hook_all = 'switch_theme +wp_create_nav_menu +wp_update_nav_menu +wp_delete_nav_menu +create_term +edit_terms +delete_term +add_link +edit_link +delete_link' +;; -------------------------------------------------- ;; +;; -------------- ESI ----------------- ;; +;; -------------------------------------------------- ;; +; O_ESI +esi = false +; O_ESI_CACHE_ADMBAR +esi-cache_admbar = true +; O_ESI_CACHE_COMMFORM +esi-cache_commform = true +; O_ESI_NONCE +esi-nonce = 'stats_nonce +subscribe_nonce' +;; -------------------------------------------------- ;; +;; -------------- Utilities ----------------- ;; +;; -------------------------------------------------- ;; +util-heartbeat = true +util-instant_click = false +util-check_advcache = true +util-no_https_vary = false +;; -------------------------------------------------- ;; +;; -------------- Debug ----------------- ;; +;; -------------------------------------------------- ;; +; O_DEBUG_DISABLE_ALL +debug-disable_all = false +; O_DEBUG +debug = false +; O_DEBUG_IPS +debug-ips = '127.0.0.1' +; O_DEBUG_LEVEL +debug-level = false +; O_DEBUG_FILESIZE +debug-filesize = 3 +; O_DEBUG_COOKIE +debug-cookie = false +; O_DEBUG_COLLAPS_QS +debug-collaps_qs = false +; O_DEBUG_INC +debug-inc = '' +; O_DEBUG_EXC +debug-exc = '' +;; -------------------------------------------------- ;; +;; -------------- DB Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_DB_OPTM_REVISIONS_MAX +db_optm-revisions_max = 0 +; O_DB_OPTM_REVISIONS_AGE +db_optm-revisions_age = 0 +;; -------------------------------------------------- ;; +;; -------------- HTML Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_OPTM_CSS_MIN +optm-css_min = false +optm-css_inline_min = false +; O_OPTM_CSS_COMB +optm-css_comb = false +optm-css_comb_priority = false +; O_OPTM_CSS_HTTP2 +optm-css_http2 = false +optm-css_exc = '' +; O_OPTM_JS_MIN +optm-js_min = false +optm-js_inline_min = false +; O_OPTM_JS_COMB +optm-js_comb = false +optm-js_comb_priority = false +; O_OPTM_JS_HTTP2 +optm-js_http2 = false +; O_OPTM_EXC_JQ +optm-js_exc = '' +optm-ttl = 604800 +optm-html_min = false +optm-qs_rm = false +optm-ggfonts_rm = false +; O_OPTM_CSS_ASYNC +optm-css_async = false +; O_OPTM_CCSS_GEN +optm-ccss_gen = true +; O_OPTM_CCSS_ASYNC +optm-ccss_async = true +; O_OPTM_CSS_ASYNC_INLINE +optm-css_async_inline = true +; O_OPTM_CSS_FONT_DISPLAY +optm-css_font_display = false +; O_OPTM_JS_DEFER +optm-js_defer = false +; O_OPTM_JS_INLINE_DEFER +optm-js_inline_defer = false +optm-emoji_rm = false +optm-exc_jq = true +optm-ggfonts_async = false +optm-max_size = 2 +optm-rm_comment = false +optm-exc_roles = '' +optm-ccss_con = '' +optm-js_defer_exc = '' +; O_OPTM_DNS_PREFETCH +optm-dns_prefetch = '' +; O_OPTM_DNS_PREFETCH_CTRL +optm-dns_prefetch_ctrl = false +optm-exc = '' +; O_OPTM_CCSS_SEP_POSTTYPE +optm-ccss_sep_posttype = '' +; O_OPTM_CCSS_SEP_URI +optm-ccss_sep_uri = '' +;; -------------------------------------------------- ;; +;; -------------- Object Cache ----------------- ;; +;; -------------------------------------------------- ;; +object = true +object-kind = false +;object-host = 'localhost' +object-host = '/var/www/memcached.sock' +;object-port = 11211 +cache_object_port = '' +object-life = 360 +object-persistent = true +object-admin = true +object-transients = true +object-db_id = 0 +object-user = '' +object-pswd = '' +object-global_groups = 'users +userlogins +usermeta +user_meta +site-transient +site-options +site-lookup +blog-lookup +blog-details +rss +global-posts +blog-id-cache' +object-non_persistent_groups = 'comment +counts +plugins +wc_session_id' +;; -------------------------------------------------- ;; +;; -------------- Discussion ----------------- ;; +;; -------------------------------------------------- ;; +; O_DISCUSS_AVATAR_CACHE +discuss-avatar_cache = false +; O_DISCUSS_AVATAR_CRON +discuss-avatar_cron = false +; O_DISCUSS_AVATAR_CACHE_TTL +discuss-avatar_cache_ttl = 604800 +;; -------------------------------------------------- ;; +;; -------------- Media ----------------- ;; +;; -------------------------------------------------- ;; +; O_MEDIA_LAZY +media-lazy = false +; O_MEDIA_LAZY_PLACEHOLDER +media-lazy_placeholder = '' +; O_MEDIA_PLACEHOLDER_RESP +media-placeholder_resp = false +; O_MEDIA_PLACEHOLDER_RESP_COLOR +media-placeholder_resp_color = '#cfd4db' +; O_MEDIA_PLACEHOLDER_RESP_GENERATOR +media-placeholder_resp_generator = false +; O_MEDIA_PLACEHOLDER_RESP_SVG +media-placeholder_resp_svg = '' +; O_MEDIA_PLACEHOLDER_LQIP +media-placeholder_lqip = false +; O_MEDIA_PLACEHOLDER_LQIP_QUAL +media-placeholder_lqip_qual = 4 +; O_MEDIA_PLACEHOLDER_RESP_ASYNC +media-placeholder_resp_async = true +; O_MEDIA_IFRAME_LAZY +media-iframe_lazy = false +; O_MEDIA_LAZYJS_INLINE +media-lazyjs_inline = false +; O_MEDIA_LAZY_EXC +media-lazy_exc = '' +; O_MEDIA_LAZY_CLS_EXC +media-lazy_cls_exc = '' +; O_MEDIA_LAZY_PARENT_CLS_EXC +media-lazy_parent_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_CLS_EXC +media-iframe_lazy_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_PARENT_CLS_EXC +media-iframe_lazy_parent_cls_exc = '' +; O_MEDIA_LAZY_URI_EXC +media-lazy_uri_exc = '' +;; -------------------------------------------------- ;; +;; -------------- Image Optm ----------------- ;; +;; -------------------------------------------------- ;; +img_optm-auto = false +img_optm-cron = true +img_optm-ori = true +img_optm-rm_bkup = false +img_optm-webp = false +img_optm-lossless = false +img_optm-exif = false +img_optm-webp_replace = false +img_optm-webp_attr = 'img.src +div.data-thumb +img.data-src +div.data-large_image +img.retina_logo_url +div.data-parallax-image +video.poster' +img_optm-webp_replace_srcset = false +img_optm-jpg_quality = 82 +;; -------------------------------------------------- ;; +;; -------------- Crawler ----------------- ;; +;; -------------------------------------------------- ;; +crawler = false +crawler-inc_posts = true +crawler-inc_pages = true +crawler-inc_cats = true +crawler-inc_tags = true +crawler-exc_cpt = '' +crawler-order_links = 'date_desc' +crawler-usleep = 500 +crawler-run_duration = 400 +crawler-run_interval = 600 +crawler-crawl_interval = 302400 +crawler-threads = 3 +crawler-timeout = 30 +crawler-load_limit = 1 +; O_CRAWLER_SITEMAP +crawler-sitemap = '' +; O_CRAWLER_DROP_DOMAIN +crawler-drop_domain = true +crawler-roles = '' +crawler-cookies = '' +;; -------------------------------------------------- ;; +;; -------------- Misc ----------------- ;; +;; -------------------------------------------------- ;; +; O_MISC_HTACCESS_FRONT +misc-htaccess_front = '' +; O_MISC_HTACCESS_BACK +misc-htaccess_back = '' +; O_MISC_HEARTBEAT_FRONT +misc-heartbeat_front = false +; O_MISC_HEARTBEAT_FRONT_TTL +misc-heartbeat_front_ttl = 60 +; O_MISC_HEARTBEAT_BACK +misc-heartbeat_back = false +; O_MISC_HEARTBEAT_BACK_TTL +misc-heartbeat_back_ttl = 60 +; O_MISC_HEARTBEAT_EDITOR +misc-heartbeat_editor = false +; O_MISC_HEARTBEAT_EDITOR_TTL +misc-heartbeat_editor_ttl = 15 +;; -------------------------------------------------- ;; +;; -------------- CDN ----------------- ;; +;; -------------------------------------------------- ;; +cdn = false +cdn-ori = '' +cdn-ori_dir = '' +cdn-exc = '' +cdn-remote_jq = false +cdn-quic = false +cdn-quic_email = '' +cdn-quic_key = '' +cdn-cloudflare = false +cdn-cloudflare_email = '' +cdn-cloudflare_key = '' +cdn-cloudflare_name = '' +cdn-cloudflare_zone = '' +; \`cdn-mapping\` needs to be put in the end with a section tag +;; -------------------------------------------------- ;; +;; -------------- CDN 2 ----------------- ;; +;; -------------------------------------------------- ;; +; <------------ CDN Mapping Example BEGIN --------------------> +; Need to keep the section tag \`[cdn-mapping]\` before list. +; +; NOTE 1) Need to set all child options to make all resources to be replaced without missing. +; NOTE 2) \`url[n]\` option must have to enable the row setting of \`n\`. +; NOTE 3) This section needs to be put in the end of this .ini file +; +; To enable the 2nd mapping record by default, please remove the \`;;\` in the related lines. +[cdn-mapping] +url[0] = '' +inc_js[0] = true +inc_css[0] = true +inc_img[0] = true +filetype[0] = '.aac +.css +.eot +.gif +.jpeg +.js +.jpg +.less +.mp3 +.mp4 +.ogg +.otf +.pdf +.png +.svg +.ttf +.woff' +;;url[1] = 'https://2nd_CDN_url.com/' +;;filetype[1] = '.webm' +; <------------ CDN Mapping Example END ------------------> +EOM + + THEME_PATH="${VH_DOC_ROOT}/wp-content/themes/${THEME}" + if [ ! -f ${THEME_PATH}/functions.php ]; then + cat >> "${THEME_PATH}/functions.php" <>/dev/null 2>&1 +2i +require_once( WP_CONTENT_DIR.'/../wp-admin/includes/plugin.php' ); +\$path = 'litespeed-cache/litespeed-cache.php' ; +if (!is_plugin_active( \$path )) { + activate_plugin( \$path ) ; + rename( __FILE__ . '.bk', __FILE__ ); +} +. +w +q +END + fi +} + +preinstall_wordpress(){ + if [ "${VHNAME}" != '' ]; then + get_db_pass ${VHNAME} + else + get_db_pass ${DOMAIN} + fi + if [ ! -f ${VH_DOC_ROOT}/wp-config.php ] && [ -f ${VH_DOC_ROOT}/wp-config-sample.php ]; then + cp ${VH_DOC_ROOT}/wp-config-sample.php ${VH_DOC_ROOT}/wp-config.php + NEWDBPWD="define('DB_PASSWORD', '${SQL_PASS}');" + linechange 'DB_PASSWORD' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_USER', '${SQL_USER}');" + linechange 'DB_USER' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_NAME', '${SQL_DB}');" + linechange 'DB_NAME' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + #NEWDBPWD="define('DB_HOST', '${PUB_IP}');" + NEWDBPWD="define('DB_HOST', '${DB_HOST}');" + linechange 'DB_HOST' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + elif [ -f ${VH_DOC_ROOT}/wp-config.php ]; then + echo "${VH_DOC_ROOT}/wp-config.php already exist, exit !" + exit 1 + else + echo 'Skip!' + exit 2 + fi +} + +app_wordpress_dl(){ + if [ ! -f "${VH_DOC_ROOT}/wp-config.php" ] && [ ! -f "${VH_DOC_ROOT}/wp-config-sample.php" ]; then + wp core download \ + --allow-root \ + --quiet + else + echo 'wordpress already exist, abort!' + exit 1 + fi +} + +change_owner(){ + if [ "${VHNAME}" != '' ]; then + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${VHNAME} + else + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${DOMAIN} + fi +} + +main(){ + set_vh_docroot ${DOMAIN} + get_owner + cd ${VH_DOC_ROOT} + if [ "${APP_NAME}" = 'wordpress' ] || [ "${APP_NAME}" = 'wp' ]; then + check_sql_native + app_wordpress_dl + preinstall_wordpress + install_wp_plugin + set_htaccess + get_theme_name + set_lscache + change_owner + exit 0 + else + echo "APP: ${APP_NAME} not support, exit!" + exit 1 + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -vhname | --vhname) shift + VHNAME="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/certhookctl.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/certhookctl.sh new file mode 100644 index 00000000..18be0965 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/certhookctl.sh @@ -0,0 +1,18 @@ +#!/bin/bash +BOTCRON='/var/spool/cron/crontabs/root' + +cert_hook(){ + grep 'acme' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + grep 'lswsctrl' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + echo 'Hook already exist, skip!' + else + sed -i 's/--cron/--cron --renew-hook "\/usr\/local\/lsws\/bin\/lswsctrl restart"/g' ${BOTCRON} + fi + else + echo "[X] ${BOTCRON} does not exist, please check it later!" + fi +} + +cert_hook \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/domainctl.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/domainctl.sh new file mode 100644 index 00000000..75539ef0 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/domainctl.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +CK_RESULT='' +LSDIR='/usr/local/lsws' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --add [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will add domain to listener and creat a virtual host from template" + echow '-D, --del [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will delete domain from listener" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help." +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +dot_escape(){ + ESCAPE=$(echo ${1} | sed 's/\./\\./g') +} + +check_duplicate(){ + CK_RESULT=$(grep -E "${1}" ${2}) +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 ${1} ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +check_www(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + echo 'www domain shoudnt be passed!' + exit 1 + fi +} + +www_domain(){ + check_www ${1} + WWW_DOMAIN=$(echo www.${1}) +} + +add_ls_domain(){ + fst_match_line 'docker.xml' ${LS_HTTPD_CONF} + NEWNUM=$((FIRST_LINE_NUM+2)) + sed -i "${NEWNUM}i \ \ \ \ \ \ \n \ \ \ \ \ \ \ ${DOMAIN}\n \ \ \ \ \ \ \ ${DOMAIN},${WWW_DOMAIN}\n \ \ \ \ \ \ " ${LS_HTTPD_CONF} +} + +add_ols_domain(){ + perl -0777 -p -i -e 's/(vhTemplate docker \{[^}]+)\}*(^.*listeners.*$)/\1$2 + member '${DOMAIN}' { + vhDomain '${DOMAIN},${WWW_DOMAIN}' + }/gmi' ${OLS_HTTPD_CONF} +} + +add_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + www_domain ${1} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + add_ls_domain + add_ols_domain +} + +del_ls_domain(){ + fst_match_line "*${1}" ${LS_HTTPD_CONF} + FIRST_LINE_NUM=$((FIRST_LINE_NUM-1)) + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} +} + +del_ols_domain(){ + fst_match_line ${1} ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} +} + +del_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + del_ls_domain ${1} + del_ols_domain ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/owaspctl.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/owaspctl.sh new file mode 100644 index 00000000..72fd8e59 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/owaspctl.sh @@ -0,0 +1,236 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +OWASP_DIR="${LSDIR}/conf/owasp" +RULE_FILE='modsec_includes.conf' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' +OWASP_V='3.3.4' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-E, --enable' + echo "${EPACE}${EPACE}Will Enable mod_secure module with latest OWASP version of rules" + echow '-D, --disable' + echo "${EPACE}${EPACE}Will Disable mod_secure module with latest OWASP version of rules" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +mk_owasp_dir(){ + if [ -d ${OWASP_DIR} ] ; then + rm -rf ${OWASP_DIR} + fi + mkdir -p ${OWASP_DIR} + if [ ${?} -ne 0 ] ; then + echo "Unable to create directory: ${OWASP_DIR}, exit!" + exit 1 + fi +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 "${1}" ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +enable_ols_modsec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "Already configured for modsecurity." + else + echo 'Enable modsecurity' + sed -i "s=module cache=module mod_security {\nmodsecurity on\ + \nmodsecurity_rules \`\nSecRuleEngine On\n\`\nmodsecurity_rules_file \ + ${OWASP_DIR}/${RULE_FILE}\n ls_enabled 1\n}\ + \n\nmodule cache=" ${OLS_HTTPD_CONF} + fi +} + +enable_ls_modsec(){ + grep '1' ${LS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "LSWS already configured for modsecurity" + else + echo 'Enable modsecurity' + sed -i \ + "s=0=1=" ${LS_HTTPD_CONF} + sed -i \ + "s==\n\ + \n\ + ModSec\n\ + 1\n\ + include ${OWASP_DIR}/modsec_includes.conf\n\ + =" ${LS_HTTPD_CONF} + fi +} + +enable_modsec(){ + if [ "${LSV}" = 'lsws' ]; then + enable_ls_modsec + elif [ "${LSV}" = 'openlitespeed' ]; then + enable_ols_modsec + fi +} + +disable_ols_modesec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo 'Disable modsecurity' + fst_match_line 'module mod_security' ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} + else + echo 'Already disabled for modsecurity' + fi +} + +disable_ls_modesec(){ + grep '0' ${LS_HTTPD_CONF} + if [ ${?} -eq 0 ] ; then + echo 'Already disabled for modsecurity' + else + echo 'Disable modsecurity' + sed -i \ + "s=1=0=" ${LS_HTTPD_CONF} + fst_match_line 'censorshipRuleSet' ${LS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '/censorshipRuleSet' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} + fi +} + +disable_modsec(){ + check_lsv + if [ "${LSV}" = 'lsws' ]; then + disable_ls_modesec + elif [ "${LSV}" = 'openlitespeed' ]; then + disable_ols_modesec + fi +} + +install_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo 'Install Unzip' + apt update >/dev/null 2>&1 + apt-get install unzip -y >/dev/null 2>&1 + fi +} + +install_owasp(){ + cd ${OWASP_DIR} + echo 'Download OWASP rules' + wget -q https://github.com/coreruleset/coreruleset/archive/refs/tags/v${OWASP_V}.zip + unzip -qq v${OWASP_V}.zip + rm -f v${OWASP_V}.zip + mv coreruleset-* owasp-modsecurity-crs +} + +configure_owasp(){ + echo 'Config OWASP rules.' + cd ${OWASP_DIR} + echo "include modsecurity.conf +include owasp-modsecurity-crs/crs-setup.conf +include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf +include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf +include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf +include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf +include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf +include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf +include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf +include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf +include owasp-modsecurity-crs/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf +include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf +include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf +include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf +include owasp-modsecurity-crs/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf +include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf +include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf +include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf +include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf +include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf +include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf">modsec_includes.conf + echo "SecRuleEngine On">modsecurity.conf + cd ${OWASP_DIR}/owasp-modsecurity-crs + if [ -f crs-setup.conf.example ]; then + mv crs-setup.conf.example crs-setup.conf + fi + cd ${OWASP_DIR}/owasp-modsecurity-crs/rules + if [ -f REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example ]; then + mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf + fi + if [ -f RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example ]; then + mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf + fi +} + +main_owasp(){ + mk_owasp_dir + install_unzip + install_owasp + configure_owasp + check_lsv + enable_modsec +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[eE] | -enable | --enable) + main_owasp + ;; + -[dD] | -disable | --disable) + disable_modsec + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/serialctl.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/serialctl.sh new file mode 100644 index 00000000..42e312dc --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/container/serialctl.sh @@ -0,0 +1,84 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply and register the serial to LSWS." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +backup_old(){ + if [ -f ${1} ] && [ ! -f ${1}_old ]; then + mv ${1} ${1}_old + fi +} + +detect_ols(){ + if [ -e ${LSDIR}/bin/openlitespeed ]; then + echo '[X] Detect OpenLiteSpeed, abort!' + exit 1 + fi +} + +apply_serial(){ + detect_ols + check_input ${1} + echo ${1} | grep -i 'trial' >/dev/null + if [ ${?} = 0 ]; then + echo 'Apply Trial License' + if [ ! -e ${LSDIR}/conf/serial.no ] && [ ! -e ${LSDIR}/conf/license.key ]; then + rm -f ${LSDIR}/conf/trial.key* + wget -P ${LSDIR}/conf -q http://license.litespeedtech.com/reseller/trial.key + echo 'Apply trial finished' + else + echo "Please backup and remove your existing license, apply abort!" + exit 1 + fi + else + echo "Apply Serial number: ${1}" + backup_old ${LSDIR}/conf/serial.no + backup_old ${LSDIR}/conf/license.key + backup_old ${LSDIR}/conf/trial.key + echo "${1}" > ${LSDIR}/conf/serial.no + ${LSDIR}/bin/lshttpd -r + if [ -f ${LSDIR}/conf/license.key ]; then + echo '[O] Apply success' + else + echo '[X] Apply failed, please check!' + exit 1 + fi + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[sS] | -serial | --serial) shift + apply_serial "${1}" + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/database.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/database.sh new file mode 100644 index 00000000..ec1462d4 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/database.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +source .env + +DOMAIN='' +SQL_DB='' +SQL_USER='' +SQL_PASS='' +ANY="'%'" +SET_OK=0 +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com" + echo "${EPACE}${EPACE}Will auto generate Database/username/password for the domain" + echow '-D, --domain [DOMAIN_NAME] -U, --user [xxx] -P, --password [xxx] -DB, --database [xxx]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com -U USERNAME -P PASSWORD -DB DATABASENAME" + echo "${EPACE}${EPACE}Will create Database/username/password by given" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +specify_name(){ + check_input ${SQL_USER} + check_input ${SQL_PASS} + check_input ${SQL_DB} +} + +auto_name(){ + SQL_DB="${TRANSNAME}" + SQL_USER="${TRANSNAME}" + SQL_PASS="'${RANDOM_PASS}'" +} + +gen_pass(){ + RANDOM_PASS="$(openssl rand -base64 12)" +} + +trans_name(){ + TRANSNAME=$(echo ${1} | tr -d '.&&-') +} + +display_credential(){ + if [ ${SET_OK} = 0 ]; then + echo "Database: ${SQL_DB}" + echo "Username: ${SQL_USER}" + echo "Password: $(echo ${SQL_PASS} | tr -d "'")" + fi +} + +store_credential(){ + if [ -d "./sites/${1}" ]; then + if [ -f ./sites/${1}/.db_pass ]; then + mv ./sites/${1}/.db_pass ./sites/${1}/.db_pass.bk + fi + cat > "./sites/${1}/.db_pass" << EOT +"Database":"${SQL_DB}" +"Username":"${SQL_USER}" +"Password":"$(echo ${SQL_PASS} | tr -d "'")" +EOT + else + echo "./sites/${1} not found, abort credential store!" + fi +} + +check_db_access(){ + docker compose exec -T mysql su -c "mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e 'status'" >/dev/null 2>&1 + if [ ${?} != 0 ]; then + echo '[X] DB access failed, please check!' + exit 1 + fi +} + +check_db_exist(){ + docker compose exec -T mysql su -c "test -e /var/lib/mysql/${1}" + if [ ${?} = 0 ]; then + echo "Database ${1} already exist, skip DB creation!" + exit 0 + fi +} + +db_setup(){ + docker compose exec -T mysql su -c 'mysql -uroot -p${MYSQL_ROOT_PASSWORD} \ + -e "CREATE DATABASE '${SQL_DB}';" \ + -e "GRANT ALL PRIVILEGES ON '${SQL_DB}'.* TO '${SQL_USER}'@'${ANY}' IDENTIFIED BY '${SQL_PASS}';" \ + -e "FLUSH PRIVILEGES;"' + SET_OK=${?} +} + +auto_setup_main(){ + check_input ${DOMAIN} + gen_pass + trans_name ${DOMAIN} + auto_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +specify_setup_main(){ + specify_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +main(){ + if [ "${SQL_USER}" != '' ] && [ "${SQL_PASS}" != '' ] && [ "${SQL_DB}" != '' ]; then + specify_setup_main + else + auto_setup_main + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[dD] | -domain| --domain) shift + DOMAIN="${1}" + ;; + -[uU] | -user | --user) shift + SQL_USER="${1}" + ;; + -[pP] | -password| --password) shift + SQL_PASS="'${1}'" + ;; + -db | -DB | -database| --database) shift + SQL_DB="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/demosite.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/demosite.sh new file mode 100644 index 00000000..91474647 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/demosite.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +source .env +APP_NAME='wordpress' +CONT_NAME='litespeed' +DOC_FD='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echow "Script will get 'DOMAIN' and 'database' info from .env file, then auto setup virtual host and the wordpress site for you." + exit 0 + ;; + "2") + echow 'Service finished, enjoy your accelarated LiteSpeed server!' + ;; + esac +} + +domain_filter(){ + if [ ! -n "${DOMAIN}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +gen_root_fd(){ + DOC_FD="./sites/${1}/" + if [ -d "./sites/${1}" ]; then + echo -e "[O] The root folder \033[32m${DOC_FD}\033[0m exist." + else + echo "Creating - document root." + bash bin/domain.sh -add ${1} + echo "Finished - document root." + fi +} + +create_db(){ + if [ ! -n "${MYSQL_DATABASE}" ] || [ ! -n "${MYSQL_USER}" ] || [ ! -n "${MYSQL_PASSWORD}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + else + bash bin/database.sh -D ${1} -U ${MYSQL_USER} -P ${MYSQL_PASSWORD} -DB ${MYSQL_DATABASE} + fi +} + +store_credential(){ + if [ -f ${DOC_FD}/.db_pass ]; then + echo '[O] db file exist!' + else + echo 'Storing database parameter' + cat > "${DOC_FD}/.db_pass" << EOT +"Database":"${MYSQL_DATABASE}" +"Username":"${MYSQL_USER}" +"Password":"$(echo ${MYSQL_PASSWORD} | tr -d "'")" +EOT + fi +} + +app_download(){ + docker compose exec -T ${CONT_NAME} su -c "appinstallctl.sh --app ${1} --domain ${2}" +} + +lsws_restart(){ + bash bin/webadmin.sh -r +} + +main(){ + domain_filter ${DOMAIN} + gen_root_fd ${DOMAIN} + create_db ${DOMAIN} + store_credential + app_download ${APP_NAME} ${DOMAIN} + lsws_restart + help_message 2 +} + +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 1 + ;; + *) + help_message 1 + ;; + esac + shift +done +main \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/list-flagged-files.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/list-flagged-files.sh new file mode 100644 index 00000000..bde4f25f --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/list-flagged-files.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +git ls-files -v|grep '^S' diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/no-skip-worktree-conf.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/no-skip-worktree-conf.sh new file mode 100644 index 00000000..9bf83e7c --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/no-skip-worktree-conf.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --no-skip-worktree" \; diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/skip-worktree-conf.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/skip-worktree-conf.sh new file mode 100644 index 00000000..18b16184 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/dev/skip-worktree-conf.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --skip-worktree" \; + diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/domain.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/domain.sh new file mode 100644 index 00000000..d99dca40 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/domain.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow "-A, --add [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -A example.com, will add the domain to Listener and auto create a new virtual host." + echow "-D, --del [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -D example.com, will delete the domain from Listener." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +add_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --add ${1}" + if [ ! -d "./sites/${1}" ]; then + mkdir -p ./sites/${1}/{html,logs,certs} + fi + bash bin/webadmin.sh -r +} + +del_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --del ${1}" + bash bin/webadmin.sh -r +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done + \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/bin/webadmin.sh b/apps/openlitespeed/1.7.17-lsphp81/data/bin/webadmin.sh new file mode 100644 index 00000000..18e108ec --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/bin/webadmin.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '[Enter Your PASSWORD]' + echo "${EPACE}${EPACE}Example: webadmin.sh MY_SECURE_PASS, to update web admin password immediatly." + echow '-R, --restart' + echo "${EPACE}${EPACE}Will gracefully restart LiteSpeed Web Server." + echow '-M, --mod-secure [enable|disable]' + echo "${EPACE}${EPACE}Example: webadmin.sh -M enable, will enable and apply Mod_Secure OWASP rules on server" + echow '-U, --upgrade' + echo "${EPACE}${EPACE}Will upgrade web server to latest stable version" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply your serial number to LiteSpeed Web Server." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +lsws_restart(){ + docker compose exec -T ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +apply_serial(){ + docker compose exec ${CONT_NAME} su -c "serialctl.sh --serial ${1}" + lsws_restart +} + +mod_secure(){ + if [ "${1}" = 'enable' ] || [ "${1}" = 'Enable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --enable" + lsws_restart + elif [ "${1}" = 'disable' ] || [ "${1}" = 'Disable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --disable" + lsws_restart + else + help_message + fi +} + +ls_upgrade(){ + echo 'Upgrade web server to latest stable version.' + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/admin/misc/lsup.sh 2>/dev/null' +} + +set_web_admin(){ + echo 'Update web admin password.' + local LSADPATH='/usr/local/lsws/admin' + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c \ + 'if [ -e /usr/local/lsws/admin/fcgi-bin/admin_php ]; then \ + echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + else echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php5 -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + fi'; +} + +main(){ + set_web_admin ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[rR] | -restart | --restart) + lsws_restart + ;; + -M | -mode-secure | --mod-secure) shift + mod_secure ${1} + ;; + -lsup | --lsup | --upgrade | -U) shift + ls_upgrade + ;; + -[sS] | -serial | --serial) shift + apply_serial ${1} + ;; + *) + main ${1} + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/1.7.17-lsphp81/data/sites/.gitignore b/apps/openlitespeed/1.7.17-lsphp81/data/sites/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/data/sites/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/apps/openlitespeed/1.7.17-lsphp81/docker-compose.yml b/apps/openlitespeed/1.7.17-lsphp81/docker-compose.yml new file mode 100644 index 00000000..0d66d457 --- /dev/null +++ b/apps/openlitespeed/1.7.17-lsphp81/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' +services: + litespeed: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + logging: + driver: none + volumes: + - ${DATA_PATH}/lsws/conf:/usr/local/lsws/conf + - ${DATA_PATH}/lsws/admin-conf:/usr/local/lsws/admin/conf + - ${DATA_PATH}/bin/container:/usr/local/bin + - ${DATA_PATH}/sites:/var/www/vhosts/ + - ${DATA_PATH}/acme:/root/.acme.sh/ + - ${DATA_PATH}/logs:/usr/local/lsws/logs/ + ports: + - "${PANEL_APP_PORT_HTTP}:80" + - "${PANEL_APP_PORT_HTTPS}:443" + - "${PANEL_APP_PORT_HTTPS}:443/udp" + - "${PANEL_APP_PORT_CONSOLE}:7080" + environment: + - TZ=${TIME_ZONE} + image: litespeedtech/openlitespeed:1.7.17-lsphp81 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/openlitespeed/README.md b/apps/openlitespeed/README.md new file mode 100644 index 00000000..53c7ffab --- /dev/null +++ b/apps/openlitespeed/README.md @@ -0,0 +1,43 @@ +# 使用说明 + +安装完成后,在容器功能界面,连接容器终端,执行以下命令创建管理员账户密码 + +``` +/usr/local/lsws/admin/misc/admpass.sh +``` + +# 原始相关 + +OpenLiteSpeed Web Server +======== + +Description +-------- + +OpenLiteSpeed is a high-performance, lightweight, open source HTTP server developed and copyrighted by +LiteSpeed Technologies. Users are free to download, use, distribute, and modify OpenLiteSpeed and its +source code in accordance with the precepts of the GPLv3 license. + +This is the official repository for OpenLiteSpeed's source code. It is maintained by LiteSpeed +Technologies. + +Documentation +-------- + +Users can find all OpenLiteSpeed documentation on the [OpenLiteSpeed site](https://openlitespeed.org), +but here are some quick links to important parts of the site: + +[Installation](https://openlitespeed.org/kb/category/installation/) + +[Configuration](https://openlitespeed.org/kb/category/configuration/) + +[Road map](https://openlitespeed.org/mediawiki/index.php/Road_Map) + +[Release log](https://openlitespeed.org/release-log/) + +Get in Touch +-------- + +OpenLiteSpeed has a [Google Group](https://groups.google.com/forum/#!forum/openlitespeed-development). If +you find a bug, want to request new features, or just want to talk about OpenLiteSpeed, this is the place +to do it. diff --git a/apps/openlitespeed/data.yml b/apps/openlitespeed/data.yml new file mode 100644 index 00000000..48c3a649 --- /dev/null +++ b/apps/openlitespeed/data.yml @@ -0,0 +1,20 @@ +name: OpenLiteSpeed +tags: + - Web 服务器 +title: 一个高性能、轻量级、开源 的HTTP 服务器 +type: Web 服务器 +description: 一个高性能、轻量级、开源 的HTTP 服务器 +additionalProperties: + key: openlitespeed + name: OpenLiteSpeed + tags: + - Server + shortDescZh: 一个高性能、轻量级、开源 的HTTP 服务器 + shortDescEn: A high-performance, lightweight, open source HTTP server + type: runtime + crossVersionUpdate: true + limit: 1 + recommend: 3 + website: https://openlitespeed.org + github: https://github.com/litespeedtech/openlitespeed + document: https://openlitespeed.org/#install \ No newline at end of file diff --git a/apps/openlitespeed/latest/.env.sample b/apps/openlitespeed/latest/.env.sample new file mode 100644 index 00000000..0902e645 --- /dev/null +++ b/apps/openlitespeed/latest/.env.sample @@ -0,0 +1,6 @@ +CONTAINER_NAME="openlitespeed" +DATA_PATH="./data" +PANEL_APP_PORT_CONSOLE="40113" +PANEL_APP_PORT_HTTP="80" +PANEL_APP_PORT_HTTPS="443" +TIME_ZONE="Asia/Shanghai" diff --git a/apps/openlitespeed/latest/data.yml b/apps/openlitespeed/latest/data.yml new file mode 100644 index 00000000..2c19e306 --- /dev/null +++ b/apps/openlitespeed/latest/data.yml @@ -0,0 +1,40 @@ +additionalProperties: + formFields: + - default: 80 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP端口 + required: true + rule: paramPort + type: number + - default: 443 + edit: true + envKey: PANEL_APP_PORT_HTTPS + labelEn: HTTPS Port + labelZh: HTTPS端口 + required: true + rule: paramPort + type: number + - default: 40113 + edit: true + envKey: PANEL_APP_PORT_CONSOLE + labelEn: Console Port + labelZh: 控制台端口 + required: true + rule: paramPort + type: number + - default: ./data + disabled: true + envKey: DATA_PATH + labelEn: Data folder path + labelZh: 数据文件夹路径 + required: true + type: text + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + required: true + type: text diff --git a/apps/openlitespeed/latest/data/bin/acme.sh b/apps/openlitespeed/latest/data/bin/acme.sh new file mode 100644 index 00000000..2804e217 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/acme.sh @@ -0,0 +1,293 @@ +#!/usr/bin/env bash +EMAIL='' +NO_EMAIL='' +DOMAIN='' +INSTALL='' +UNINSTALL='' +TYPE=0 +CONT_NAME='litespeed' +ACME_SRC='https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh' +EPACE=' ' +RENEW='' +RENEW_ALL='' +FORCE='' +REVOKE='' +REMOVE='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echo 'You will need to install acme script at the first time.' + echo 'Please run acme.sh --install --email example@example.com' + ;; + "2") + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: acme.sh --domain example.com" + echo "${EPACE}${EPACE}will auto detect and apply for both example.com and www.example.com domains." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + echo -e "\033[1m Only for the First time\033[0m" + echow '--install --email [EMAIL_ADDR]' + echo "${EPACE}${EPACE}Will install ACME with the Email provided" + echow '-r, --renew' + echo "${EPACE}${EPACE}Renew a specific domain with -D or --domain parameter if posibile. To force renew, use -f parameter." + echow '-R, --renew-all' + echo "${EPACE}${EPACE}Renew all domains if possible. To force renew, use -f parameter." + echow '-f, -F, --force' + echo "${EPACE}${EPACE}Force renew for a specific domain or all domains." + echow '-v, --revoke' + echo "${EPACE}${EPACE}Revoke a domain." + echow '-V, --remove' + echo "${EPACE}${EPACE}Remove a domain." + exit 0 + ;; + "3") + echo 'Please run acme.sh --domain [DOMAIN_NAME] to apply certificate' + exit 0 + ;; + esac +} + +check_input(){ + if [ -z "${1}" ]; then + help_message 2 + fi +} + +domain_filter(){ + if [ -z "${1}" ]; then + help_message 3 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +email_filter(){ + CKREG="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$" + if [[ "${1}" =~ ${CKREG} ]] ; then + echo -e "[O] The E-mail \033[32m${1}\033[0m is valid." + else + echo -e "[X] The E-mail \e[31m${1}\e[39m is invalid" + exit 1 + fi +} + +cert_hook(){ + echo '[Start] Adding ACME hook' + docker compose exec ${CONT_NAME} su -s /bin/bash -c "certhookctl.sh" + echo '[End] Adding ACME hook' +} + +www_domain(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + DOMAIN=$(echo ${1} | cut -c 5-) + else + DOMAIN=${1} + fi + WWW_DOMAIN="www.${DOMAIN}" +} + +domain_verify(){ + curl -Is http://${DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${DOMAIN}\033[0m is accessible." + TYPE=1 + curl -Is http://${WWW_DOMAIN}/ | grep -i LiteSpeed > /dev/null 2>&1 + if [ ${?} = 0 ]; then + echo -e "[O] The domain name \033[32m${WWW_DOMAIN}\033[0m is accessible." + TYPE=2 + else + echo -e "[!] The domain name ${WWW_DOMAIN} is inaccessible." + fi + else + echo -e "[X] The domain name \e[31m${DOMAIN}\e[39m is inaccessible, please verify." + exit 1 + fi +} + +install_acme(){ + echo '[Start] Install ACME' + if [ "${1}" = 'true' ]; then + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs; \ + rm ~/acme.sh" + elif [ "${2}" != '' ]; then + email_filter "${2}" + docker compose exec litespeed su -c "cd; wget ${ACME_SRC}; chmod 755 acme.sh; \ + ./acme.sh --install --cert-home ~/.acme.sh/certs --accountemail ${2}; \ + rm ~/acme.sh" + else + help_message 1 + exit 1 + fi + echo '[End] Install ACME' +} + +uninstall_acme(){ + echo '[Start] Uninstall ACME' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --uninstall" + echo '[End] Uninstall ACME' + exit 0 +} + +check_acme(){ + echo '[Start] Checking ACME' + docker compose exec ${CONT_NAME} su -c "test -f /root/.acme.sh/acme.sh" + if [ ${?} != 0 ]; then + install_acme "${NO_EMAIL}" "${EMAIL}" + cert_hook + help_message 3 + fi + echo '[End] Checking ACME' +} + +lsws_restart(){ + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +doc_root_verify(){ + if [ "${DOC_ROOT}" = '' ]; then + DOC_PATH="/var/www/vhosts/${1}/html" + else + DOC_PATH="${DOC_ROOT}" + fi + docker compose exec ${CONT_NAME} su -c "[ -e ${DOC_PATH} ]" + if [ ${?} -eq 0 ]; then + echo -e "[O] The document root folder \033[32m${DOC_PATH}\033[0m does exist." + else + echo -e "[X] The document root folder \e[31m${DOC_PATH}\e[39m does not exist!" + exit 1 + fi +} + +install_cert(){ + echo '[Start] Apply Lets Encrypt Certificate' + if [ ${TYPE} = 1 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -w ${DOC_PATH}" + elif [ ${TYPE} = 2 ]; then + docker compose exec ${CONT_NAME} su -c "/root/.acme.sh/acme.sh --issue -d ${1} -d www.${1} -w ${DOC_PATH}" + else + echo 'unknown Type!' + exit 2 + fi + echo '[End] Apply Lets Encrypt Certificate' +} + +renew_acme(){ + echo '[Start] Renew ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1} --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew --domain ${1}" + fi + echo '[End] Renew ACME' + lsws_restart +} + +renew_all_acme(){ + echo '[Start] Renew all ACME' + if [ "${FORCE}" = 'true' ]; then + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all --force" + else + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --renew-all" + fi + echo '[End] Renew all ACME' + lsws_restart +} + +revoke(){ + echo '[Start] Revoke a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --revoke --domain ${1}" + echo '[End] Revoke a domain' + lsws_restart +} + +remove(){ + echo '[Start] Remove a domain' + docker compose exec ${CONT_NAME} su -c "~/.acme.sh/acme.sh --remove --domain ${1}" + echo '[End] Remove a domain' + lsws_restart +} + +main(){ + if [ "${RENEW_ALL}" = 'true' ]; then + renew_all_acme + exit 0 + elif [ "${RENEW}" = 'true' ]; then + renew_acme ${DOMAIN} + exit 0 + elif [ "${REVOKE}" = 'true' ]; then + revoke ${DOMAIN} + exit 0 + elif [ "${REMOVE}" = 'true' ]; then + remove ${DOMAIN} + exit 0 + fi + + check_acme + domain_filter ${DOMAIN} + www_domain ${DOMAIN} + domain_verify + doc_root_verify ${DOMAIN} + install_cert ${DOMAIN} + lsws_restart +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 2 + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -[iI] | --install ) + INSTALL=true + ;; + -[uU] | --uninstall ) + UNINSTALL=true + uninstall_acme + ;; + -[fF] | --force ) + FORCE=true + ;; + -[r] | --renew ) + RENEW=true + ;; + -[R] | --renew-all ) + RENEW_ALL=true + ;; + -[v] | --revoke ) + REVOKE=true + ;; + -[V] | --remove ) + REMOVE=true + ;; + -[eE] | --email ) shift + check_input "${1}" + EMAIL="${1}" + ;; + *) + help_message 2 + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/appinstall.sh b/apps/openlitespeed/latest/data/bin/appinstall.sh new file mode 100644 index 00000000..ba67d52d --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/appinstall.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +APP_NAME='' +DOMAIN='' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --app [app_name] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstall.sh -A wordpress -D example.com" + echo "${EPACE}${EPACE}Will install WordPress CMS under the example.com domain" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +app_download(){ + docker compose exec litespeed su -c "appinstallctl.sh --app ${1} --domain ${2}" + bash bin/webadmin.sh -r + exit 0 +} + +main(){ + app_download ${APP_NAME} ${DOMAIN} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + *) + help_message + ;; + esac + shift +done + +main \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/container/appinstallctl.sh b/apps/openlitespeed/latest/data/bin/container/appinstallctl.sh new file mode 100644 index 00000000..d79c63f1 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/container/appinstallctl.sh @@ -0,0 +1,660 @@ +#!/bin/bash +DEFAULT_VH_ROOT='/var/www/vhosts' +VH_DOC_ROOT='' +VHNAME='' +APP_NAME='' +DOMAIN='' +WWW_UID='' +WWW_GID='' +WP_CONST_CONF='' +PUB_IP=$(curl -s http://checkip.amazonaws.com) +DB_HOST='mysql' +PLUGINLIST="litespeed-cache.zip" +THEME='twentytwenty' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, -app [wordpress] -D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: appinstallctl.sh --app wordpress --domain example.com" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +linechange(){ + LINENUM=$(grep -n "${1}" ${2} | cut -d: -f 1) + if [ -n "${LINENUM}" ] && [ "${LINENUM}" -eq "${LINENUM}" ] 2>/dev/null; then + sed -i "${LINENUM}d" ${2} + sed -i "${LINENUM}i${3}" ${2} + fi +} + +ck_ed(){ + if [ ! -f /bin/ed ]; then + echo "Install ed package.." + apt-get install ed -y > /dev/null 2>&1 + fi +} + +ck_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo "Install unzip package.." + apt-get install unzip -y > /dev/null 2>&1 + fi +} + +get_owner(){ + WWW_UID=$(stat -c "%u" ${DEFAULT_VH_ROOT}) + WWW_GID=$(stat -c "%g" ${DEFAULT_VH_ROOT}) + if [ ${WWW_UID} -eq 0 ] || [ ${WWW_GID} -eq 0 ]; then + WWW_UID=1000 + WWW_GID=1000 + echo "Set owner to ${WWW_UID}" + fi +} + +get_db_pass(){ + if [ -f ${DEFAULT_VH_ROOT}/${1}/.db_pass ]; then + SQL_DB=$(grep -i Database ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_USER=$(grep -i Username ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + SQL_PASS=$(grep -i Password ${VH_ROOT}/.db_pass | awk -F ':' '{print $2}' | tr -d '"') + else + echo 'db pass file can not locate, skip wp-config pre-config.' + fi +} + +set_vh_docroot(){ + if [ "${VHNAME}" != '' ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${VHNAME}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + elif [ -d ${DEFAULT_VH_ROOT}/${1}/html ]; then + VH_ROOT="${DEFAULT_VH_ROOT}/${1}" + VH_DOC_ROOT="${DEFAULT_VH_ROOT}/${1}/html" + WP_CONST_CONF="${VH_DOC_ROOT}/wp-content/plugins/litespeed-cache/data/const.default.ini" + else + echo "${DEFAULT_VH_ROOT}/${1}/html does not exist, please add domain first! Abort!" + exit 1 + fi +} + +check_sql_native(){ + local COUNTER=0 + local LIMIT_NUM=100 + until [ "$(curl -v mysql:3306 2>&1 | grep -i 'native\|Connected')" ]; do + echo "Counter: ${COUNTER}/${LIMIT_NUM}" + COUNTER=$((COUNTER+1)) + if [ ${COUNTER} = 10 ]; then + echo '--- MySQL is starting, please wait... ---' + elif [ ${COUNTER} = ${LIMIT_NUM} ]; then + echo '--- MySQL is timeout, exit! ---' + exit 1 + fi + sleep 1 + done +} + +install_wp_plugin(){ + for PLUGIN in ${PLUGINLIST}; do + wget -q -P ${VH_DOC_ROOT}/wp-content/plugins/ https://downloads.wordpress.org/plugin/${PLUGIN} + if [ ${?} = 0 ]; then + ck_unzip + unzip -qq -o ${VH_DOC_ROOT}/wp-content/plugins/${PLUGIN} -d ${VH_DOC_ROOT}/wp-content/plugins/ + else + echo "${PLUGINLIST} FAILED to download" + fi + done + rm -f ${VH_DOC_ROOT}/wp-content/plugins/*.zip +} + +set_htaccess(){ + if [ ! -f ${VH_DOC_ROOT}/.htaccess ]; then + touch ${VH_DOC_ROOT}/.htaccess + fi + cat << EOM > ${VH_DOC_ROOT}/.htaccess +# BEGIN WordPress + +RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + +# END WordPress +EOM +} + +get_theme_name(){ + THEME_NAME=$(grep WP_DEFAULT_THEME ${VH_DOC_ROOT}/wp-includes/default-constants.php | grep -v '!' | awk -F "'" '{print $4}') + echo "${THEME_NAME}" | grep 'twenty' >/dev/null 2>&1 + if [ ${?} = 0 ]; then + THEME="${THEME_NAME}" + fi +} + +set_lscache(){ + cat << EOM > "${WP_CONST_CONF}" +; +; This is the predefined default LSCWP configuration file +; +; All the keys and values please refer \`src/const.cls.php\` +; +; Comments start with \`;\` +; +;; -------------------------------------------------- ;; +;; -------------- General ----------------- ;; +;; -------------------------------------------------- ;; +; O_AUTO_UPGRADE +auto_upgrade = false +; O_API_KEY +api_key = '' +; O_SERVER_IP +server_ip = '' +; O_NEWS +news = false +;; -------------------------------------------------- ;; +;; -------------- Cache ----------------- ;; +;; -------------------------------------------------- ;; +cache-priv = true +cache-commenter = true +cache-rest = true +cache-page_login = true +cache-favicon = true +cache-resources = true +cache-browser = false +cache-mobile = false +cache-mobile_rules = 'Mobile +Android +Silk/ +Kindle +BlackBerry +Opera Mini +Opera Mobi' +cache-exc_useragents = '' +cache-exc_cookies = '' +cache-exc_qs = '' +cache-exc_cat = '' +cache-exc_tag = '' +cache-force_uri = '' +cache-force_pub_uri = '' +cache-priv_uri = '' +cache-exc = '' +cache-exc_roles = '' +cache-drop_qs = 'fbclid +gclid +utm* +_ga' +cache-ttl_pub = 604800 +cache-ttl_priv = 1800 +cache-ttl_frontpage = 604800 +cache-ttl_feed = 604800 +; O_CACHE_TTL_REST +cache-ttl_rest = 604800 +cache-ttl_browser = 31557600 +cache-login_cookie = '' +cache-vary_group = '' +cache-ttl_status = '403 3600 +404 3600 +500 3600' +;; -------------------------------------------------- ;; +;; -------------- Purge ----------------- ;; +;; -------------------------------------------------- ;; +; O_PURGE_ON_UPGRADE +purge-upgrade = true +; O_PURGE_STALE +purge-stale = true +purge-post_all = false +purge-post_f = true +purge-post_h = true +purge-post_p = true +purge-post_pwrp = true +purge-post_a = true +purge-post_y = false +purge-post_m = true +purge-post_d = false +purge-post_t = true +purge-post_pt = true +purge-timed_urls = '' +purge-timed_urls_time = '' +purge-hook_all = 'switch_theme +wp_create_nav_menu +wp_update_nav_menu +wp_delete_nav_menu +create_term +edit_terms +delete_term +add_link +edit_link +delete_link' +;; -------------------------------------------------- ;; +;; -------------- ESI ----------------- ;; +;; -------------------------------------------------- ;; +; O_ESI +esi = false +; O_ESI_CACHE_ADMBAR +esi-cache_admbar = true +; O_ESI_CACHE_COMMFORM +esi-cache_commform = true +; O_ESI_NONCE +esi-nonce = 'stats_nonce +subscribe_nonce' +;; -------------------------------------------------- ;; +;; -------------- Utilities ----------------- ;; +;; -------------------------------------------------- ;; +util-heartbeat = true +util-instant_click = false +util-check_advcache = true +util-no_https_vary = false +;; -------------------------------------------------- ;; +;; -------------- Debug ----------------- ;; +;; -------------------------------------------------- ;; +; O_DEBUG_DISABLE_ALL +debug-disable_all = false +; O_DEBUG +debug = false +; O_DEBUG_IPS +debug-ips = '127.0.0.1' +; O_DEBUG_LEVEL +debug-level = false +; O_DEBUG_FILESIZE +debug-filesize = 3 +; O_DEBUG_COOKIE +debug-cookie = false +; O_DEBUG_COLLAPS_QS +debug-collaps_qs = false +; O_DEBUG_INC +debug-inc = '' +; O_DEBUG_EXC +debug-exc = '' +;; -------------------------------------------------- ;; +;; -------------- DB Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_DB_OPTM_REVISIONS_MAX +db_optm-revisions_max = 0 +; O_DB_OPTM_REVISIONS_AGE +db_optm-revisions_age = 0 +;; -------------------------------------------------- ;; +;; -------------- HTML Optm ----------------- ;; +;; -------------------------------------------------- ;; +; O_OPTM_CSS_MIN +optm-css_min = false +optm-css_inline_min = false +; O_OPTM_CSS_COMB +optm-css_comb = false +optm-css_comb_priority = false +; O_OPTM_CSS_HTTP2 +optm-css_http2 = false +optm-css_exc = '' +; O_OPTM_JS_MIN +optm-js_min = false +optm-js_inline_min = false +; O_OPTM_JS_COMB +optm-js_comb = false +optm-js_comb_priority = false +; O_OPTM_JS_HTTP2 +optm-js_http2 = false +; O_OPTM_EXC_JQ +optm-js_exc = '' +optm-ttl = 604800 +optm-html_min = false +optm-qs_rm = false +optm-ggfonts_rm = false +; O_OPTM_CSS_ASYNC +optm-css_async = false +; O_OPTM_CCSS_GEN +optm-ccss_gen = true +; O_OPTM_CCSS_ASYNC +optm-ccss_async = true +; O_OPTM_CSS_ASYNC_INLINE +optm-css_async_inline = true +; O_OPTM_CSS_FONT_DISPLAY +optm-css_font_display = false +; O_OPTM_JS_DEFER +optm-js_defer = false +; O_OPTM_JS_INLINE_DEFER +optm-js_inline_defer = false +optm-emoji_rm = false +optm-exc_jq = true +optm-ggfonts_async = false +optm-max_size = 2 +optm-rm_comment = false +optm-exc_roles = '' +optm-ccss_con = '' +optm-js_defer_exc = '' +; O_OPTM_DNS_PREFETCH +optm-dns_prefetch = '' +; O_OPTM_DNS_PREFETCH_CTRL +optm-dns_prefetch_ctrl = false +optm-exc = '' +; O_OPTM_CCSS_SEP_POSTTYPE +optm-ccss_sep_posttype = '' +; O_OPTM_CCSS_SEP_URI +optm-ccss_sep_uri = '' +;; -------------------------------------------------- ;; +;; -------------- Object Cache ----------------- ;; +;; -------------------------------------------------- ;; +object = true +object-kind = false +;object-host = 'localhost' +object-host = '/var/www/memcached.sock' +;object-port = 11211 +cache_object_port = '' +object-life = 360 +object-persistent = true +object-admin = true +object-transients = true +object-db_id = 0 +object-user = '' +object-pswd = '' +object-global_groups = 'users +userlogins +usermeta +user_meta +site-transient +site-options +site-lookup +blog-lookup +blog-details +rss +global-posts +blog-id-cache' +object-non_persistent_groups = 'comment +counts +plugins +wc_session_id' +;; -------------------------------------------------- ;; +;; -------------- Discussion ----------------- ;; +;; -------------------------------------------------- ;; +; O_DISCUSS_AVATAR_CACHE +discuss-avatar_cache = false +; O_DISCUSS_AVATAR_CRON +discuss-avatar_cron = false +; O_DISCUSS_AVATAR_CACHE_TTL +discuss-avatar_cache_ttl = 604800 +;; -------------------------------------------------- ;; +;; -------------- Media ----------------- ;; +;; -------------------------------------------------- ;; +; O_MEDIA_LAZY +media-lazy = false +; O_MEDIA_LAZY_PLACEHOLDER +media-lazy_placeholder = '' +; O_MEDIA_PLACEHOLDER_RESP +media-placeholder_resp = false +; O_MEDIA_PLACEHOLDER_RESP_COLOR +media-placeholder_resp_color = '#cfd4db' +; O_MEDIA_PLACEHOLDER_RESP_GENERATOR +media-placeholder_resp_generator = false +; O_MEDIA_PLACEHOLDER_RESP_SVG +media-placeholder_resp_svg = '' +; O_MEDIA_PLACEHOLDER_LQIP +media-placeholder_lqip = false +; O_MEDIA_PLACEHOLDER_LQIP_QUAL +media-placeholder_lqip_qual = 4 +; O_MEDIA_PLACEHOLDER_RESP_ASYNC +media-placeholder_resp_async = true +; O_MEDIA_IFRAME_LAZY +media-iframe_lazy = false +; O_MEDIA_LAZYJS_INLINE +media-lazyjs_inline = false +; O_MEDIA_LAZY_EXC +media-lazy_exc = '' +; O_MEDIA_LAZY_CLS_EXC +media-lazy_cls_exc = '' +; O_MEDIA_LAZY_PARENT_CLS_EXC +media-lazy_parent_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_CLS_EXC +media-iframe_lazy_cls_exc = '' +; O_MEDIA_IFRAME_LAZY_PARENT_CLS_EXC +media-iframe_lazy_parent_cls_exc = '' +; O_MEDIA_LAZY_URI_EXC +media-lazy_uri_exc = '' +;; -------------------------------------------------- ;; +;; -------------- Image Optm ----------------- ;; +;; -------------------------------------------------- ;; +img_optm-auto = false +img_optm-cron = true +img_optm-ori = true +img_optm-rm_bkup = false +img_optm-webp = false +img_optm-lossless = false +img_optm-exif = false +img_optm-webp_replace = false +img_optm-webp_attr = 'img.src +div.data-thumb +img.data-src +div.data-large_image +img.retina_logo_url +div.data-parallax-image +video.poster' +img_optm-webp_replace_srcset = false +img_optm-jpg_quality = 82 +;; -------------------------------------------------- ;; +;; -------------- Crawler ----------------- ;; +;; -------------------------------------------------- ;; +crawler = false +crawler-inc_posts = true +crawler-inc_pages = true +crawler-inc_cats = true +crawler-inc_tags = true +crawler-exc_cpt = '' +crawler-order_links = 'date_desc' +crawler-usleep = 500 +crawler-run_duration = 400 +crawler-run_interval = 600 +crawler-crawl_interval = 302400 +crawler-threads = 3 +crawler-timeout = 30 +crawler-load_limit = 1 +; O_CRAWLER_SITEMAP +crawler-sitemap = '' +; O_CRAWLER_DROP_DOMAIN +crawler-drop_domain = true +crawler-roles = '' +crawler-cookies = '' +;; -------------------------------------------------- ;; +;; -------------- Misc ----------------- ;; +;; -------------------------------------------------- ;; +; O_MISC_HTACCESS_FRONT +misc-htaccess_front = '' +; O_MISC_HTACCESS_BACK +misc-htaccess_back = '' +; O_MISC_HEARTBEAT_FRONT +misc-heartbeat_front = false +; O_MISC_HEARTBEAT_FRONT_TTL +misc-heartbeat_front_ttl = 60 +; O_MISC_HEARTBEAT_BACK +misc-heartbeat_back = false +; O_MISC_HEARTBEAT_BACK_TTL +misc-heartbeat_back_ttl = 60 +; O_MISC_HEARTBEAT_EDITOR +misc-heartbeat_editor = false +; O_MISC_HEARTBEAT_EDITOR_TTL +misc-heartbeat_editor_ttl = 15 +;; -------------------------------------------------- ;; +;; -------------- CDN ----------------- ;; +;; -------------------------------------------------- ;; +cdn = false +cdn-ori = '' +cdn-ori_dir = '' +cdn-exc = '' +cdn-remote_jq = false +cdn-quic = false +cdn-quic_email = '' +cdn-quic_key = '' +cdn-cloudflare = false +cdn-cloudflare_email = '' +cdn-cloudflare_key = '' +cdn-cloudflare_name = '' +cdn-cloudflare_zone = '' +; \`cdn-mapping\` needs to be put in the end with a section tag +;; -------------------------------------------------- ;; +;; -------------- CDN 2 ----------------- ;; +;; -------------------------------------------------- ;; +; <------------ CDN Mapping Example BEGIN --------------------> +; Need to keep the section tag \`[cdn-mapping]\` before list. +; +; NOTE 1) Need to set all child options to make all resources to be replaced without missing. +; NOTE 2) \`url[n]\` option must have to enable the row setting of \`n\`. +; NOTE 3) This section needs to be put in the end of this .ini file +; +; To enable the 2nd mapping record by default, please remove the \`;;\` in the related lines. +[cdn-mapping] +url[0] = '' +inc_js[0] = true +inc_css[0] = true +inc_img[0] = true +filetype[0] = '.aac +.css +.eot +.gif +.jpeg +.js +.jpg +.less +.mp3 +.mp4 +.ogg +.otf +.pdf +.png +.svg +.ttf +.woff' +;;url[1] = 'https://2nd_CDN_url.com/' +;;filetype[1] = '.webm' +; <------------ CDN Mapping Example END ------------------> +EOM + + THEME_PATH="${VH_DOC_ROOT}/wp-content/themes/${THEME}" + if [ ! -f ${THEME_PATH}/functions.php ]; then + cat >> "${THEME_PATH}/functions.php" <>/dev/null 2>&1 +2i +require_once( WP_CONTENT_DIR.'/../wp-admin/includes/plugin.php' ); +\$path = 'litespeed-cache/litespeed-cache.php' ; +if (!is_plugin_active( \$path )) { + activate_plugin( \$path ) ; + rename( __FILE__ . '.bk', __FILE__ ); +} +. +w +q +END + fi +} + +preinstall_wordpress(){ + if [ "${VHNAME}" != '' ]; then + get_db_pass ${VHNAME} + else + get_db_pass ${DOMAIN} + fi + if [ ! -f ${VH_DOC_ROOT}/wp-config.php ] && [ -f ${VH_DOC_ROOT}/wp-config-sample.php ]; then + cp ${VH_DOC_ROOT}/wp-config-sample.php ${VH_DOC_ROOT}/wp-config.php + NEWDBPWD="define('DB_PASSWORD', '${SQL_PASS}');" + linechange 'DB_PASSWORD' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_USER', '${SQL_USER}');" + linechange 'DB_USER' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + NEWDBPWD="define('DB_NAME', '${SQL_DB}');" + linechange 'DB_NAME' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + #NEWDBPWD="define('DB_HOST', '${PUB_IP}');" + NEWDBPWD="define('DB_HOST', '${DB_HOST}');" + linechange 'DB_HOST' ${VH_DOC_ROOT}/wp-config.php "${NEWDBPWD}" + elif [ -f ${VH_DOC_ROOT}/wp-config.php ]; then + echo "${VH_DOC_ROOT}/wp-config.php already exist, exit !" + exit 1 + else + echo 'Skip!' + exit 2 + fi +} + +app_wordpress_dl(){ + if [ ! -f "${VH_DOC_ROOT}/wp-config.php" ] && [ ! -f "${VH_DOC_ROOT}/wp-config-sample.php" ]; then + wp core download \ + --allow-root \ + --quiet + else + echo 'wordpress already exist, abort!' + exit 1 + fi +} + +change_owner(){ + if [ "${VHNAME}" != '' ]; then + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${VHNAME} + else + chown -R ${WWW_UID}:${WWW_GID} ${DEFAULT_VH_ROOT}/${DOMAIN} + fi +} + +main(){ + set_vh_docroot ${DOMAIN} + get_owner + cd ${VH_DOC_ROOT} + if [ "${APP_NAME}" = 'wordpress' ] || [ "${APP_NAME}" = 'wp' ]; then + check_sql_native + app_wordpress_dl + preinstall_wordpress + install_wp_plugin + set_htaccess + get_theme_name + set_lscache + change_owner + exit 0 + else + echo "APP: ${APP_NAME} not support, exit!" + exit 1 + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -app | --app) shift + check_input "${1}" + APP_NAME="${1}" + ;; + -[dD] | -domain | --domain) shift + check_input "${1}" + DOMAIN="${1}" + ;; + -vhname | --vhname) shift + VHNAME="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/latest/data/bin/container/certhookctl.sh b/apps/openlitespeed/latest/data/bin/container/certhookctl.sh new file mode 100644 index 00000000..18be0965 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/container/certhookctl.sh @@ -0,0 +1,18 @@ +#!/bin/bash +BOTCRON='/var/spool/cron/crontabs/root' + +cert_hook(){ + grep 'acme' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + grep 'lswsctrl' ${BOTCRON} >/dev/null + if [ ${?} = 0 ]; then + echo 'Hook already exist, skip!' + else + sed -i 's/--cron/--cron --renew-hook "\/usr\/local\/lsws\/bin\/lswsctrl restart"/g' ${BOTCRON} + fi + else + echo "[X] ${BOTCRON} does not exist, please check it later!" + fi +} + +cert_hook \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/container/domainctl.sh b/apps/openlitespeed/latest/data/bin/container/domainctl.sh new file mode 100644 index 00000000..75539ef0 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/container/domainctl.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +CK_RESULT='' +LSDIR='/usr/local/lsws' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-A, --add [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will add domain to listener and creat a virtual host from template" + echow '-D, --del [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Will delete domain from listener" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help." +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +dot_escape(){ + ESCAPE=$(echo ${1} | sed 's/\./\\./g') +} + +check_duplicate(){ + CK_RESULT=$(grep -E "${1}" ${2}) +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 ${1} ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +check_www(){ + CHECK_WWW=$(echo ${1} | cut -c1-4) + if [[ ${CHECK_WWW} == www. ]] ; then + echo 'www domain shoudnt be passed!' + exit 1 + fi +} + +www_domain(){ + check_www ${1} + WWW_DOMAIN=$(echo www.${1}) +} + +add_ls_domain(){ + fst_match_line 'docker.xml' ${LS_HTTPD_CONF} + NEWNUM=$((FIRST_LINE_NUM+2)) + sed -i "${NEWNUM}i \ \ \ \ \ \ \n \ \ \ \ \ \ \ ${DOMAIN}\n \ \ \ \ \ \ \ ${DOMAIN},${WWW_DOMAIN}\n \ \ \ \ \ \ " ${LS_HTTPD_CONF} +} + +add_ols_domain(){ + perl -0777 -p -i -e 's/(vhTemplate docker \{[^}]+)\}*(^.*listeners.*$)/\1$2 + member '${DOMAIN}' { + vhDomain '${DOMAIN},${WWW_DOMAIN}' + }/gmi' ${OLS_HTTPD_CONF} +} + +add_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + www_domain ${1} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" != '' ]; then + echo "# It appears the domain already exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + add_ls_domain + add_ols_domain +} + +del_ls_domain(){ + fst_match_line "*${1}" ${LS_HTTPD_CONF} + FIRST_LINE_NUM=$((FIRST_LINE_NUM-1)) + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} +} + +del_ols_domain(){ + fst_match_line ${1} ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} +} + +del_domain(){ + check_lsv + dot_escape ${1} + DOMAIN=${ESCAPE} + if [ "${LSV}" = 'lsws' ]; then + check_duplicate "vhDomain.*${DOMAIN}" ${LS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${LS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + elif [ "${LSV}" = 'openlitespeed' ]; then + check_duplicate "member.*${DOMAIN}" ${OLS_HTTPD_CONF} + if [ "${CK_RESULT}" = '' ]; then + echo "# Domain non-exist! Check the ${OLS_HTTPD_CONF} if you believe this is a mistake!" + exit 1 + fi + fi + del_ls_domain ${1} + del_ols_domain ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/container/owaspctl.sh b/apps/openlitespeed/latest/data/bin/container/owaspctl.sh new file mode 100644 index 00000000..72fd8e59 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/container/owaspctl.sh @@ -0,0 +1,236 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +OWASP_DIR="${LSDIR}/conf/owasp" +RULE_FILE='modsec_includes.conf' +LS_HTTPD_CONF="${LSDIR}/conf/httpd_config.xml" +OLS_HTTPD_CONF="${LSDIR}/conf/httpd_config.conf" +EPACE=' ' +OWASP_V='3.3.4' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-E, --enable' + echo "${EPACE}${EPACE}Will Enable mod_secure module with latest OWASP version of rules" + echow '-D, --disable' + echo "${EPACE}${EPACE}Will Disable mod_secure module with latest OWASP version of rules" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_lsv(){ + if [ -f ${LSDIR}/bin/openlitespeed ]; then + LSV='openlitespeed' + elif [ -f ${LSDIR}/bin/litespeed ]; then + LSV='lsws' + else + echo 'Version not exist, abort!' + exit 1 + fi +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +mk_owasp_dir(){ + if [ -d ${OWASP_DIR} ] ; then + rm -rf ${OWASP_DIR} + fi + mkdir -p ${OWASP_DIR} + if [ ${?} -ne 0 ] ; then + echo "Unable to create directory: ${OWASP_DIR}, exit!" + exit 1 + fi +} + +fst_match_line(){ + FIRST_LINE_NUM=$(grep -n -m 1 "${1}" ${2} | awk -F ':' '{print $1}') +} +fst_match_after(){ + FIRST_NUM_AFTER=$(tail -n +${1} ${2} | grep -n -m 1 ${3} | awk -F ':' '{print $1}') +} +lst_match_line(){ + fst_match_after ${1} ${2} ${3} + LAST_LINE_NUM=$((${FIRST_LINE_NUM}+${FIRST_NUM_AFTER}-1)) +} + +enable_ols_modsec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "Already configured for modsecurity." + else + echo 'Enable modsecurity' + sed -i "s=module cache=module mod_security {\nmodsecurity on\ + \nmodsecurity_rules \`\nSecRuleEngine On\n\`\nmodsecurity_rules_file \ + ${OWASP_DIR}/${RULE_FILE}\n ls_enabled 1\n}\ + \n\nmodule cache=" ${OLS_HTTPD_CONF} + fi +} + +enable_ls_modsec(){ + grep '1' ${LS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo "LSWS already configured for modsecurity" + else + echo 'Enable modsecurity' + sed -i \ + "s=0=1=" ${LS_HTTPD_CONF} + sed -i \ + "s==\n\ + \n\ + ModSec\n\ + 1\n\ + include ${OWASP_DIR}/modsec_includes.conf\n\ + =" ${LS_HTTPD_CONF} + fi +} + +enable_modsec(){ + if [ "${LSV}" = 'lsws' ]; then + enable_ls_modsec + elif [ "${LSV}" = 'openlitespeed' ]; then + enable_ols_modsec + fi +} + +disable_ols_modesec(){ + grep 'module mod_security {' ${OLS_HTTPD_CONF} >/dev/null 2>&1 + if [ ${?} -eq 0 ] ; then + echo 'Disable modsecurity' + fst_match_line 'module mod_security' ${OLS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${OLS_HTTPD_CONF} '}' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${OLS_HTTPD_CONF} + else + echo 'Already disabled for modsecurity' + fi +} + +disable_ls_modesec(){ + grep '0' ${LS_HTTPD_CONF} + if [ ${?} -eq 0 ] ; then + echo 'Already disabled for modsecurity' + else + echo 'Disable modsecurity' + sed -i \ + "s=1=0=" ${LS_HTTPD_CONF} + fst_match_line 'censorshipRuleSet' ${LS_HTTPD_CONF} + lst_match_line ${FIRST_LINE_NUM} ${LS_HTTPD_CONF} '/censorshipRuleSet' + sed -i "${FIRST_LINE_NUM},${LAST_LINE_NUM}d" ${LS_HTTPD_CONF} + fi +} + +disable_modsec(){ + check_lsv + if [ "${LSV}" = 'lsws' ]; then + disable_ls_modesec + elif [ "${LSV}" = 'openlitespeed' ]; then + disable_ols_modesec + fi +} + +install_unzip(){ + if [ ! -f /usr/bin/unzip ]; then + echo 'Install Unzip' + apt update >/dev/null 2>&1 + apt-get install unzip -y >/dev/null 2>&1 + fi +} + +install_owasp(){ + cd ${OWASP_DIR} + echo 'Download OWASP rules' + wget -q https://github.com/coreruleset/coreruleset/archive/refs/tags/v${OWASP_V}.zip + unzip -qq v${OWASP_V}.zip + rm -f v${OWASP_V}.zip + mv coreruleset-* owasp-modsecurity-crs +} + +configure_owasp(){ + echo 'Config OWASP rules.' + cd ${OWASP_DIR} + echo "include modsecurity.conf +include owasp-modsecurity-crs/crs-setup.conf +include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf +include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf +include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf +include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf +include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf +include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf +include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf +include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf +include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf +include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf +include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf +include owasp-modsecurity-crs/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf +include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf +include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf +include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf +include owasp-modsecurity-crs/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf +include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf +include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf +include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf +include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf +include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf +include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf +include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf">modsec_includes.conf + echo "SecRuleEngine On">modsecurity.conf + cd ${OWASP_DIR}/owasp-modsecurity-crs + if [ -f crs-setup.conf.example ]; then + mv crs-setup.conf.example crs-setup.conf + fi + cd ${OWASP_DIR}/owasp-modsecurity-crs/rules + if [ -f REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example ]; then + mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf + fi + if [ -f RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example ]; then + mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf + fi +} + +main_owasp(){ + mk_owasp_dir + install_unzip + install_owasp + configure_owasp + check_lsv + enable_modsec +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[eE] | -enable | --enable) + main_owasp + ;; + -[dD] | -disable | --disable) + disable_modsec + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/container/serialctl.sh b/apps/openlitespeed/latest/data/bin/container/serialctl.sh new file mode 100644 index 00000000..42e312dc --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/container/serialctl.sh @@ -0,0 +1,84 @@ +#!/bin/bash +LSDIR='/usr/local/lsws' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply and register the serial to LSWS." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +backup_old(){ + if [ -f ${1} ] && [ ! -f ${1}_old ]; then + mv ${1} ${1}_old + fi +} + +detect_ols(){ + if [ -e ${LSDIR}/bin/openlitespeed ]; then + echo '[X] Detect OpenLiteSpeed, abort!' + exit 1 + fi +} + +apply_serial(){ + detect_ols + check_input ${1} + echo ${1} | grep -i 'trial' >/dev/null + if [ ${?} = 0 ]; then + echo 'Apply Trial License' + if [ ! -e ${LSDIR}/conf/serial.no ] && [ ! -e ${LSDIR}/conf/license.key ]; then + rm -f ${LSDIR}/conf/trial.key* + wget -P ${LSDIR}/conf -q http://license.litespeedtech.com/reseller/trial.key + echo 'Apply trial finished' + else + echo "Please backup and remove your existing license, apply abort!" + exit 1 + fi + else + echo "Apply Serial number: ${1}" + backup_old ${LSDIR}/conf/serial.no + backup_old ${LSDIR}/conf/license.key + backup_old ${LSDIR}/conf/trial.key + echo "${1}" > ${LSDIR}/conf/serial.no + ${LSDIR}/bin/lshttpd -r + if [ -f ${LSDIR}/conf/license.key ]; then + echo '[O] Apply success' + else + echo '[X] Apply failed, please check!' + exit 1 + fi + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[sS] | -serial | --serial) shift + apply_serial "${1}" + ;; + *) + help_message + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/database.sh b/apps/openlitespeed/latest/data/bin/database.sh new file mode 100644 index 00000000..ec1462d4 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/database.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +source .env + +DOMAIN='' +SQL_DB='' +SQL_USER='' +SQL_PASS='' +ANY="'%'" +SET_OK=0 +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '-D, --domain [DOMAIN_NAME]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com" + echo "${EPACE}${EPACE}Will auto generate Database/username/password for the domain" + echow '-D, --domain [DOMAIN_NAME] -U, --user [xxx] -P, --password [xxx] -DB, --database [xxx]' + echo "${EPACE}${EPACE}Example: database.sh -D example.com -U USERNAME -P PASSWORD -DB DATABASENAME" + echo "${EPACE}${EPACE}Will create Database/username/password by given" + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +specify_name(){ + check_input ${SQL_USER} + check_input ${SQL_PASS} + check_input ${SQL_DB} +} + +auto_name(){ + SQL_DB="${TRANSNAME}" + SQL_USER="${TRANSNAME}" + SQL_PASS="'${RANDOM_PASS}'" +} + +gen_pass(){ + RANDOM_PASS="$(openssl rand -base64 12)" +} + +trans_name(){ + TRANSNAME=$(echo ${1} | tr -d '.&&-') +} + +display_credential(){ + if [ ${SET_OK} = 0 ]; then + echo "Database: ${SQL_DB}" + echo "Username: ${SQL_USER}" + echo "Password: $(echo ${SQL_PASS} | tr -d "'")" + fi +} + +store_credential(){ + if [ -d "./sites/${1}" ]; then + if [ -f ./sites/${1}/.db_pass ]; then + mv ./sites/${1}/.db_pass ./sites/${1}/.db_pass.bk + fi + cat > "./sites/${1}/.db_pass" << EOT +"Database":"${SQL_DB}" +"Username":"${SQL_USER}" +"Password":"$(echo ${SQL_PASS} | tr -d "'")" +EOT + else + echo "./sites/${1} not found, abort credential store!" + fi +} + +check_db_access(){ + docker compose exec -T mysql su -c "mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e 'status'" >/dev/null 2>&1 + if [ ${?} != 0 ]; then + echo '[X] DB access failed, please check!' + exit 1 + fi +} + +check_db_exist(){ + docker compose exec -T mysql su -c "test -e /var/lib/mysql/${1}" + if [ ${?} = 0 ]; then + echo "Database ${1} already exist, skip DB creation!" + exit 0 + fi +} + +db_setup(){ + docker compose exec -T mysql su -c 'mysql -uroot -p${MYSQL_ROOT_PASSWORD} \ + -e "CREATE DATABASE '${SQL_DB}';" \ + -e "GRANT ALL PRIVILEGES ON '${SQL_DB}'.* TO '${SQL_USER}'@'${ANY}' IDENTIFIED BY '${SQL_PASS}';" \ + -e "FLUSH PRIVILEGES;"' + SET_OK=${?} +} + +auto_setup_main(){ + check_input ${DOMAIN} + gen_pass + trans_name ${DOMAIN} + auto_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +specify_setup_main(){ + specify_name + check_db_exist ${SQL_DB} + check_db_access + db_setup + display_credential + store_credential ${DOMAIN} +} + +main(){ + if [ "${SQL_USER}" != '' ] && [ "${SQL_PASS}" != '' ] && [ "${SQL_DB}" != '' ]; then + specify_setup_main + else + auto_setup_main + fi +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[dD] | -domain| --domain) shift + DOMAIN="${1}" + ;; + -[uU] | -user | --user) shift + SQL_USER="${1}" + ;; + -[pP] | -password| --password) shift + SQL_PASS="'${1}'" + ;; + -db | -DB | -database| --database) shift + SQL_DB="${1}" + ;; + *) + help_message + ;; + esac + shift +done +main diff --git a/apps/openlitespeed/latest/data/bin/demosite.sh b/apps/openlitespeed/latest/data/bin/demosite.sh new file mode 100644 index 00000000..91474647 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/demosite.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +source .env +APP_NAME='wordpress' +CONT_NAME='litespeed' +DOC_FD='' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + case ${1} in + "1") + echow "Script will get 'DOMAIN' and 'database' info from .env file, then auto setup virtual host and the wordpress site for you." + exit 0 + ;; + "2") + echow 'Service finished, enjoy your accelarated LiteSpeed server!' + ;; + esac +} + +domain_filter(){ + if [ ! -n "${DOMAIN}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + fi + DOMAIN="${1}" + DOMAIN="${DOMAIN#http://}" + DOMAIN="${DOMAIN#https://}" + DOMAIN="${DOMAIN#ftp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#scp://}" + DOMAIN="${DOMAIN#sftp://}" + DOMAIN=${DOMAIN%%/*} +} + +gen_root_fd(){ + DOC_FD="./sites/${1}/" + if [ -d "./sites/${1}" ]; then + echo -e "[O] The root folder \033[32m${DOC_FD}\033[0m exist." + else + echo "Creating - document root." + bash bin/domain.sh -add ${1} + echo "Finished - document root." + fi +} + +create_db(){ + if [ ! -n "${MYSQL_DATABASE}" ] || [ ! -n "${MYSQL_USER}" ] || [ ! -n "${MYSQL_PASSWORD}" ]; then + echo "Parameters not supplied, please check!" + exit 1 + else + bash bin/database.sh -D ${1} -U ${MYSQL_USER} -P ${MYSQL_PASSWORD} -DB ${MYSQL_DATABASE} + fi +} + +store_credential(){ + if [ -f ${DOC_FD}/.db_pass ]; then + echo '[O] db file exist!' + else + echo 'Storing database parameter' + cat > "${DOC_FD}/.db_pass" << EOT +"Database":"${MYSQL_DATABASE}" +"Username":"${MYSQL_USER}" +"Password":"$(echo ${MYSQL_PASSWORD} | tr -d "'")" +EOT + fi +} + +app_download(){ + docker compose exec -T ${CONT_NAME} su -c "appinstallctl.sh --app ${1} --domain ${2}" +} + +lsws_restart(){ + bash bin/webadmin.sh -r +} + +main(){ + domain_filter ${DOMAIN} + gen_root_fd ${DOMAIN} + create_db ${DOMAIN} + store_credential + app_download ${APP_NAME} ${DOMAIN} + lsws_restart + help_message 2 +} + +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message 1 + ;; + *) + help_message 1 + ;; + esac + shift +done +main \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/dev/list-flagged-files.sh b/apps/openlitespeed/latest/data/bin/dev/list-flagged-files.sh new file mode 100644 index 00000000..bde4f25f --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/dev/list-flagged-files.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +git ls-files -v|grep '^S' diff --git a/apps/openlitespeed/latest/data/bin/dev/no-skip-worktree-conf.sh b/apps/openlitespeed/latest/data/bin/dev/no-skip-worktree-conf.sh new file mode 100644 index 00000000..9bf83e7c --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/dev/no-skip-worktree-conf.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --no-skip-worktree" \; diff --git a/apps/openlitespeed/latest/data/bin/dev/skip-worktree-conf.sh b/apps/openlitespeed/latest/data/bin/dev/skip-worktree-conf.sh new file mode 100644 index 00000000..18b16184 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/dev/skip-worktree-conf.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +find conf -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd && git ls-files -z ${pwd} | xargs -0 git update-index --skip-worktree" \; + diff --git a/apps/openlitespeed/latest/data/bin/domain.sh b/apps/openlitespeed/latest/data/bin/domain.sh new file mode 100644 index 00000000..d99dca40 --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/domain.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow "-A, --add [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -A example.com, will add the domain to Listener and auto create a new virtual host." + echow "-D, --del [domain_name]" + echo "${EPACE}${EPACE}Example: domain.sh -D example.com, will delete the domain from Listener." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +add_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --add ${1}" + if [ ! -d "./sites/${1}" ]; then + mkdir -p ./sites/${1}/{html,logs,certs} + fi + bash bin/webadmin.sh -r +} + +del_domain(){ + check_input ${1} + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c "cd /usr/local/lsws/conf && domainctl.sh --del ${1}" + bash bin/webadmin.sh -r +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[aA] | -add | --add) shift + add_domain ${1} + ;; + -[dD] | -del | --del | --delete) shift + del_domain ${1} + ;; + *) + help_message + ;; + esac + shift +done + \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/bin/webadmin.sh b/apps/openlitespeed/latest/data/bin/webadmin.sh new file mode 100644 index 00000000..18e108ec --- /dev/null +++ b/apps/openlitespeed/latest/data/bin/webadmin.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +CONT_NAME='litespeed' +EPACE=' ' + +echow(){ + FLAG=${1} + shift + echo -e "\033[1m${EPACE}${FLAG}\033[0m${@}" +} + +help_message(){ + echo -e "\033[1mOPTIONS\033[0m" + echow '[Enter Your PASSWORD]' + echo "${EPACE}${EPACE}Example: webadmin.sh MY_SECURE_PASS, to update web admin password immediatly." + echow '-R, --restart' + echo "${EPACE}${EPACE}Will gracefully restart LiteSpeed Web Server." + echow '-M, --mod-secure [enable|disable]' + echo "${EPACE}${EPACE}Example: webadmin.sh -M enable, will enable and apply Mod_Secure OWASP rules on server" + echow '-U, --upgrade' + echo "${EPACE}${EPACE}Will upgrade web server to latest stable version" + echow '-S, --serial [YOUR_SERIAL|TRIAL]' + echo "${EPACE}${EPACE}Will apply your serial number to LiteSpeed Web Server." + echow '-H, --help' + echo "${EPACE}${EPACE}Display help and exit." + exit 0 +} + +check_input(){ + if [ -z "${1}" ]; then + help_message + exit 1 + fi +} + +lsws_restart(){ + docker compose exec -T ${CONT_NAME} su -c '/usr/local/lsws/bin/lswsctrl restart >/dev/null' +} + +apply_serial(){ + docker compose exec ${CONT_NAME} su -c "serialctl.sh --serial ${1}" + lsws_restart +} + +mod_secure(){ + if [ "${1}" = 'enable' ] || [ "${1}" = 'Enable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --enable" + lsws_restart + elif [ "${1}" = 'disable' ] || [ "${1}" = 'Disable' ]; then + docker compose exec ${CONT_NAME} su -s /bin/bash root -c "owaspctl.sh --disable" + lsws_restart + else + help_message + fi +} + +ls_upgrade(){ + echo 'Upgrade web server to latest stable version.' + docker compose exec ${CONT_NAME} su -c '/usr/local/lsws/admin/misc/lsup.sh 2>/dev/null' +} + +set_web_admin(){ + echo 'Update web admin password.' + local LSADPATH='/usr/local/lsws/admin' + docker compose exec ${CONT_NAME} su -s /bin/bash lsadm -c \ + 'if [ -e /usr/local/lsws/admin/fcgi-bin/admin_php ]; then \ + echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + else echo "admin:$('${LSADPATH}'/fcgi-bin/admin_php5 -q '${LSADPATH}'/misc/htpasswd.php '${1}')" > '${LSADPATH}'/conf/htpasswd; \ + fi'; +} + +main(){ + set_web_admin ${1} +} + +check_input ${1} +while [ ! -z "${1}" ]; do + case ${1} in + -[hH] | -help | --help) + help_message + ;; + -[rR] | -restart | --restart) + lsws_restart + ;; + -M | -mode-secure | --mod-secure) shift + mod_secure ${1} + ;; + -lsup | --lsup | --upgrade | -U) shift + ls_upgrade + ;; + -[sS] | -serial | --serial) shift + apply_serial ${1} + ;; + *) + main ${1} + ;; + esac + shift +done \ No newline at end of file diff --git a/apps/openlitespeed/latest/data/sites/.gitignore b/apps/openlitespeed/latest/data/sites/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/apps/openlitespeed/latest/data/sites/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/apps/openlitespeed/latest/docker-compose.yml b/apps/openlitespeed/latest/docker-compose.yml new file mode 100644 index 00000000..d7977118 --- /dev/null +++ b/apps/openlitespeed/latest/docker-compose.yml @@ -0,0 +1,30 @@ +version: '3' +services: + litespeed: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + logging: + driver: none + volumes: + - ${DATA_PATH}/lsws/conf:/usr/local/lsws/conf + - ${DATA_PATH}/lsws/admin-conf:/usr/local/lsws/admin/conf + - ${DATA_PATH}/bin/container:/usr/local/bin + - ${DATA_PATH}/sites:/var/www/vhosts/ + - ${DATA_PATH}/acme:/root/.acme.sh/ + - ${DATA_PATH}/logs:/usr/local/lsws/logs/ + ports: + - "${PANEL_APP_PORT_HTTP}:80" + - "${PANEL_APP_PORT_HTTPS}:443" + - "${PANEL_APP_PORT_HTTPS}:443/udp" + - "${PANEL_APP_PORT_CONSOLE}:7080" + environment: + - TZ=${TIME_ZONE} + image: litespeedtech/openlitespeed:latest + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/openlitespeed/logo.png b/apps/openlitespeed/logo.png new file mode 100644 index 00000000..dba1cecc Binary files /dev/null and b/apps/openlitespeed/logo.png differ diff --git a/docs/app-list.png b/docs/app-list.png index 406696ce..f46b1850 100644 Binary files a/docs/app-list.png and b/docs/app-list.png differ diff --git a/docs/applist-20230810-2.png:Zone.Identifier b/docs/applist-20230810-2.png:Zone.Identifier deleted file mode 100644 index a45e1ac4..00000000 --- a/docs/applist-20230810-2.png:Zone.Identifier +++ /dev/null @@ -1,2 +0,0 @@ -[ZoneTransfer] -ZoneId=3