| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 | #!/usr/bin/env bash# -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-# SPDX-License-Identifier: AGPL-3.0-or-later# shellcheck disable=SC2001# shellcheck source=utils/lib.shsource "$(dirname "${BASH_SOURCE[0]}")/lib.sh"# shellcheck source=utils/brand.envsource "${REPO_ROOT}/utils/brand.env"source_dot_configsource "${REPO_ROOT}/utils/lxc-searx.env"in_container && lxc_set_suite_env# ----------------------------------------------------------------------------# config# ----------------------------------------------------------------------------PUBLIC_URL="${PUBLIC_URL:-http://$(uname -n)/searx}"SEARX_INTERNAL_HTTP="${SEARX_INTERNAL_HTTP:-127.0.0.1:8888}"SEARX_URL_PATH="${SEARX_URL_PATH:-$(echo "${PUBLIC_URL}" \| sed -e 's,^.*://[^/]*\(/.*\),\1,g')}"[[ "${SEARX_URL_PATH}" == "${PUBLIC_URL}" ]] && SEARX_URL_PATH=/SEARX_INSTANCE_NAME="${SEARX_INSTANCE_NAME:-searx@$(echo "$PUBLIC_URL" \| sed -e 's,^.*://\([^\:/]*\).*,\1,g') }"SERVICE_NAME="searx"SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}"SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}"# shellcheck disable=SC2034SERVICE_GROUP="${SERVICE_USER}"GIT_BRANCH="${GIT_BRANCH:-master}"SEARX_PYENV="${SERVICE_HOME}/searx-pyenv"SEARX_SRC="${SERVICE_HOME}/searx-src"SEARX_SETTINGS_PATH="/etc/searx/settings.yml"SEARX_SETTINGS_TEMPLATE="${SEARX_SETTINGS_TEMPLATE:-${REPO_ROOT}/utils/templates/etc/searx/use_default_settings.yml}"SEARX_UWSGI_APP="searx.ini"# shellcheck disable=SC2034SEARX_UWSGI_SOCKET="/run/uwsgi/app/searx/socket"# apt packagesSEARX_PACKAGES_debian="\python3-dev python3-babel python3-venvuwsgi uwsgi-plugin-python3git build-essential libxslt-dev zlib1g-dev libffi-dev libssl-devshellcheck"BUILD_PACKAGES_debian="\firefox graphviz imagemagick texlive-xetex librsvg2-bintexlive-latex-recommended texlive-extra-utils fonts-dejavulatexmk"# pacman packagesSEARX_PACKAGES_arch="\python python-pip python-lxml python-babeluwsgi uwsgi-plugin-pythongit base-devel libxml2shellcheck"BUILD_PACKAGES_arch="\firefox graphviz imagemagick texlive-bin extra/librsvgtexlive-core texlive-latexextra ttf-dejavu"# dnf packagesSEARX_PACKAGES_fedora="\python python-pip python-lxml python-babeluwsgi uwsgi-plugin-python3git @development-tools libxml2ShellCheck"BUILD_PACKAGES_fedora="\firefox graphviz graphviz-gd ImageMagick librsvg2-toolstexlive-xetex-bin texlive-collection-fontsrecommendedtexlive-collection-latex dejavu-sans-fonts dejavu-serif-fontsdejavu-sans-mono-fonts"# yum packagesSEARX_PACKAGES_centos="\python36 python36-pip python36-lxml python-babeluwsgi uwsgi-plugin-python3git @development-tools libxml2ShellCheck"BUILD_PACKAGES_centos="\firefox graphviz graphviz-gd ImageMagick librsvg2-toolstexlive-xetex-bin texlive-collection-fontsrecommendedtexlive-collection-latex dejavu-sans-fonts dejavu-serif-fontsdejavu-sans-mono-fonts"case $DIST_ID-$DIST_VERS in    ubuntu-16.04|ubuntu-18.04)        SEARX_PACKAGES="${SEARX_PACKAGES_debian}"        BUILD_PACKAGES="${BUILD_PACKAGES_debian}"        APACHE_PACKAGES="$APACHE_PACKAGES libapache2-mod-proxy-uwsgi"        ;;    ubuntu-20.04)        # https://askubuntu.com/a/1224710        SEARX_PACKAGES="${SEARX_PACKAGES_debian} python-is-python3"        BUILD_PACKAGES="${BUILD_PACKAGES_debian}"        ;;    ubuntu-*|debian-*)        SEARX_PACKAGES="${SEARX_PACKAGES_debian}"        BUILD_PACKAGES="${BUILD_PACKAGES_debian}"        ;;    arch-*)        SEARX_PACKAGES="${SEARX_PACKAGES_arch}"        BUILD_PACKAGES="${BUILD_PACKAGES_arch}"        ;;    fedora-*)        SEARX_PACKAGES="${SEARX_PACKAGES_fedora}"        BUILD_PACKAGES="${BUILD_PACKAGES_fedora}"        ;;    centos-7)        SEARX_PACKAGES="${SEARX_PACKAGES_centos}"        BUILD_PACKAGES="${BUILD_PACKAGES_centos}"        ;;esac# Apache SettingsAPACHE_SEARX_SITE="searx.conf"# shellcheck disable=SC2034CONFIG_FILES=(    "${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}")# shellcheck disable=SC2034CONFIG_BACKUP_ENCRYPTED=(    "${SEARX_SETTINGS_PATH}")# ----------------------------------------------------------------------------usage() {# ----------------------------------------------------------------------------    # shellcheck disable=SC1117    cat <<EOFusage::  $(basename "$0") shell  $(basename "$0") install    [all|user|searx-src|pyenv|uwsgi|packages|settings|buildhost]  $(basename "$0") update     [searx]  $(basename "$0") remove     [all|user|pyenv|searx-src]  $(basename "$0") activate   [service]  $(basename "$0") deactivate [service]  $(basename "$0") inspect    [service]  $(basename "$0") option     [debug-[on|off]|image-proxy-[on|off]|result-proxy <url> <key>]  $(basename "$0") apache     [install|remove]shell  start interactive shell from user ${SERVICE_USER}install / remove  :all:        complete (de-) installation of searx service  :user:       add/remove service user '$SERVICE_USER' ($SERVICE_HOME)  :searx-src:  clone $GIT_URL  :pyenv:      create/remove virtualenv (python) in $SEARX_PYENV  :uwsgi:      install searx uWSGI application  :settings:   reinstall settings from ${SEARX_SETTINGS_TEMPLATE}  :packages:   install needed packages from OS package manager  :buildhost:  install packages from OS package manager needed by buildhostsupdate searx  Update searx installation ($SERVICE_HOME)activate service  activate and start service daemon (systemd unit)deactivate service  stop and deactivate service daemon (systemd unit)inspect service  run some small tests and inspect service's status and logoption  set one of the available optionsapache  :install: apache site with the searx uwsgi app  :remove:  apache site ${APACHE_FILTRON_SITE}searx settings: ${SEARX_SETTINGS_PATH}If needed, set PUBLIC_URL of your WEB service in the '${DOT_CONFIG#"$REPO_ROOT/"}' file::  PUBLIC_URL          : ${PUBLIC_URL}  SEARX_INSTANCE_NAME : ${SEARX_INSTANCE_NAME}  SERVICE_USER        : ${SERVICE_USER}  SEARX_INTERNAL_HTTP : http://${SEARX_INTERNAL_HTTP}EOF    if in_container; then        # searx is listening on 127.0.0.1 and not available from outside container        # in containers the service is listening on 0.0.0.0 (see lxc-searx.env)        echo -e "${_BBlack}HINT:${_creset} searx only listen on loopback device" \             "${_BBlack}inside${_creset} the container."        for ip in $(global_IPs) ; do            if [[ $ip =~ .*:.* ]]; then                echo "  container (IPv6): [${ip#*|}]"            else                # IPv4:                echo "  container (IPv4): ${ip#*|}"            fi        done    fi    [[ -n ${1} ]] &&  err_msg "$1"}main() {    required_commands \        sudo systemctl install git wget curl \        || exit    local _usage="unknown or missing $1 command $2"    case $1 in        --getenv)  var="$2"; echo "${!var}"; exit 0;;        -h|--help) usage; exit 0;;        shell)            sudo_or_exit            interactive_shell "${SERVICE_USER}"            ;;        inspect)            case $2 in                service)                    sudo_or_exit                    inspect_service                    ;;                *) usage "$_usage"; exit 42;;            esac ;;        install)            rst_title "$SEARX_INSTANCE_NAME" part            sudo_or_exit            case $2 in                all) install_all ;;                user) assert_user ;;                pyenv) create_pyenv ;;                searx-src) clone_searx ;;                settings) install_settings ;;                uwsgi)                    install_searx_uwsgi                    if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then                        err_msg "URL http://${SEARX_INTERNAL_HTTP} not available, check searx & uwsgi setup!"                    fi                    ;;                packages)                    pkg_install "$SEARX_PACKAGES"                    ;;                buildhost)                    pkg_install "$SEARX_PACKAGES"                    pkg_install "$BUILD_PACKAGES"                    ;;                *) usage "$_usage"; exit 42;;            esac ;;        update)            sudo_or_exit            case $2 in                searx) update_searx;;                *) usage "$_usage"; exit 42;;            esac ;;        remove)            sudo_or_exit            case $2 in                all) remove_all;;                user) drop_service_account "${SERVICE_USER}";;                pyenv) remove_pyenv ;;                searx-src) remove_searx ;;                *) usage "$_usage"; exit 42;;            esac ;;        activate)            sudo_or_exit            case $2 in                service)                    activate_service ;;                *) usage "$_usage"; exit 42;;            esac ;;        deactivate)            sudo_or_exit            case $2 in                service)  deactivate_service ;;                *) usage "$_usage"; exit 42;;            esac ;;        option)            sudo_or_exit            case $2 in                debug-on)  echo; enable_debug ;;                debug-off)  echo; disable_debug ;;                result-proxy) set_result_proxy "$3" "$4" ;;                image-proxy-on) enable_image_proxy ;;                image-proxy-off) disable_image_proxy ;;                *) usage "$_usage"; exit 42;;            esac ;;        apache)            sudo_or_exit            case $2 in                install) install_apache_site ;;                remove) remove_apache_site ;;                *) usage "$_usage"; exit 42;;            esac ;;        doc) rst-doc;;        *) usage "unknown or missing command $1"; exit 42;;    esac}_service_prefix="  ${_Yellow}|$SERVICE_USER|${_creset} "install_all() {    rst_title "Install $SEARX_INSTANCE_NAME (service)"    pkg_install "$SEARX_PACKAGES"    wait_key    assert_user    wait_key    clone_searx    wait_key    create_pyenv    wait_key    install_settings    wait_key    test_local_searx    wait_key    install_searx_uwsgi    if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then        err_msg "URL http://${SEARX_INTERNAL_HTTP} not available, check searx & uwsgi setup!"    fi    if ask_yn "Do you want to inspect the installation?" Ny; then        inspect_service    fi}update_searx() {    rst_title "Update searx instance"    echo    tee_stderr 0.3 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}git checkout -B "$GIT_BRANCH"git pullpip install -U pippip install -U setuptoolspip install -U wheelpip install -U pyyamlpip install -U -e .EOF    install_settings    uWSGI_restart "$SEARX_UWSGI_APP"}remove_all() {    rst_title "De-Install $SEARX_INSTANCE_NAME (service)"    rst_para "\It goes without saying that this script can only be used to removeinstallations that were installed with this script."    if ! ask_yn "Do you really want to deinstall $SEARX_INSTANCE_NAME?"; then        return    fi    remove_searx_uwsgi    drop_service_account "${SERVICE_USER}"    remove_settings    wait_key    if service_is_available "${PUBLIC_URL}"; then        MSG="** Don't forgett to remove your public site! (${PUBLIC_URL}) **" wait_key 10    fi}assert_user() {    rst_title "user $SERVICE_USER" section    echo    tee_stderr 1 <<EOF | bash | prefix_stdoutuseradd --shell /bin/bash --system \ --home-dir "$SERVICE_HOME" \ --comment 'Privacy-respecting metasearch engine' $SERVICE_USERmkdir "$SERVICE_HOME"chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"groups $SERVICE_USEREOF    #SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"    #export SERVICE_HOME    #echo "export SERVICE_HOME=$SERVICE_HOME"}clone_is_available() {    [[ -f "$SEARX_SRC/.git/config" ]]}# shellcheck disable=SC2164clone_searx() {    rst_title "Clone searx sources" section    echo    if ! sudo -i -u "$SERVICE_USER" ls -d "$REPO_ROOT" > /dev/null; then        die 42 "user '$SERVICE_USER' missed read permission: $REPO_ROOT"    fi    SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME 2>/dev/null)"    if [[ ! "${SERVICE_HOME}" ]]; then        err_msg "to clone searx sources, user $SERVICE_USER hast to be created first"        return 42    fi    if [[ ! $(git show-ref "refs/heads/${GIT_BRANCH}") ]]; then        warn_msg "missing local branch ${GIT_BRANCH}"        info_msg "create local branch ${GIT_BRANCH} from start point: origin/${GIT_BRANCH}"        git branch "${GIT_BRANCH}" "origin/${GIT_BRANCH}"    fi    if [[ ! $(git branch --show-current) == "${GIT_BRANCH}" ]]; then        warn_msg "take into account, installing branch $GIT_BRANCH while current branch is $(git branch --show-current)"    fi    export SERVICE_HOME    git_clone "$REPO_ROOT" "$SEARX_SRC" \              "$GIT_BRANCH" "$SERVICE_USER"    pushd "${SEARX_SRC}" > /dev/null    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 | prefix_stdout "$_service_prefix"cd "${SEARX_SRC}"git remote set-url origin ${GIT_URL}git config user.email "$ADMIN_EMAIL"git config user.name "$ADMIN_NAME"git config --listEOF    popd > /dev/null}install_settings() {    rst_title "${SEARX_SETTINGS_PATH}" section    if ! clone_is_available; then        err_msg "you have to install searx first"        exit 42    fi    mkdir -p "$(dirname ${SEARX_SETTINGS_PATH})"    if [[ ! -f ${SEARX_SETTINGS_PATH} ]]; then        info_msg "install settings ${SEARX_SETTINGS_TEMPLATE}"        info_msg "  --> ${SEARX_SETTINGS_PATH}"        cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"        configure_searx        return    fi    rst_para "Diff between origin's setting file (+) and current (-):"    echo "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"    $DIFF_CMD "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_TEMPLATE}"    local action    choose_one action "What should happen to the settings file? " \           "keep configuration unchanged" \           "use origin settings" \           "start interactiv shell"    case $action in        "keep configuration unchanged")            info_msg "leave settings file unchanged"            ;;        "use origin settings")            backup_file "${SEARX_SETTINGS_PATH}"            info_msg "install origin settings"            cp "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"            ;;        "start interactiv shell")            backup_file "${SEARX_SETTINGS_PATH}"            echo -e "// exit with [${_BCyan}CTRL-D${_creset}]"            sudo -H -i            rst_para 'Diff between new setting file (-) and current (+):'            echo            $DIFF_CMD "${SEARX_SETTINGS_TEMPLATE}" "${SEARX_SETTINGS_PATH}"            wait_key            ;;    esac}remove_settings() {    rst_title "remove searx settings" section    echo    info_msg "delete ${SEARX_SETTINGS_PATH}"    rm -f "${SEARX_SETTINGS_PATH}"}remove_searx() {    rst_title "Drop searx sources" section    if ask_yn "Do you really want to drop searx sources ($SEARX_SRC)?"; then        rm -rf "$SEARX_SRC"    else        rst_para "Leave searx sources unchanged."    fi}pyenv_is_available() {    [[ -f "${SEARX_PYENV}/bin/activate" ]]}create_pyenv() {    rst_title "Create virtualenv (python)" section    echo    if [[ ! -f "${SEARX_SRC}/manage.sh" ]]; then        err_msg "to create pyenv for searx, searx has to be cloned first"        return 42    fi    info_msg "create pyenv in ${SEARX_PYENV}"    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"rm -rf "${SEARX_PYENV}"python3 -m venv "${SEARX_PYENV}"grep -qFs -- 'source ${SEARX_PYENV}/bin/activate' ~/.profile \  || echo 'source ${SEARX_PYENV}/bin/activate' >> ~/.profileEOF    info_msg "inspect python's virtual environment"    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"command -v python && python --versionEOF    wait_key    info_msg "install needed python packages"    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"pip install -U pippip install -U setuptoolspip install -U wheelpip install -U pyyamlpip install -U -e .cd ${SEARX_SRC}pip install -e .EOF}remove_pyenv() {    rst_title "Remove virtualenv (python)" section    if ! ask_yn "Do you really want to drop ${SEARX_PYENV} ?"; then        return    fi    info_msg "remove pyenv activation from ~/.profile"    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"grep -v 'source ${SEARX_PYENV}/bin/activate' ~/.profile > ~/.profile.##mv ~/.profile.## ~/.profileEOF    rm -rf "${SEARX_PYENV}"}configure_searx() {    rst_title "Configure searx" section    rst_para "Setup searx config located at $SEARX_SETTINGS_PATH"    echo    tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}sed -i -e "s/ultrasecretkey/$(openssl rand -hex 16)/g" "$SEARX_SETTINGS_PATH"sed -i -e "s/{instance_name}/${SEARX_INSTANCE_NAME}/g" "$SEARX_SETTINGS_PATH"EOF}test_local_searx() {    rst_title "Testing searx instance localy" section    echo    if service_is_available "http://${SEARX_INTERNAL_HTTP}" &>/dev/null; then        err_msg "URL/port http://${SEARX_INTERNAL_HTTP} is already in use, you"        err_msg "should stop that service before starting local tests!"        if ! ask_yn "Continue with local tests?"; then            return        fi    fi    sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"    tee_stderr 0.1 <<EOF | sudo -H -u "${SERVICE_USER}" -i 2>&1 |  prefix_stdout "$_service_prefix"export SEARX_SETTINGS_PATH="${SEARX_SETTINGS_PATH}"cd ${SEARX_SRC}timeout 10 python searx/webapp.py &sleep 3curl --location --verbose --head --insecure $SEARX_INTERNAL_HTTPEOF    sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"}install_searx_uwsgi() {    rst_title "Install searx's uWSGI app (searx.ini)" section    echo    install_uwsgi    uWSGI_install_app "$SEARX_UWSGI_APP"}remove_searx_uwsgi() {    rst_title "Remove searx's uWSGI app (searx.ini)" section    echo    uWSGI_remove_app "$SEARX_UWSGI_APP"}activate_service() {    rst_title "Activate $SEARX_INSTANCE_NAME (service)" section    echo    uWSGI_enable_app "$SEARX_UWSGI_APP"    uWSGI_restart "$SEARX_UWSGI_APP"}deactivate_service() {    rst_title "De-Activate $SEARX_INSTANCE_NAME (service)" section    echo    uWSGI_disable_app "$SEARX_UWSGI_APP"    uWSGI_restart "$SEARX_UWSGI_APP"}enable_image_proxy() {    info_msg "try to enable image_proxy ..."    tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}sed -i -e "s/image_proxy : False/image_proxy : True/g" "$SEARX_SETTINGS_PATH"EOF    uWSGI_restart "$SEARX_UWSGI_APP"}disable_image_proxy() {    info_msg "try to enable image_proxy ..."    tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}sed -i -e "s/image_proxy : True/image_proxy : False/g" "$SEARX_SETTINGS_PATH"EOF    uWSGI_restart "$SEARX_UWSGI_APP"}enable_debug() {    warn_msg "Do not enable debug in production enviroments!!"    info_msg "try to enable debug mode ..."    tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}sed -i -e "s/debug : False/debug : True/g" "$SEARX_SETTINGS_PATH"EOF    uWSGI_restart "$SEARX_UWSGI_APP"}disable_debug() {    info_msg "try to disable debug mode ..."    tee_stderr 0.1 <<EOF | sudo -H -i 2>&1 |  prefix_stdout "$_service_prefix"cd ${SEARX_SRC}sed -i -e "s/debug : True/debug : False/g" "$SEARX_SETTINGS_PATH"EOF    uWSGI_restart "$SEARX_UWSGI_APP"}set_result_proxy() {    # usage: set_result_proxy <URL> [<key>]    info_msg "try to set result proxy: '$1' ($2)"    cp "${SEARX_SETTINGS_PATH}" "${SEARX_SETTINGS_PATH}.bak"    _set_result_proxy "$1" "$2" > "${SEARX_SETTINGS_PATH}"}_set_result_proxy() {    local line    local stage=0    local url="    url: $1"    local key="    key: !!binary \"$2\""    if [[ -z $2 ]]; then       key=    fi    while IFS=  read -r line    do        if [[ $stage = 0 ]] || [[ $stage = 2 ]] ; then            if [[ $line =~ ^[[:space:]]*#*[[:space:]]*result_proxy[[:space:]]*:[[:space:]]*$ ]]; then                if [[ $stage = 0 ]]; then                    stage=1                    echo "result_proxy:"                    continue                elif [[ $stage = 2 ]]; then                    continue                fi            fi        fi        if [[ $stage = 1 ]] || [[ $stage = 2 ]] ; then            if [[ $line =~ ^[[:space:]]*#*[[:space:]]*url[[:space:]]*:[[:space:]] ]]; then                [[ $stage = 1 ]]  && echo "$url"                continue            elif [[ $line =~ ^[[:space:]]*#*[[:space:]]*key[[:space:]]*:[[:space:]] ]]; then                [[ $stage = 1 ]] && [[ -n $key ]] && echo "$key"                continue            elif [[ $line =~ ^[[:space:]]*$ ]]; then                stage=2            fi        fi        echo "$line"    done < "${SEARX_SETTINGS_PATH}.bak"}function has_substring() {   [[ "$1" != "${2/$1/}" ]]}inspect_service() {    rst_title "service status & log"    cat <<EOFsourced ${DOT_CONFIG#"$REPO_ROOT/"} :  PUBLIC_URL          : ${PUBLIC_URL}  SEARX_URL_PATH      : ${SEARX_URL_PATH}  SEARX_INSTANCE_NAME : ${SEARX_INSTANCE_NAME}  SEARX_INTERNAL_HTTP  : ${SEARX_INTERNAL_HTTP}EOF    if service_account_is_available "$SERVICE_USER"; then        info_msg "Service account $SERVICE_USER exists."    else        err_msg "Service account $SERVICE_USER does not exists!"    fi    if pyenv_is_available; then        info_msg "~$SERVICE_USER: python environment is available."    else        err_msg "~$SERVICE_USER: python environment is not available!"    fi    if clone_is_available; then        info_msg "~$SERVICE_USER: Searx software is installed."    else        err_msg "~$SERVICE_USER: Missing searx software!"    fi    if uWSGI_app_enabled "$SEARX_UWSGI_APP"; then        info_msg "uWSGI app $SEARX_UWSGI_APP is enabled."    else        err_msg "uWSGI app $SEARX_UWSGI_APP not enabled!"    fi    uWSGI_app_available "$SEARX_UWSGI_APP" \        || err_msg "uWSGI app $SEARX_UWSGI_APP not available!"    if in_container; then        lxc_suite_info    else        info_msg "public URL   --> ${PUBLIC_URL}"        info_msg "internal URL --> http://${SEARX_INTERNAL_HTTP}"    fi    if ! service_is_available "http://${SEARX_INTERNAL_HTTP}"; then        err_msg "uWSGI app (service) at http://${SEARX_INTERNAL_HTTP} is not available!"        MSG="${_Green}[${_BCyan}CTRL-C${_Green}] to stop or [${_BCyan}KEY${_Green}] to continue"\           wait_key    fi    if ! service_is_available "${PUBLIC_URL}"; then        warn_msg "Public service at ${PUBLIC_URL} is not available!"        if ! in_container; then            warn_msg "Check if public name is correct and routed or use the public IP from above."        fi    fi    local _debug_on    if ask_yn "Enable searx debug mode?"; then        enable_debug        _debug_on=1    fi    echo    case $DIST_ID-$DIST_VERS in        ubuntu-*|debian-*)            systemctl --no-pager -l status "${SERVICE_NAME}"            ;;        arch-*)            systemctl --no-pager -l status "uwsgi@${SERVICE_NAME%.*}"            ;;        fedora-*|centos-7)            systemctl --no-pager -l status uwsgi            ;;    esac    # shellcheck disable=SC2059    printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"    read -r -s -n1 -t 5    echo    while true;  do        trap break 2        case $DIST_ID-$DIST_VERS in            ubuntu-*|debian-*) tail -f /var/log/uwsgi/app/searx.log ;;            arch-*)  journalctl -f -u "uwsgi@${SERVICE_NAME%.*}" ;;            fedora-*|centos-7)  journalctl -f -u uwsgi ;;        esac    done    if [[ $_debug_on == 1 ]]; then        disable_debug    fi    return 0}install_apache_site() {    rst_title "Install Apache site $APACHE_SEARX_SITE"    rst_para "\This installs the searx uwsgi app as apache site.  If your server is public tothe internet, you should instead use a reverse proxy (filtron) to blockexcessively bot queries."    ! apache_is_installed && err_msg "Apache is not installed."    if ! ask_yn "Do you really want to continue?" Yn; then        return    else        install_apache    fi    apache_install_site --variant=uwsgi "${APACHE_SEARX_SITE}"    rst_title "Install searx's uWSGI app (searx.ini)" section    echo    uWSGI_install_app --variant=socket "$SEARX_UWSGI_APP"    if ! service_is_available "${PUBLIC_URL}"; then        err_msg "Public service at ${PUBLIC_URL} is not available!"    fi}remove_apache_site() {    rst_title "Remove Apache site ${APACHE_SEARX_SITE}"    rst_para "\This removes apache site ${APACHE_SEARX_SITE}."    ! apache_is_installed && err_msg "Apache is not installed."    if ! ask_yn "Do you really want to continue?" Yn; then        return    fi    apache_remove_site "${APACHE_SEARX_SITE}"    rst_title "Remove searx's uWSGI app (searx.ini)" section    echo    uWSGI_remove_app "$SEARX_UWSGI_APP"}rst-doc() {    local debian="${SEARX_PACKAGES_debian}"    local arch="${SEARX_PACKAGES_arch}"    local fedora="${SEARX_PACKAGES_fedora}"    local centos="${SEARX_PACKAGES_centos}"    local debian_build="${BUILD_PACKAGES_debian}"    local arch_build="${BUILD_PACKAGES_arch}"    local fedora_build="${BUILD_PACKAGES_fedora}"    local centos_build="${SEARX_PACKAGES_centos}"    debian="$(echo "${debian}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    arch="$(echo "${arch}"     | sed 's/.*/          & \\/' | sed '$ s/.$//')"    fedora="$(echo "${fedora}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    centos="$(echo "${centos}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    debian_build="$(echo "${debian_build}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    arch_build="$(echo "${arch_build}"     | sed 's/.*/          & \\/' | sed '$ s/.$//')"    fedora_build="$(echo "${fedora_build}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    centos_build="$(echo "${centos_build}" | sed 's/.*/          & \\/' | sed '$ s/.$//')"    eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/searx.rst")\""    # I use ubuntu-20.04 here to demonstrate that versions are also suported,    # normaly debian-* and ubuntu-* are most the same.    for DIST_NAME in ubuntu-20.04 arch fedora; do        (            DIST_ID=${DIST_NAME%-*}            DIST_VERS=${DIST_NAME#*-}            [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=            uWSGI_distro_setup            echo -e "\n.. START searx uwsgi-description $DIST_NAME"            case $DIST_ID-$DIST_VERS in                ubuntu-*|debian-*)  cat <<EOF.. code:: bash   # init.d --> /usr/share/doc/uwsgi/README.Debian.gz   # For uWSGI debian uses the LSB init process, this might be changed   # one day, see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=833067   create     ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}   enable:    sudo -H ln -s ${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP} ${uWSGI_APPS_ENABLED}/   start:     sudo -H service uwsgi start   ${SEARX_UWSGI_APP%.*}   restart:   sudo -H service uwsgi restart ${SEARX_UWSGI_APP%.*}   stop:      sudo -H service uwsgi stop    ${SEARX_UWSGI_APP%.*}   disable:   sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}EOF                ;;                arch-*) cat <<EOF.. code:: bash   # systemd --> /usr/lib/systemd/system/uwsgi@.service   # For uWSGI archlinux uses systemd template units, see   # - http://0pointer.de/blog/projects/instances.html   # - https://uwsgi-docs.readthedocs.io/en/latest/Systemd.html#one-service-per-app-in-systemd   create:    ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}   enable:    sudo -H systemctl enable   uwsgi@${SEARX_UWSGI_APP%.*}   start:     sudo -H systemctl start    uwsgi@${SEARX_UWSGI_APP%.*}   restart:   sudo -H systemctl restart  uwsgi@${SEARX_UWSGI_APP%.*}   stop:      sudo -H systemctl stop     uwsgi@${SEARX_UWSGI_APP%.*}   disable:   sudo -H systemctl disable  uwsgi@${SEARX_UWSGI_APP%.*}EOF                ;;                fedora-*|centos-7) cat <<EOF.. code:: bash   # systemd --> /usr/lib/systemd/system/uwsgi.service   # The unit file starts uWSGI in emperor mode (/etc/uwsgi.ini), see   # - https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html   create:    ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}   restart:   sudo -H touch ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}   disable:   sudo -H rm ${uWSGI_APPS_ENABLED}/${SEARX_UWSGI_APP}EOF                ;;            esac            echo -e ".. END searx uwsgi-description $DIST_NAME"            echo -e "\n.. START searx uwsgi-appini $DIST_NAME"            echo ".. code:: bash"            echo            eval "echo \"$(< "${TEMPLATES}/${uWSGI_APPS_AVAILABLE}/${SEARX_UWSGI_APP}")\"" | prefix_stdout "  "            echo -e "\n.. END searx uwsgi-appini $DIST_NAME"        )    done}# ----------------------------------------------------------------------------main "$@"# ----------------------------------------------------------------------------
 |