filtron.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. # shellcheck source=utils/lib.sh
  6. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  7. source_dot_config
  8. # ----------------------------------------------------------------------------
  9. # config
  10. # ----------------------------------------------------------------------------
  11. FILTRON_URL_PATH="${FILTRON_URL_PATH:-$(echo "${PUBLIC_URL}" \
  12. | sed -e 's,^.*://[^/]*\(/.*\),\1,g')}"
  13. [[ "${FILTRON_URL_PATH}" == "${PUBLIC_URL}" ]] && FILTRON_URL_PATH=/
  14. FILTRON_ETC="/etc/filtron"
  15. FILTRON_RULES="$FILTRON_ETC/rules.json"
  16. FILTRON_API="127.0.0.1:4005"
  17. FILTRON_LISTEN="127.0.0.1:4004"
  18. FILTRON_TARGET="127.0.0.1:8888"
  19. SERVICE_NAME="filtron"
  20. SERVICE_USER="${SERVICE_NAME}"
  21. SERVICE_HOME="/home/${SERVICE_USER}"
  22. SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
  23. # shellcheck disable=SC2034
  24. SERVICE_GROUP="${SERVICE_USER}"
  25. GO_ENV="${SERVICE_HOME}/.go_env"
  26. GO_PKG_URL="https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
  27. GO_TAR=$(basename "$GO_PKG_URL")
  28. # Apache Settings
  29. APACHE_FILTRON_SITE="searx.conf"
  30. # shellcheck disable=SC2034
  31. CONFIG_FILES=(
  32. "${FILTRON_RULES}"
  33. "${SERVICE_SYSTEMD_UNIT}"
  34. )
  35. # ----------------------------------------------------------------------------
  36. usage() {
  37. # ----------------------------------------------------------------------------
  38. # shellcheck disable=SC1117
  39. cat <<EOF
  40. usage:
  41. $(basename "$0") shell
  42. $(basename "$0") install [all|user]
  43. $(basename "$0") update [filtron]
  44. $(basename "$0") remove [all]
  45. $(basename "$0") activate [service]
  46. $(basename "$0") deactivate [service]
  47. $(basename "$0") inspect [service]
  48. $(basename "$0") option [debug-on|debug-off]
  49. $(basename "$0") apache [install|remove]
  50. shell
  51. start interactive shell from user ${SERVICE_USER}
  52. install / remove
  53. all: complete setup of filtron service
  54. user: add/remove service user '$SERVICE_USER' at $SERVICE_HOME
  55. update filtron
  56. Update filtron installation of user ${SERVICE_USER}
  57. activate service
  58. activate and start service daemon (systemd unit)
  59. deactivate service
  60. stop and deactivate service daemon (systemd unit)
  61. inspect service
  62. show service status and log
  63. option
  64. set one of the available options
  65. apache
  66. install: apache site with a reverse proxy (ProxyPass)
  67. remove: apache site ${APACHE_FILTRON_SITE}
  68. If needed change the environment variable PUBLIC_URL of your WEB service in the
  69. ${DOT_CONFIG#"$REPO_ROOT/"} file:
  70. PUBLIC_URL : ${PUBLIC_URL}
  71. PUBLIC_HOST : ${PUBLIC_HOST}
  72. EOF
  73. [ ! -z ${1+x} ] && echo -e "$1"
  74. }
  75. main() {
  76. rst_title "$SERVICE_NAME" part
  77. required_commands \
  78. dpkg apt-get install git wget curl \
  79. || exit
  80. local _usage="ERROR: unknown or missing $1 command $2"
  81. case $1 in
  82. --source-only) ;;
  83. -h|--help) usage; exit 0;;
  84. shell)
  85. sudo_or_exit
  86. interactive_shell "${SERVICE_USER}"
  87. ;;
  88. inspect)
  89. case $2 in
  90. service)
  91. sudo_or_exit
  92. inspect_service
  93. ;;
  94. *) usage "$_usage"; exit 42;;
  95. esac ;;
  96. install)
  97. sudo_or_exit
  98. case $2 in
  99. all) install_all ;;
  100. user) assert_user ;;
  101. *) usage "$_usage"; exit 42;;
  102. esac ;;
  103. update)
  104. sudo_or_exit
  105. case $2 in
  106. filtron) update_filtron ;;
  107. *) usage "$_usage"; exit 42;;
  108. esac ;;
  109. remove)
  110. sudo_or_exit
  111. case $2 in
  112. all) remove_all;;
  113. user) drop_service_account "${SERVICE_USER}" ;;
  114. *) usage "$_usage"; exit 42;;
  115. esac ;;
  116. activate)
  117. sudo_or_exit
  118. case $2 in
  119. service) systemd_activate_service "${SERVICE_NAME}" ;;
  120. *) usage "$_usage"; exit 42;;
  121. esac ;;
  122. deactivate)
  123. sudo_or_exit
  124. case $2 in
  125. service) systemd_deactivate_service "${SERVICE_NAME}" ;;
  126. *) usage "$_usage"; exit 42;;
  127. esac ;;
  128. apache)
  129. sudo_or_exit
  130. case $2 in
  131. install) install_apache_site ;;
  132. remove) remove_apache_site ;;
  133. *) usage "$_usage"; exit 42;;
  134. esac ;;
  135. option)
  136. sudo_or_exit
  137. case $2 in
  138. debug-on) echo; enable_debug ;;
  139. debug-off) echo; disable_debug ;;
  140. *) usage "$_usage"; exit 42;;
  141. esac ;;
  142. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  143. esac
  144. }
  145. install_all() {
  146. rst_title "Install $SERVICE_NAME (service)"
  147. assert_user
  148. wait_key
  149. install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}"
  150. wait_key
  151. install_filtron
  152. wait_key
  153. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  154. wait_key
  155. echo
  156. if ! service_is_available "http://${FILTRON_LISTEN}" ; then
  157. err_msg "Filtron does not listening on: http://${FILTRON_LISTEN}"
  158. fi
  159. if apache_is_installed; then
  160. info_msg "Apache is installed on this host."
  161. if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then
  162. install_apache_site
  163. fi
  164. fi
  165. if ask_yn "Do you want to inspect the installation?" Yn; then
  166. inspect_service
  167. fi
  168. }
  169. remove_all() {
  170. rst_title "De-Install $SERVICE_NAME (service)"
  171. rst_para "\
  172. It goes without saying that this script can only be used to remove
  173. installations that were installed with this script."
  174. systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  175. wait_key
  176. drop_service_account "${SERVICE_USER}"
  177. rm -r "$FILTRON_ETC" 2>&1 | prefix_stdout
  178. if service_is_available "${PUBLIC_URL}"; then
  179. MSG="** Don't forget to remove your public site! (${PUBLIC_URL}) **" wait_key 10
  180. fi
  181. }
  182. assert_user() {
  183. rst_title "user $SERVICE_USER" section
  184. echo
  185. tee_stderr 1 <<EOF | bash | prefix_stdout
  186. sudo -H adduser --shell /bin/bash --system --home $SERVICE_HOME \
  187. --disabled-password --group --gecos 'Filtron' $SERVICE_USER
  188. sudo -H usermod -a -G shadow $SERVICE_USER
  189. groups $SERVICE_USER
  190. EOF
  191. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  192. export SERVICE_HOME
  193. echo "export SERVICE_HOME=$SERVICE_HOME"
  194. cat > "$GO_ENV" <<EOF
  195. export GOPATH=\$HOME/go-apps
  196. export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin
  197. EOF
  198. echo "Environment $GO_ENV has been setup."
  199. tee_stderr <<EOF | sudo -i -u $SERVICE_USER
  200. grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile
  201. EOF
  202. }
  203. filtron_is_installed() {
  204. [[ -f $SERVICE_HOME/go-apps/bin/filtron ]]
  205. }
  206. install_filtron() {
  207. rst_title "Install filtron in user's ~/go-apps" section
  208. echo
  209. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_service_prefix"
  210. go get -v -u github.com/asciimoo/filtron
  211. EOF
  212. install_template --no-eval "$FILTRON_RULES" root root 644
  213. }
  214. update_filtron() {
  215. rst_title "Update filtron" section
  216. echo
  217. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_service_prefix"
  218. go get -v -u github.com/asciimoo/filtron
  219. EOF
  220. }
  221. inspect_service() {
  222. rst_title "service status & log"
  223. cat <<EOF
  224. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  225. PUBLIC_URL : ${PUBLIC_URL}
  226. PUBLIC_HOST : ${PUBLIC_HOST}
  227. FILTRON_URL_PATH : ${FILTRON_URL_PATH}
  228. FILTRON_API : ${FILTRON_API}
  229. FILTRON_LISTEN : ${FILTRON_LISTEN}
  230. FILTRON_TARGET : ${FILTRON_TARGET}
  231. EOF
  232. apache_is_installed && info_msg "Apache is installed."
  233. if service_account_is_available "$SERVICE_USER"; then
  234. info_msg "service account $SERVICE_USER available."
  235. else
  236. err_msg "service account $SERVICE_USER not available!"
  237. fi
  238. if go_is_available "$SERVICE_USER"; then
  239. info_msg "~$SERVICE_USER: go is installed"
  240. else
  241. err_msg "~$SERVICE_USER: go is not installed"
  242. fi
  243. if filtron_is_installed; then
  244. info_msg "~$SERVICE_USER: filtron app is installed"
  245. else
  246. err_msg "~$SERVICE_USER: filtron app is not installed!"
  247. fi
  248. if ! service_is_available "http://${FILTRON_API}"; then
  249. err_msg "API not available at: http://${FILTRON_API}"
  250. fi
  251. if ! service_is_available "http://${FILTRON_LISTEN}" ; then
  252. err_msg "Filtron does not listening on: http://${FILTRON_LISTEN}"
  253. fi
  254. if ! service_is_available ""http://${FILTRON_TARGET}"" ; then
  255. info_msg "Filtron's target is available at: http://${FILTRON_TARGET}"
  256. fi
  257. if ! service_is_available "${PUBLIC_URL}"; then
  258. err_msg "Public service at ${PUBLIC_URL} is not available!"
  259. fi
  260. local _debug_on
  261. if ask_yn "Enable filtron debug mode?"; then
  262. enable_debug
  263. _debug_on=1
  264. fi
  265. echo
  266. systemctl --no-pager -l status filtron.service
  267. echo
  268. # shellcheck disable=SC2059
  269. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  270. read -r -s -n1 -t 2
  271. echo
  272. while true; do
  273. trap break 2
  274. journalctl -f -u filtron
  275. done
  276. if [[ $_debug_on == 1 ]]; then
  277. disable_debug
  278. fi
  279. return 0
  280. }
  281. enable_debug() {
  282. info_msg "try to enable debug mode ..."
  283. python <<EOF
  284. import sys, json
  285. debug = {
  286. u'name': u'debug request'
  287. , u'filters': []
  288. , u'interval': 0
  289. , u'limit': 0
  290. , u'actions': [{u'name': u'log'}]
  291. }
  292. with open('$FILTRON_RULES') as rules:
  293. j = json.load(rules)
  294. pos = None
  295. for i in range(len(j)):
  296. if j[i].get('name') == 'debug request':
  297. pos = i
  298. break
  299. if pos is not None:
  300. j[pos] = debug
  301. else:
  302. j.append(debug)
  303. with open('$FILTRON_RULES', 'w') as rules:
  304. json.dump(j, rules, indent=2, sort_keys=True)
  305. EOF
  306. systemctl restart "${SERVICE_NAME}.service"
  307. }
  308. disable_debug() {
  309. info_msg "try to disable debug mode ..."
  310. python <<EOF
  311. import sys, json
  312. with open('$FILTRON_RULES') as rules:
  313. j = json.load(rules)
  314. pos = None
  315. for i in range(len(j)):
  316. if j[i].get('name') == 'debug request':
  317. pos = i
  318. break
  319. if pos is not None:
  320. del j[pos]
  321. with open('$FILTRON_RULES', 'w') as rules:
  322. json.dump(j, rules, indent=2, sort_keys=True)
  323. EOF
  324. systemctl restart "${SERVICE_NAME}.service"
  325. }
  326. install_apache_site() {
  327. rst_title "Install Apache site $APACHE_FILTRON_SITE"
  328. rst_para "\
  329. This installs a reverse proxy (ProxyPass) into apache site (${APACHE_FILTRON_SITE})"
  330. ! apache_is_installed && err_msg "Apache is not installed."
  331. if ! ask_yn "Do you really want to continue?"; then
  332. return
  333. fi
  334. a2enmod headers
  335. a2enmod proxy
  336. a2enmod proxy_http
  337. echo
  338. apache_install_site --variant=filtron "${APACHE_FILTRON_SITE}"
  339. info_msg "testing public url .."
  340. if ! service_is_available "${PUBLIC_URL}"; then
  341. err_msg "Public service at ${PUBLIC_URL} is not available!"
  342. fi
  343. }
  344. remove_apache_site() {
  345. rst_title "Remove Apache site $APACHE_FILTRON_SITE"
  346. rst_para "\
  347. This removes apache site ${APACHE_FILTRON_SITE}."
  348. ! apache_is_installed && err_msg "Apache is not installed."
  349. if ! ask_yn "Do you really want to continue?"; then
  350. return
  351. fi
  352. apache_remove_site "$APACHE_FILTRON_SITE"
  353. }
  354. # ----------------------------------------------------------------------------
  355. main "$@"
  356. # ----------------------------------------------------------------------------