morty.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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 source=utils/lib.sh
  5. source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
  6. source_dot_config
  7. source "${REPO_ROOT}/utils/lxc-searx.env"
  8. in_container && lxc_set_suite_env
  9. # ----------------------------------------------------------------------------
  10. # config
  11. # ----------------------------------------------------------------------------
  12. PUBLIC_URL_PATH_MORTY="/morty"
  13. PUBLIC_URL_MORTY="$(dirname "${PUBLIC_URL}")${PUBLIC_URL_PATH_MORTY}"
  14. MORTY_LISTEN="${MORTY_LISTEN:-127.0.0.1:3000}"
  15. # shellcheck disable=SC2034
  16. MORTY_TIMEOUT=5
  17. SERVICE_NAME="morty"
  18. SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
  19. SERVICE_HOME_BASE="${SERVICE_HOME_BASE:-/usr/local}"
  20. SERVICE_HOME="${SERVICE_HOME_BASE}/${SERVICE_USER}"
  21. SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
  22. # shellcheck disable=SC2034
  23. SERVICE_GROUP="${SERVICE_USER}"
  24. # shellcheck disable=SC2034
  25. SERVICE_ENV_DEBUG=false
  26. GO_ENV="${SERVICE_HOME}/.go_env"
  27. GO_PKG_URL="https://dl.google.com/go/go1.13.5.linux-amd64.tar.gz"
  28. GO_TAR=$(basename "$GO_PKG_URL")
  29. # shellcheck disable=SC2034
  30. CONFIG_FILES=()
  31. # Apache Settings
  32. APACHE_MORTY_SITE="morty.conf"
  33. # ----------------------------------------------------------------------------
  34. usage() {
  35. # ----------------------------------------------------------------------------
  36. # shellcheck disable=SC1117
  37. cat <<EOF
  38. usage::
  39. $(basename "$0") shell
  40. $(basename "$0") install [all|user]
  41. $(basename "$0") update [morty]
  42. $(basename "$0") remove [all]
  43. $(basename "$0") activate [service]
  44. $(basename "$0") deactivate [service]
  45. $(basename "$0") inspect [service]
  46. $(basename "$0") option [debug-on|debug-off]
  47. $(basename "$0") apache [install|remove]
  48. $(basename "$0") info [searx]
  49. shell
  50. start interactive shell from user ${SERVICE_USER}
  51. install / remove
  52. all: complete setup of morty service
  53. user: add/remove service user '$SERVICE_USER' ($SERVICE_HOME)
  54. update morty
  55. Update morty installation ($SERVICE_HOME)
  56. activate service
  57. activate and start service daemon (systemd unit)
  58. deactivate service
  59. stop and deactivate service daemon (systemd unit)
  60. inspect service
  61. show service status and log
  62. option
  63. set one of the available options
  64. apache : ${PUBLIC_URL_MORTY}
  65. :install: apache site with a reverse proxy (ProxyPass)
  66. :remove: apache site ${APACHE_MORTY_SITE}
  67. If needed, set the environment variable MORTY_LISTEN in the
  68. ${DOT_CONFIG#"$REPO_ROOT/"} file::
  69. MORTY_LISTEN : ${MORTY_LISTEN}
  70. SERVICE_USER : ${SERVICE_USER}
  71. EOF
  72. if in_container; then
  73. lxc_suite_info
  74. else
  75. info_msg "public URL --> ${PUBLIC_URL}"
  76. info_msg "internal URL --> http://${SEARX_INTERNAL_URL}"
  77. fi
  78. info_searx
  79. [[ -n ${1} ]] && err_msg "$1"
  80. }
  81. info_searx() {
  82. # shellcheck disable=SC1117
  83. cat <<EOF
  84. To activate morty in searx, add result_proxy to your settings.yml::
  85. result_proxy:
  86. url : ${PUBLIC_URL_MORTY}/
  87. server:
  88. ...
  89. image_proxy : True # Proxying image results through searx
  90. ...
  91. further read: ${DOCS_URL}/admin/morty.html
  92. EOF
  93. }
  94. main() {
  95. rst_title "$SERVICE_NAME" part
  96. required_commands \
  97. sudo install git wget curl \
  98. || exit
  99. local _usage="ERROR: unknown or missing $1 command $2"
  100. case $1 in
  101. --source-only) ;;
  102. -h|--help) usage; exit 0;;
  103. shell)
  104. sudo_or_exit
  105. interactive_shell "${SERVICE_USER}"
  106. ;;
  107. inspect)
  108. case $2 in
  109. service)
  110. sudo_or_exit
  111. inspect_service
  112. ;;
  113. *) usage "$_usage"; exit 42;;
  114. esac ;;
  115. install)
  116. sudo_or_exit
  117. case $2 in
  118. all) install_all ;;
  119. user) assert_user ;;
  120. *) usage "$_usage"; exit 42;;
  121. esac ;;
  122. update)
  123. sudo_or_exit
  124. case $2 in
  125. morty) update_morty ;;
  126. *) usage "$_usage"; exit 42;;
  127. esac ;;
  128. remove)
  129. sudo_or_exit
  130. case $2 in
  131. all) remove_all;;
  132. user) drop_service_account "${SERVICE_USER}" ;;
  133. *) usage "$_usage"; exit 42;;
  134. esac ;;
  135. activate)
  136. sudo_or_exit
  137. case $2 in
  138. service) systemd_activate_service "${SERVICE_NAME}" ;;
  139. *) usage "$_usage"; exit 42;;
  140. esac ;;
  141. deactivate)
  142. sudo_or_exit
  143. case $2 in
  144. service) systemd_deactivate_service "${SERVICE_NAME}" ;;
  145. *) usage "$_usage"; exit 42;;
  146. esac ;;
  147. apache)
  148. sudo_or_exit
  149. case $2 in
  150. install) install_apache_site ;;
  151. remove) remove_apache_site ;;
  152. *) usage "$_usage"; exit 42;;
  153. esac ;;
  154. info)
  155. case $2 in
  156. searx) info_searx ;;
  157. *) usage "$_usage"; exit 42;;
  158. esac ;;
  159. option)
  160. sudo_or_exit
  161. case $2 in
  162. debug-on) enable_debug ;;
  163. debug-off) disable_debug ;;
  164. *) usage "$_usage"; exit 42;;
  165. esac ;;
  166. doc)
  167. echo
  168. echo ".. generic utils/morty.sh documentation"
  169. ;;
  170. *) usage "ERROR: unknown or missing command $1"; exit 42;;
  171. esac
  172. }
  173. install_all() {
  174. rst_title "Install $SERVICE_NAME (service)"
  175. assert_user
  176. wait_key
  177. install_go "${GO_PKG_URL}" "${GO_TAR}" "${SERVICE_USER}"
  178. wait_key
  179. install_morty
  180. wait_key
  181. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  182. wait_key
  183. info_searx
  184. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  185. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  186. fi
  187. if apache_is_installed; then
  188. info_msg "Apache is installed on this host."
  189. if ask_yn "Do you want to install a reverse proxy (ProxyPass)" Yn; then
  190. install_apache_site
  191. fi
  192. fi
  193. if ask_yn "Do you want to inspect the installation?" Ny; then
  194. inspect_service
  195. fi
  196. }
  197. remove_all() {
  198. rst_title "De-Install $SERVICE_NAME (service)"
  199. rst_para "\
  200. It goes without saying that this script can only be used to remove
  201. installations that were installed with this script."
  202. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  203. drop_service_account "${SERVICE_USER}"
  204. fi
  205. }
  206. assert_user() {
  207. rst_title "user $SERVICE_USER" section
  208. echo
  209. tee_stderr 1 <<EOF | bash | prefix_stdout
  210. useradd --shell /bin/bash --system \
  211. --home-dir "$SERVICE_HOME" \
  212. --comment 'Web content sanitizer proxy' $SERVICE_USER
  213. mkdir "$SERVICE_HOME"
  214. chown -R "$SERVICE_GROUP:$SERVICE_GROUP" "$SERVICE_HOME"
  215. groups $SERVICE_USER
  216. EOF
  217. SERVICE_HOME="$(sudo -i -u "$SERVICE_USER" echo \$HOME)"
  218. export SERVICE_HOME
  219. echo "export SERVICE_HOME=$SERVICE_HOME"
  220. cat > "$GO_ENV" <<EOF
  221. export GOPATH=\$HOME/go-apps
  222. export PATH=\$PATH:\$HOME/local/go/bin:\$GOPATH/bin
  223. EOF
  224. echo "Environment $GO_ENV has been setup."
  225. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER"
  226. grep -qFs -- 'source $GO_ENV' ~/.profile || echo 'source $GO_ENV' >> ~/.profile
  227. EOF
  228. }
  229. morty_is_installed() {
  230. [[ -f $SERVICE_HOME/go-apps/bin/morty ]]
  231. }
  232. _svcpr=" ${_Yellow}|${SERVICE_USER}|${_creset} "
  233. install_morty() {
  234. rst_title "Install morty in user's ~/go-apps" section
  235. echo
  236. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  237. go get -v -u github.com/asciimoo/morty
  238. EOF
  239. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  240. cd \$GOPATH/src/github.com/asciimoo/morty
  241. go test
  242. go test -benchmem -bench .
  243. EOF
  244. }
  245. update_morty() {
  246. rst_title "Update morty" section
  247. echo
  248. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  249. go get -v -u github.com/asciimoo/morty
  250. EOF
  251. tee_stderr <<EOF | sudo -i -u "$SERVICE_USER" 2>&1 | prefix_stdout "$_svcpr"
  252. cd \$GOPATH/src/github.com/asciimoo/morty
  253. go test
  254. go test -benchmem -bench .
  255. EOF
  256. }
  257. set_service_env_debug() {
  258. # usage: set_service_env_debug [false|true]
  259. # shellcheck disable=SC2034
  260. local SERVICE_ENV_DEBUG="${1:-false}"
  261. if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
  262. systemd_install_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"
  263. fi
  264. }
  265. inspect_service() {
  266. rst_title "service status & log"
  267. cat <<EOF
  268. sourced ${DOT_CONFIG#"$REPO_ROOT/"} :
  269. MORTY_LISTEN : ${MORTY_LISTEN}
  270. EOF
  271. if service_account_is_available "$SERVICE_USER"; then
  272. info_msg "service account $SERVICE_USER available."
  273. else
  274. err_msg "service account $SERVICE_USER not available!"
  275. fi
  276. if go_is_available "$SERVICE_USER"; then
  277. info_msg "~$SERVICE_USER: go is installed"
  278. else
  279. err_msg "~$SERVICE_USER: go is not installed"
  280. fi
  281. if morty_is_installed; then
  282. info_msg "~$SERVICE_USER: morty app is installed"
  283. else
  284. err_msg "~$SERVICE_USER: morty app is not installed!"
  285. fi
  286. if ! service_is_available "http://${MORTY_LISTEN}" ; then
  287. err_msg "Morty does not listening on: http://${MORTY_LISTEN}"
  288. echo -e "${_Green}stop with [${_BCyan}CTRL-C${_Green}] or .."
  289. wait_key
  290. fi
  291. if ! service_is_available "${PUBLIC_URL}"; then
  292. warn_msg "Public service at ${PUBLIC_URL} is not available!"
  293. if ! in_container; then
  294. warn_msg "Check if public name is correct and routed or use the public IP from above."
  295. fi
  296. fi
  297. if in_container; then
  298. lxc_suite_info
  299. else
  300. info_msg "public URL --> ${PUBLIC_URL_MORTY}"
  301. info_msg "morty URL --> http://${MORTY_LISTEN}"
  302. fi
  303. local _debug_on
  304. if ask_yn "Enable filtron debug mode (needs reinstall of systemd service)?"; then
  305. enable_debug
  306. _debug_on=1
  307. else
  308. systemctl --no-pager -l status "${SERVICE_NAME}"
  309. fi
  310. echo
  311. # shellcheck disable=SC2059
  312. printf "// use ${_BCyan}CTRL-C${_creset} to stop monitoring the log"
  313. read -r -s -n1 -t 5
  314. echo
  315. while true; do
  316. trap break 2
  317. journalctl -f -u "${SERVICE_NAME}"
  318. done
  319. if [[ $_debug_on == 1 ]]; then
  320. FORCE_SELECTION=Y disable_debug
  321. fi
  322. return 0
  323. }
  324. enable_debug() {
  325. warn_msg "Do not enable debug in production enviroments!!"
  326. info_msg "Enabling debug option needs to reinstall systemd service!"
  327. set_service_env_debug true
  328. }
  329. disable_debug() {
  330. info_msg "Disabling debug option needs to reinstall systemd service!"
  331. set_service_env_debug false
  332. }
  333. install_apache_site() {
  334. rst_title "Install Apache site $APACHE_MORTY_SITE"
  335. rst_para "\
  336. This installs a reverse proxy (ProxyPass) into apache site (${APACHE_MORTY_SITE})"
  337. ! apache_is_installed && err_msg "Apache is not installed."
  338. if ! ask_yn "Do you really want to continue?"; then
  339. return
  340. fi
  341. a2enmod headers
  342. a2enmod proxy
  343. a2enmod proxy_http
  344. echo
  345. apache_install_site "${APACHE_MORTY_SITE}"
  346. info_msg "testing public url .."
  347. if ! service_is_available "${PUBLIC_URL_MORTY}"; then
  348. err_msg "Public service at ${PUBLIC_URL_MORTY} is not available!"
  349. fi
  350. }
  351. remove_apache_site() {
  352. rst_title "Remove Apache site $APACHE_MORTY_SITE"
  353. rst_para "\
  354. This removes apache site ${APACHE_MORTY_SITE}."
  355. ! apache_is_installed && err_msg "Apache is not installed."
  356. if ! ask_yn "Do you really want to continue?"; then
  357. return
  358. fi
  359. apache_remove_site "$APACHE_MORTY_SITE"
  360. }
  361. # ----------------------------------------------------------------------------
  362. main "$@"
  363. # ----------------------------------------------------------------------------