morty.sh 13 KB

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