morty.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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) rst-doc ;;
  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. rst-doc() {
  362. eval "echo \"$(< "${REPO_ROOT}/docs/build-templates/morty.rst")\""
  363. echo -e "\n.. START install systemd unit"
  364. cat <<EOF
  365. .. tabs::
  366. .. group-tab:: systemd
  367. .. code:: bash
  368. EOF
  369. eval "echo \"$(< "${TEMPLATES}/${SERVICE_SYSTEMD_UNIT}")\"" | prefix_stdout " "
  370. echo -e "\n.. END install systemd unit"
  371. # for DIST_NAME in ubuntu-20.04 arch fedora; do
  372. # (
  373. # DIST_ID=${DIST_NAME%-*}
  374. # DIST_VERS=${DIST_NAME#*-}
  375. # [[ $DIST_VERS =~ $DIST_ID ]] && DIST_VERS=
  376. # # ...
  377. # )
  378. # done
  379. }
  380. # ----------------------------------------------------------------------------
  381. main "$@"
  382. # ----------------------------------------------------------------------------