The installation script for Bibliotecha https://install.bibliotecha.info/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bibliotecha.sh 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #!/bin/bash
  2. # ____ _ _ _ _ _ _
  3. # | _ \(_) | | (_) | | | |
  4. # | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _
  5. # | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _` |
  6. # | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |
  7. # |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|
  8. #
  9. # Digital books need libraries too
  10. #
  11. # This install script is intended for use with Debian based
  12. # distributions. More specifically, Debian Buster, which is
  13. # currently the latest distribution release from the Debian
  14. # project.
  15. #
  16. # License
  17. # =======
  18. #
  19. # Copyright (C) 2019 Bibliotecha Contributors <info@varia.zone>
  20. #
  21. # This program is free software: you can redistribute it and/or modify
  22. # it under the terms of the GNU Affero General Public License as published by
  23. # the Free Software Foundation, either version 3 of the License, or
  24. # (at your option) any later version.
  25. #
  26. # This program is distributed in the hope that it will be useful,
  27. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. # GNU Affero General Public License for more details.
  30. #
  31. # You should have received a copy of the GNU Affero General Public License
  32. # along with this program. If not, see http://www.gnu.org/licenses/.
  33. #
  34. # Thanks
  35. # =====
  36. #
  37. # This script is based on the good work of the Freedombone project:
  38. # https://code.freedombone.net/bashrc/freedombone/src/stretch/src/freedombone
  39. APT_CMD="apt -q"
  40. APT_INSTALL_CMD="$APT_CMD install -y --no-install-recommends"
  41. CALIBRE_DATABASE_PATH="/opt/calibre-database"
  42. CAPTIVE_PORTAL_PATH="/var/www/bibliotecha"
  43. CALIBRE_WEB_PATH="/var/www/calibre-web"
  44. LIGHTTPD_CONFIG_PATH="/etc/lighttpd/bibliotecha"
  45. function ensure_root_account {
  46. echo "Checking user account ..."
  47. if ! id | grep -q root; then
  48. echo ""
  49. echo "This script must be run as root"
  50. echo "You can switch to the root user account with:"
  51. echo "$ sudo -i"
  52. echo ""
  53. exit 0
  54. fi
  55. }
  56. function show_bibliotecha_banner {
  57. echo ""
  58. echo " ____ _ _ _ _ _ _ "
  59. echo " | _ \(_) | | (_) | | | |"
  60. echo " | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _ "
  61. echo " | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _' |"
  62. echo " | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |"
  63. echo " |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|"
  64. echo ""
  65. echo " Digital books need libraries too"
  66. echo ""
  67. }
  68. function show_introduction_text {
  69. echo ""
  70. echo "Welcome to the Bibliotecha automatic installation script"
  71. echo ""
  72. echo "This script will attempt to setup the following infrastructure:"
  73. echo ""
  74. echo "* A Python 3 environment"
  75. echo "* A Wifi hotspot with DNS and DHCP services enabled"
  76. echo "* A web server"
  77. echo "* A Calibre library"
  78. echo "* A Calibre-web service"
  79. echo ""
  80. echo "Once the script is finished, please see post-install steps"
  81. echo "that are documented and available from the Bibliotecha manual:"
  82. echo ""
  83. echo " https://manual.bibliotecha.info/#post-installation"
  84. echo ""
  85. echo "If anything goes wrong, please see the troubleshooting guide"
  86. echo ""
  87. echo " https://manual.bibliotecha.info/#troubleshooting"
  88. echo ""
  89. echo "Waiting a few seconds before moving on ..."
  90. sleep 10
  91. }
  92. function ensure_buster_based_distribution {
  93. echo "Checking distribution ..."
  94. local installing_on_buster_based=1
  95. if [ ! -f /etc/apt/sources.list ]; then
  96. installing_on_buster_based=
  97. else
  98. if ! grep -q 'buster' /etc/apt/sources.list; then
  99. installing_on_buster_based=
  100. fi
  101. if ! grep -q 'debian' /etc/apt/sources.list; then
  102. if ! grep -q 'raspbian' /etc/apt/sources.list; then
  103. installing_on_buster_based=
  104. fi
  105. fi
  106. fi
  107. if [ ! $installing_on_buster_based ]; then
  108. echo "You should only run this on a Debian Buster based system"
  109. exit 1
  110. fi
  111. }
  112. function run_apt_update {
  113. echo "Running a package listing update ..."
  114. $APT_CMD update
  115. }
  116. function install_networking_packages {
  117. echo "Installing networking packages ..."
  118. $APT_INSTALL_CMD \
  119. dhcpcd \
  120. dnsmasq \
  121. dnsutils \
  122. hostapd \
  123. wireless-tools
  124. }
  125. function stop_networking_services {
  126. echo "Stopping the networking services ..."
  127. local services="dnsmasq hostapd"
  128. # shellcheck disable=SC2086
  129. systemctl stop ${services}
  130. }
  131. function disable_avahi_service {
  132. echo "Disable the avahi service ..."
  133. systemctl stop avahi-daemon
  134. systemctl disable avahi-daemon
  135. }
  136. function ensure_predictable_network_interfaces {
  137. echo "Ensuring predictable networking interfaces ..."
  138. # shellcheck disable=SC2010
  139. # shellcheck disable=SC2155
  140. local ethernet_interface=$(ls /sys/class/net/ | grep en)
  141. if [[ -z "${ethernet_interface}" ]]; then
  142. echo ""
  143. echo "Could not determine the ethernet interface"
  144. echo "Please ensure you've configure 'predictable network interfaces'"
  145. echo "Please see https://manual.bibliotecha.info/#pre-installation for more"
  146. echo ""
  147. exit 1
  148. fi
  149. # shellcheck disable=SC2010
  150. # shellcheck disable=SC2155
  151. local wireless_interface=$(ls /sys/class/net/ | grep wl)
  152. if [[ -z "${wireless_interface}" ]]; then
  153. echo ""
  154. echo "Could not determine the wireless interface"
  155. echo "Please ensure you've configure 'predictable network interfaces'"
  156. echo "Please see https://manual.bibliotecha.info/#pre-installation for more"
  157. echo ""
  158. exit 1
  159. fi
  160. }
  161. function configure_network_interfaces {
  162. echo "Configuring networking interfaces ..."
  163. # shellcheck disable=SC2010
  164. # shellcheck disable=SC2155
  165. local ethernet_interface=$(ls /sys/class/net/ | grep en)
  166. local ethernet_filename="/etc/network/interfaces.d/${ethernet_interface}"
  167. { echo "auto eth0";
  168. echo "allow-hotplug ${ethernet_interface}";
  169. echo "iface ${ethernet_interface} inet dhcp"; } > "${ethernet_filename}"
  170. # shellcheck disable=SC2010
  171. # shellcheck disable=SC2155
  172. local wireless_interface=$(ls /sys/class/net/ | grep wl)
  173. local wireless_filename="/etc/network/interfaces.d/${wireless_interface}"
  174. { echo "auto ${wireless_interface}";
  175. echo "iface ${wireless_interface} inet static";
  176. echo " address 10.0.0.1";
  177. echo " netmask 255.255.255.0"; } > "${wireless_filename}"
  178. }
  179. function configure_dnsmasq {
  180. echo "Configuring dnsmasq ..."
  181. # shellcheck disable=SC2010
  182. # shellcheck disable=SC2155
  183. local wireless_interface=$(ls /sys/class/net/ | grep wl)
  184. local wireless_filename="/etc/dnsmasq.d/${wireless_interface}.conf"
  185. { echo "bogus-priv"
  186. echo "server=/library/10.0.0.1"
  187. echo "local=/library/"
  188. echo "address=/#/10.0.0.1"
  189. echo "interface=${wireless_interface}"
  190. echo "domain=library"
  191. echo "dhcp-range=10.0.0.50,10.0.0.200,255.255.255.0,12h"
  192. echo "dhcp-option=3,10.0.0.1"
  193. echo "dhcp-option=6,10.0.0.1"
  194. echo "dhcp-authoritative"; } > "${wireless_filename}"
  195. }
  196. function configure_hostapd {
  197. echo "Configuring hostapd ..."
  198. # shellcheck disable=SC2010
  199. # shellcheck disable=SC2155
  200. local wireless_interface=$(ls /sys/class/net/ | grep wl)
  201. local hostapd_filename="/etc/hostapd/hostapd.conf"
  202. { echo "interface=${wireless_interface}"
  203. echo "ssid=Bibliotecha"
  204. echo "hw_mode=g"
  205. echo "channel=11"
  206. echo "auth_algs=1"; } > "${hostapd_filename}"
  207. sed -i \
  208. 's/#DAEMON_CONF=""/DAEMON_CONF="\/etc\/hostapd\/hostapd.conf"/g' \
  209. /etc/default/hostapd
  210. }
  211. function configure_etc_hosts {
  212. echo "Configuring /etc/hosts entry ..."
  213. if ! grep -q "bibliotecha.library" /etc/hosts; then
  214. echo '10.0.0.1 bibliotecha.library' >> /etc/hosts
  215. fi
  216. }
  217. function enable_networking_services {
  218. echo "Enabling network services ..."
  219. local services="dnsmasq hostapd"
  220. systemctl unmask hostapd
  221. # shellcheck disable=SC2086
  222. systemctl enable ${services}
  223. }
  224. function install_webserver {
  225. echo "Installing lighttpd ..."
  226. $APT_INSTALL_CMD lighttpd
  227. }
  228. function configure_webserver {
  229. echo "Configuring bibliotecha under lighttpd ..."
  230. if ! grep -q mod_proxy /etc/lighttpd/lighttpd.conf; then
  231. echo ""
  232. echo 'server.modules += ("mod_proxy",)' >> /etc/lighttpd/lighttpd.conf
  233. fi
  234. if ! grep -q bibliotecha /etc/lighttpd/lighttpd.conf; then
  235. echo ""
  236. echo 'include "bibliotecha/bibliotecha.conf"' >> /etc/lighttpd/lighttpd.conf
  237. fi
  238. sed -i \
  239. 's/server.document-root.*/server.document-root = "\/var\/www"/g' \
  240. /etc/lighttpd/lighttpd.conf
  241. mkdir -p "$LIGHTTPD_CONFIG_PATH"
  242. { echo 'server.error-handler-404 = "/bibliotecha/index.html"'
  243. echo ""
  244. # shellcheck disable=SC2016
  245. echo '$HTTP["host"] == "bibliotecha.library" {'
  246. echo ' proxy.server = ("" => (("host" => "127.0.0.1", "port" => "8083")))'
  247. echo '}'; } > "$LIGHTTPD_CONFIG_PATH/bibliotecha.conf"
  248. }
  249. function configure_captive_portal {
  250. echo "Configuring the captive portal page ..."
  251. $APT_INSTALL_CMD wget
  252. captive_portal_url="https://git.vvvvvvaria.org/varia/bibliotecha-captive-portal/raw/branch/master/index.html"
  253. mkdir -p "$CAPTIVE_PORTAL_PATH"
  254. wget "$captive_portal_url" -O "$CAPTIVE_PORTAL_PATH/index.html"
  255. chown -R www-data: "$CAPTIVE_PORTAL_PATH"
  256. }
  257. function install_calibre {
  258. echo "Install Calibre ..."
  259. $APT_INSTALL_CMD calibre
  260. }
  261. function configure_calibre_database {
  262. echo "Configuring the Calibre database ..."
  263. mkdir -p "$CALIBRE_DATABASE_PATH"
  264. # A dirty hack to initialise a new calibre database
  265. /usr/bin/calibredb restore_database --really-do-it --with-library "$CALIBRE_DATABASE_PATH"
  266. }
  267. function install_calibreweb {
  268. echo "Installing Calibre-web ..."
  269. $APT_INSTALL_CMD git python3 python3-pip python3-dev python3-venv
  270. calibre_web_url="https://github.com/janeczku/calibre-web"
  271. if [ ! -d "$CALIBRE_WEB_PATH" ]; then
  272. git clone "$calibre_web_url" "$CALIBRE_WEB_PATH"
  273. fi
  274. if [ ! -d "$CALIBRE_WEB_PATH/.venv" ]; then
  275. # shellcheck disable=SC1091
  276. cd "$CALIBRE_WEB_PATH" && \
  277. python3 -m venv .venv && \
  278. .venv/bin/pip install -r requirements.txt
  279. fi
  280. chown -R www-data: "$CALIBRE_WEB_PATH"
  281. }
  282. function configure_calibreweb {
  283. echo "Configuring Calibre-web ..."
  284. { echo "Description=Calibre-Web"
  285. echo ""
  286. echo "[Service]"
  287. echo "Type=simple"
  288. echo "User=root"
  289. echo "ExecStart=$CALIBRE_WEB_PATH/.venv/bin/python $CALIBRE_WEB_PATH/cps.py"
  290. echo "WorkingDirectory=$CALIBRE_WEB_PATH"
  291. echo ""
  292. echo "[Install]"
  293. echo "WantedBy=multi-user.target"; } > /etc/systemd/system/cps.service
  294. systemctl enable cps.service
  295. }
  296. function show_post_install_banner {
  297. echo ""
  298. echo "Installation complete!"
  299. echo ""
  300. }
  301. function install_new_motd {
  302. echo "Installing the new MOTD ..."
  303. { echo ""
  304. echo ""
  305. echo " ____ _ _ _ _ _ _ "
  306. echo " | _ \(_) | | (_) | | | |"
  307. echo " | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _ "
  308. echo " | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _' |"
  309. echo " | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |"
  310. echo " |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|"
  311. echo ""
  312. echo " Digital books need libraries too"
  313. echo ""
  314. echo ""; } > /etc/motd
  315. }
  316. function reboot_system {
  317. echo "Rebooting system ..."
  318. reboot
  319. }
  320. function run_installation {
  321. ensure_root_account
  322. ensure_buster_based_distribution
  323. ensure_predictable_network_interfaces
  324. show_bibliotecha_banner
  325. show_introduction_text
  326. run_apt_update
  327. install_networking_packages
  328. stop_networking_services
  329. disable_avahi_service
  330. configure_network_interfaces
  331. configure_dnsmasq
  332. configure_hostapd
  333. configure_etc_hosts
  334. enable_networking_services
  335. install_webserver
  336. configure_webserver
  337. configure_captive_portal
  338. install_calibre
  339. configure_calibre_database
  340. install_calibreweb
  341. configure_calibreweb
  342. show_post_install_banner
  343. install_new_motd
  344. reboot_system
  345. }
  346. run_installation
  347. exit 0