morty.sh 11 KB

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