1#!/usr/bin/env bash 2# -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*- 3# SPDX-License-Identifier: AGPL-3.0-or-later 4# shellcheck disable=SC2119,SC2001 5 6# shellcheck source=utils/lib.sh 7source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" 8# shellcheck source=utils/brand.env 9source "${REPO_ROOT}/utils/brand.env" 10source_dot_config 11source "${REPO_ROOT}/utils/lxc-searx.env" 12in_container && lxc_set_suite_env 13 14# ---------------------------------------------------------------------------- 15# config 16# ---------------------------------------------------------------------------- 17 18PUBLIC_URL="${PUBLIC_URL:-http://$(uname -n)/searx}" 19PUBLIC_HOST="${PUBLIC_HOST:-$(echo "$PUBLIC_URL" | sed -e 's/[^/]*\/\/\([^@]*@\)\?\([^:/]*\).*/\2/')}" 20 21FILTRON_URL_PATH="${FILTRON_URL_PATH:-$(echo "${PUBLIC_URL}" \ 22| sed -e 's,^.*://[^/]*\(/.*\),\1,g')}" 23[[ "${FILTRON_URL_PATH}" == "${PUBLIC_URL}" ]] && FILTRON_URL_PATH=/ 24 25FILTRON_ETC="/etc/filtron" 26FILTRON_RULES="$FILTRON_ETC/rules.json" 27 28FILTRON_API="${FILTRON_API:-127.0.0.1:4005}" 29FILTRON_LISTEN="${FILTRON_LISTEN:-127.0.0.1:4004}" 30FILTRON_TARGET="${FILTRON_TARGET:-127.0.0.1:8888}" 31 32SERVICE_NAME="filtron" 33SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}" 34SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}" 35SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}" 36SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service" 37# shellcheck disable=SC2034 38SERVICE_GROUP="${SERVICE_USER}" 39 40# shellcheck disable=SC2034 41SERVICE_GROUP="${SERVICE_USER}" 42 43GO_ENV="${SERVICE_HOME}/.go_env" 44GO_PKG_URL="https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz" 45GO_TAR=$(basename "$GO_PKG_URL") 46 47APACHE_FILTRON_SITE="searx.conf" 48NGINX_FILTRON_SITE="searx.conf" 49 50# shellcheck disable=SC2034 51CONFIG_FILES=( 52 "${FILTRON_RULES}" 53 "${SERVICE_SYSTEMD_UNIT}" 54) 55 56# ---------------------------------------------------------------------------- 57usage() { 58# ---------------------------------------------------------------------------- 59 60 # shellcheck disable=SC1117 61 cat <<EOF 62usage:: 63 $(basename "$0") shell 64 $(basename "$0") install [all|user|rules] 65 $(basename "$0") update [filtron] 66 $(basename "$0") remove [all] 67 $(basename "$0") activate [service] 68 $(basename "$0") deactivate [service] 69 $(basename "$0") inspect [service] 70 $(basename "$0") option [debug-on|debug-off] 71 $(basename "$0") apache [install|remove] 72 $(basename "$0") nginx [install|remove] 73 74shell 75 start interactive shell from user ${SERVICE_USER} 76install / remove 77 :all: complete setup of filtron service 78 :user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME) 79 :rules: reinstall filtron rules $FILTRON_RULES 80update filtron 81 Update filtron installation ($SERVICE_HOME) 82activate service 83 activate and start service daemon (systemd unit) 84deactivate service 85 stop and deactivate service daemon (systemd unit) 86inspect service 87 show service status and log 88option 89 set one of the available options 90apache (${PUBLIC_URL}) 91 :install: apache site with a reverse proxy (ProxyPass) 92 :remove: apache site ${APACHE_FILTRON_SITE} 93nginx (${PUBLIC_URL}) 94 :install: nginx site with a reverse proxy (ProxyPass) 95 :remove: nginx site ${NGINX_FILTRON_SITE} 96 97filtron rules: ${FILTRON_RULES} 98 99If needed, set PUBLIC_URL of your WEB service in the '${DOT_CONFIG#"$REPO_ROOT/"}' file:: 100 PUBLIC_URL : ${PUBLIC_URL} 101 PUBLIC_HOST : ${PUBLIC_HOST} 102 SERVICE_USER : ${SERVICE_USER} 103 FILTRON_TARGET : ${FILTRON_TARGET} 104 FILTRON_API : ${FILTRON_API} 105 FILTRON_LISTEN : ${FILTRON_LISTEN} 106EOF 107 if in_container; then 108 # in containers the service is listening on 0.0.0.0 (see lxc-searx.env) 109 for ip in $(global_IPs) ; do 110 if [[ $ip =~ .*:.* ]]; then 111 echo " container URL (IPv6): http://[${ip#*|}]:4005/" 112 else 113 # IPv4: 114 echo " container URL (IPv4): http://${ip#*|}:4005/" 115 fi 116 done 117 fi 118 [[ -n ${1} ]] && err_msg "$1" 119} 120 121main() { 122 required_commands \ 123 sudo install git wget curl \ 124 || exit 125 126 local _usage="unknown or missing $1 command $2" 127 128 case $1 in 129 --getenv) var="$2"; echo "${!var}"; exit 0;; 130 -h|--help) usage; exit 0;; 131 132 shell) 133 sudo_or_exit 134 interactive_shell "${SERVICE_USER}" 135 ;; 136 inspect) 137 case $2 in 138 service) 139 sudo_or_exit 140 inspect_service 141 ;; 142 *) usage "$_usage"; exit 42;; 143 esac ;; 144 install) 145 rst_title "$SERVICE_NAME" part 146 sudo_or_exit 147 case $2 in 148 all) install_all ;; 149 user) assert_user ;; 150 rules) 151 rst_title "Re-Install filtron rules" 152 echo 153 install_template --no-eval "$FILTRON_RULES" root root 644 154 systemd_restart_service "${SERVICE_NAME}" 155 ;; 156 *) usage "$_usage"; exit 42;; 157 esac ;; 158 update) 159 sudo_or_exit 160 case $2 in 161 filtron) update_filtron ;; 162 *) usage "$_usage"; exit 42;; 163 esac ;; 164 remove) 165 sudo_or_exit 166 case $2 in 167 all) remove_all;; 168 user) drop_service_account "${SERVICE_USER}" ;; 169 *) usage "$_usage"; exit 42;; 170 esac ;; 171 activate) 172 sudo_or_exit 173 case $2 in 174 service) systemd_activate_service "${SERVICE_NAME}" ;; 175 *) usage "$_usage"; exit 42;; 176 esac ;; 177 deactivate) 178 sudo_or_exit 179 case $2 in 180 service) systemd_deactivate_service "${SERVICE_NAME}" ;; 181 *) usage "$_usage"; exit 42;; 182 esac ;; 183 apache) 184 sudo_or_exit 185 case $2 in 186 install) install_apache_site ;; 187 remove) remove_apache_site ;; 188 *) usage "$_usage"; exit 42;; 189 esac ;; 190 nginx) 191 sudo_or_exit 192 case $2 in 193 install) install_nginx_site ;; 194 remove) remove_nginx_site ;; 195 *) usage "$_usage"; exit 42;; 196 esac ;; 197 option) 198 sudo_or_exit 199 case $2 in 200 debug-on) echo; enable_debug ;; 201 debug-off) echo; disable_debug ;; 202 *) usage "$_usage"; exit 42;; 203 esac ;; 204 doc) rst-doc ;; 205 *) usage "unknown or missing command $1"; exit 42;; 206 esac 207} 208 209install_all() { 210 rst_title "Install $SERVICE_NAME (service)" 211 assert_user 212 wait_key 213 install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}" 214 wait_key 215 install_filtron 216 wait_key 217 systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}" 218 wait_key 219 echo 220 if ! service_is_available "http://${FILTRON_LISTEN}" ; then 221 err_msg "Filtron does not listening on: http://${FILTRON_LISTEN}" 222 fi 223 if apache_is_installed; then 224 info_msg "Apache is installed on this host." 225 if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then 226 install_apache_site 227 fi 228 elif nginx_is_installed; then 229 info_msg "nginx is installed on this host." 230 if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then 231 install_nginx_site 232 fi 233 fi 234 if ask_yn "Do you want to inspect the installation?" Ny; then 235 inspect_service 236 fi 237 238} 239 240remove_all() { 241 rst_title "De-Install $SERVICE_NAME (service)" 242 243 rst_para "\ 244It goes without saying that this script can only be used to remove 245installations that were installed with this script." 246 247 if ! systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then 248 return 42 249 fi 250 drop_service_account "${SERVICE_USER}" 251 rm -r "$FILTRON_ETC" 2>&1 | prefix_stdout 252 if service_is_available "${PUBLIC_URL}"; then 253 MSG="** Don't forget to remove your public site! (${PUBLIC_URL}) **" wait_key 10 254 fi 255} 256 257assert_user() { 258 rst_title "user $SERVICE_USER" section 259 echo 260 tee_stderr 1 <<EOF | bash | prefix_stdout 261useradd --shell /bin/bash --system \ 262 --home-dir "$SERVICE_HOME" \ 263 --comment 'Reverse HTTP proxy to filter requests' $SERVICE_USER 264mkdir "$SERVICE_HOME" 265chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME" 266groups $SERVICE_USER 267EOF 268 SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)" 269 export SERVICE_HOME 270 echo "export SERVICE_HOME=$SERVICE_HOME" 271 272 cat > "$GO_ENV" <<EOF 273export GOPATH=\$HOME/go-apps 274export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin 275EOF 276 echo "Environment $GO_ENV has been setup." 277 278 tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 279grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile 280EOF 281} 282 283filtron_is_installed() { 284 [[ -f $SERVICE_HOME/go-apps/bin/filtron ]] 285} 286 287_svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} " 288 289install_filtron() { 290 rst_title "Install filtron in user's ~/go-apps" section 291 echo 292 tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr" 293go get -v -u github.com/asciimoo/filtron 294EOF 295 install_template --no-eval "$FILTRON_RULES" root root 644 296} 297 298update_filtron() { 299 rst_title "Update filtron" section 300 echo 301 tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr" 302go get -v -u github.com/asciimoo/filtron 303EOF 304} 305 306inspect_service() { 307 308 rst_title "service status & log" 309 310 cat <<EOF 311 312sourced ${DOT_CONFIG#"$REPO_ROOT/"} : 313 314 PUBLIC_URL : ${PUBLIC_URL} 315 PUBLIC_HOST : ${PUBLIC_HOST} 316 FILTRON_URL_PATH : ${FILTRON_URL_PATH} 317 FILTRON_API : ${FILTRON_API} 318 FILTRON_LISTEN : ${FILTRON_LISTEN} 319 FILTRON_TARGET : ${FILTRON_TARGET} 320 321EOF 322 323 if service_account_is_available "$SERVICE_USER"; then 324 info_msg "service account $SERVICE_USER available." 325 else 326 err_msg "service account $SERVICE_USER not available!" 327 fi 328 if go_is_available "$SERVICE_USER"; then 329 info_msg "~$SERVICE_USER: go is installed" 330 else 331 err_msg "~$SERVICE_USER: go is not installed" 332 fi 333 if filtron_is_installed; then 334 info_msg "~$SERVICE_USER: filtron app is installed" 335 else 336 err_msg "~$SERVICE_USER: filtron app is not installed!" 337 fi 338 339 if ! service_is_available "http://${FILTRON_API}"; then 340 err_msg "API not available at: http://${FILTRON_API}" 341 fi 342 343 if ! service_is_available "http://${FILTRON_LISTEN}" ; then 344 err_msg "Filtron does not listening on: http://${FILTRON_LISTEN}" 345 fi 346 347 if service_is_available "http://${FILTRON_TARGET}" ; then 348 info_msg "Filtron's target is available at: http://${FILTRON_TARGET}" 349 fi 350 351 if ! service_is_available "${PUBLIC_URL}"; then 352 warn_msg "Public service at ${PUBLIC_URL} is not available!" 353 if ! in_container; then 354 warn_msg "Check if public name is correct and routed or use the public IP from above." 355 fi 356 fi 357 358 if in_container; then 359 lxc_suite_info 360 else 361 info_msg "public URL --> ${PUBLIC_URL}" 362 info_msg "internal URL --> http://${FILTRON_LISTEN}" 363 fi 364 365 366 local _debug_on 367 if ask_yn "Enable filtron debug mode?"; then 368 enable_debug 369 _debug_on=1 370 fi 371 echo 372 systemctl --no-pager -l status "${SERVICE_NAME}" 373 echo 374 375 info_msg "public URL --> ${PUBLIC_URL}" 376 # shellcheck disable=SC2059 377 printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log" 378 read -r -s -n1 -t 5 379 echo 380 while true; do 381 trap break 2 382 journalctl -f -u "${SERVICE_NAME}" 383 done 384 385 if [[ $_debug_on == 1 ]]; then 386 disable_debug 387 fi 388 return 0 389} 390 391 392enable_debug() { 393 info_msg "try to enable debug mode ..." 394 python <<EOF 395import sys, json 396 397debug = { 398 u'name': u'debug request' 399 , u'filters': [] 400 , u'interval': 0 401 , u'limit': 0 402 , u'actions': [{u'name': u'log'}] 403} 404 405with open('$FILTRON_RULES') as rules: 406 j = json.load(rules) 407 408pos = None 409for i in range(len(j)): 410 if j[i].get('name') == 'debug request': 411 pos = i 412 break 413if pos is not None: 414 j[pos] = debug 415else: 416 j.append(debug) 417with open('$FILTRON_RULES', 'w') as rules: 418 json.dump(j, rules, indent=2, sort_keys=True) 419 420EOF 421 systemctl restart "${SERVICE_NAME}.service" 422} 423 424disable_debug() { 425 info_msg "try to disable debug mode ..." 426 python <<EOF 427import sys, json 428with open('$FILTRON_RULES') as rules: 429 j = json.load(rules) 430 431pos = None 432for i in range(len(j)): 433 if j[i].get('name') == 'debug request': 434 pos = i 435 break 436if pos is not None: 437 del j[pos] 438 with open('$FILTRON_RULES', 'w') as rules: 439 json.dump(j, rules, indent=2, sort_keys=True) 440EOF 441 systemctl restart "${SERVICE_NAME}.service" 442} 443 444install_apache_site() { 445 446 rst_title "Install Apache site $APACHE_FILTRON_SITE" 447 448 rst_para "\ 449This installs a reverse proxy (ProxyPass) into apache site (${APACHE_FILTRON_SITE})" 450 451 ! apache_is_installed && info_msg "Apache is not installed." 452 453 if ! ask_yn "Do you really want to continue?" Yn; then 454 return 455 else 456 install_apache 457 fi 458 459 "${REPO_ROOT}/utils/searx.sh" install uwsgi 460 461 apache_install_site --variant=filtron "${APACHE_FILTRON_SITE}" 462 463 info_msg "testing public url .." 464 if ! service_is_available "${PUBLIC_URL}"; then 465 err_msg "Public service at ${PUBLIC_URL} is not available!" 466 fi 467} 468 469remove_apache_site() { 470 471 rst_title "Remove Apache site $APACHE_FILTRON_SITE" 472 473 rst_para "\ 474This removes apache site ${APACHE_FILTRON_SITE}." 475 476 ! apache_is_installed && err_msg "Apache is not installed." 477 478 if ! ask_yn "Do you really want to continue?" Yn; then 479 return 480 fi 481 482 apache_remove_site "$APACHE_FILTRON_SITE" 483 484} 485 486install_nginx_site() { 487 488 rst_title "Install nginx site $NGINX_FILTRON_SITE" 489 490 rst_para "\ 491This installs a reverse proxy (ProxyPass) into nginx site (${NGINX_FILTRON_SITE})" 492 493 ! nginx_is_installed && info_msg "nginx is not installed." 494 495 if ! ask_yn "Do you really want to continue?" Yn; then 496 return 497 else 498 install_nginx 499 fi 500 501 "${REPO_ROOT}/utils/searx.sh" install uwsgi 502 503 # shellcheck disable=SC2034 504 SEARX_SRC=$("${REPO_ROOT}/utils/searx.sh" --getenv SEARX_SRC) 505 # shellcheck disable=SC2034 506 SEARX_URL_PATH=$("${REPO_ROOT}/utils/searx.sh" --getenv SEARX_URL_PATH) 507 nginx_install_app --variant=filtron "${NGINX_FILTRON_SITE}" 508 509 info_msg "testing public url .." 510 if ! service_is_available "${PUBLIC_URL}"; then 511 err_msg "Public service at ${PUBLIC_URL} is not available!" 512 fi 513} 514 515remove_nginx_site() { 516 517 rst_title "Remove nginx site $NGINX_FILTRON_SITE" 518 519 rst_para "\ 520This removes nginx site ${NGINX_FILTRON_SITE}." 521 522 ! nginx_is_installed && err_msg "nginx is not installed." 523 524 if ! ask_yn "Do you really want to continue?" Yn; then 525 return 526 fi 527 528 nginx_remove_site "$FILTRON_FILTRON_SITE" 529 530} 531 532 533rst-doc() { 534 535 eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/filtron.rst")\"" 536 537 echo -e "\n.. START install systemd unit" 538 cat <<EOF 539.. tabs:: 540 541 .. group-tab:: systemd 542 543 .. code:: bash 544 545EOF 546 eval "echo \"$(< "${TEMPLATES}/${SERVICE_SYSTEMD_UNIT}")\"" | prefix_stdout " " 547 echo -e "\n.. END install systemd unit" 548 549 # for DIST_NAME in ubuntu-20.04 arch fedora centos; do 550 # ( 551 # DIST_ID=${DIST_NAME%-*} 552 # DIST_VERS=${DIST_NAME#*-} 553 # [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS= 554 # # ... 555 # ) 556 # done 557} 558 559# ---------------------------------------------------------------------------- 560main "$@" 561# ---------------------------------------------------------------------------- 562