morty.sh 12 KB

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