|
|
|
#!/bin/bash
|
|
|
|
# ____ _ _ _ _ _ _
|
|
|
|
# | _ \(_) | | (_) | | | |
|
|
|
|
# | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _
|
|
|
|
# | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _` |
|
|
|
|
# | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |
|
|
|
|
# |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|
|
|
|
|
#
|
|
|
|
# Digital books need libraries too
|
|
|
|
#
|
|
|
|
# This install script is intended for use with Debian based
|
|
|
|
# distributions. More specifically, Debian Buster, which is
|
|
|
|
# currently the latest distribution release from the Debian
|
|
|
|
# project.
|
|
|
|
#
|
|
|
|
# License
|
|
|
|
# =======
|
|
|
|
#
|
|
|
|
# Copyright (C) 2019 Bibliotecha Contributors <info@varia.zone>
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see http://www.gnu.org/licenses/.
|
|
|
|
#
|
|
|
|
# Thanks
|
|
|
|
# =====
|
|
|
|
#
|
|
|
|
# This script is based on the good work of the Freedombone project:
|
|
|
|
# https://code.freedombone.net/bashrc/freedombone/src/stretch/src/freedombone
|
|
|
|
|
|
|
|
APT_CMD="apt -q"
|
|
|
|
APT_INSTALL_CMD="$APT_CMD install -y --no-install-recommends"
|
|
|
|
|
|
|
|
CALIBRE_DATABASE_PATH="/opt/calibre-database"
|
|
|
|
CAPTIVE_PORTAL_PATH="/var/www/bibliotecha"
|
|
|
|
CALIBRE_WEB_PATH="/var/www/calibre-web"
|
|
|
|
LIGHTTPD_CONFIG_PATH="/etc/lighttpd/bibliotecha"
|
|
|
|
|
|
|
|
function ensure_root_account {
|
|
|
|
echo "Checking user account ..."
|
|
|
|
|
|
|
|
if ! id | grep -q root; then
|
|
|
|
echo ""
|
|
|
|
echo "This script must be run as root"
|
|
|
|
echo "You can switch to the root user account with:"
|
|
|
|
echo "$ sudo -i"
|
|
|
|
echo ""
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function show_bibliotecha_banner {
|
|
|
|
echo ""
|
|
|
|
echo " ____ _ _ _ _ _ _ "
|
|
|
|
echo " | _ \(_) | | (_) | | | |"
|
|
|
|
echo " | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _ "
|
|
|
|
echo " | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _' |"
|
|
|
|
echo " | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |"
|
|
|
|
echo " |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|"
|
|
|
|
echo ""
|
|
|
|
echo " Digital books need libraries too"
|
|
|
|
echo ""
|
|
|
|
}
|
|
|
|
|
|
|
|
function show_introduction_text {
|
|
|
|
echo ""
|
|
|
|
echo "Welcome to the Bibliotecha automatic installation script"
|
|
|
|
echo ""
|
|
|
|
echo "This script will attempt to setup the following infrastructure:"
|
|
|
|
echo ""
|
|
|
|
echo "* A Python 3 environment"
|
|
|
|
echo "* A Wifi hotspot with DNS and DHCP services enabled"
|
|
|
|
echo "* A web server"
|
|
|
|
echo "* A Calibre library"
|
|
|
|
echo "* A Calibre-web service"
|
|
|
|
echo ""
|
|
|
|
echo "Once the script is finished, please see post-install steps"
|
|
|
|
echo "that are documented and available from the Bibliotecha manual:"
|
|
|
|
echo ""
|
|
|
|
echo " https://manual.bibliotecha.info/#post-installation"
|
|
|
|
echo ""
|
|
|
|
echo "If anything goes wrong, please see the troubleshooting guide"
|
|
|
|
echo ""
|
|
|
|
echo " https://manual.bibliotecha.info/#troubleshooting"
|
|
|
|
echo ""
|
|
|
|
echo "Waiting a few seconds before moving on ..."
|
|
|
|
sleep 10
|
|
|
|
}
|
|
|
|
|
|
|
|
function ensure_buster_based_distribution {
|
|
|
|
echo "Checking distribution ..."
|
|
|
|
|
|
|
|
local installing_on_buster_based=1
|
|
|
|
|
|
|
|
if [ ! -f /etc/apt/sources.list ]; then
|
|
|
|
installing_on_buster_based=
|
|
|
|
else
|
|
|
|
if ! grep -q 'buster' /etc/apt/sources.list; then
|
|
|
|
installing_on_buster_based=
|
|
|
|
fi
|
|
|
|
if ! grep -q 'debian' /etc/apt/sources.list; then
|
|
|
|
if ! grep -q 'raspbian' /etc/apt/sources.list; then
|
|
|
|
installing_on_buster_based=
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! $installing_on_buster_based ]; then
|
|
|
|
echo "You should only run this on a Debian Buster based system"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function run_apt_update {
|
|
|
|
echo "Running a package listing update ..."
|
|
|
|
|
|
|
|
$APT_CMD update
|
|
|
|
}
|
|
|
|
|
|
|
|
function install_networking_packages {
|
|
|
|
echo "Installing networking packages ..."
|
|
|
|
|
|
|
|
$APT_INSTALL_CMD \
|
|
|
|
dhcpcd \
|
|
|
|
dnsmasq \
|
|
|
|
dnsutils \
|
|
|
|
hostapd \
|
|
|
|
wireless-tools
|
|
|
|
}
|
|
|
|
|
|
|
|
function stop_networking_services {
|
|
|
|
echo "Stopping the networking services ..."
|
|
|
|
|
|
|
|
local services="dnsmasq hostapd"
|
|
|
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
systemctl stop ${services}
|
|
|
|
}
|
|
|
|
|
|
|
|
function disable_avahi_service {
|
|
|
|
echo "Disable the avahi service ..."
|
|
|
|
|
|
|
|
systemctl stop avahi-daemon
|
|
|
|
systemctl disable avahi-daemon
|
|
|
|
}
|
|
|
|
|
|
|
|
function ensure_predictable_network_interfaces {
|
|
|
|
echo "Ensuring predictable networking interfaces ..."
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local ethernet_interface=$(ls /sys/class/net/ | grep en)
|
|
|
|
|
|
|
|
if [[ -z "${ethernet_interface}" ]]; then
|
|
|
|
echo ""
|
|
|
|
echo "Could not determine the ethernet interface"
|
|
|
|
echo "Please ensure you've configure 'predictable network interfaces'"
|
|
|
|
echo "Please see https://manual.bibliotecha.info/#pre-installation for more"
|
|
|
|
echo ""
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local wireless_interface=$(ls /sys/class/net/ | grep wl)
|
|
|
|
|
|
|
|
if [[ -z "${wireless_interface}" ]]; then
|
|
|
|
echo ""
|
|
|
|
echo "Could not determine the wireless interface"
|
|
|
|
echo "Please ensure you've configure 'predictable network interfaces'"
|
|
|
|
echo "Please see https://manual.bibliotecha.info/#pre-installation for more"
|
|
|
|
echo ""
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_network_interfaces {
|
|
|
|
echo "Configuring networking interfaces ..."
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local ethernet_interface=$(ls /sys/class/net/ | grep en)
|
|
|
|
local ethernet_filename="/etc/network/interfaces.d/${ethernet_interface}"
|
|
|
|
|
|
|
|
{ echo "auto ${ethernet_interface}";
|
|
|
|
echo "allow-hotplug ${ethernet_interface}";
|
|
|
|
echo "iface ${ethernet_interface} inet dhcp"; } > "${ethernet_filename}"
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local wireless_interface=$(ls /sys/class/net/ | grep wl)
|
|
|
|
local wireless_filename="/etc/network/interfaces.d/${wireless_interface}"
|
|
|
|
|
|
|
|
{ echo "auto ${wireless_interface}";
|
|
|
|
echo "iface ${wireless_interface} inet static";
|
|
|
|
echo " address 10.0.0.1";
|
|
|
|
echo " netmask 255.255.255.0"; } > "${wireless_filename}"
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_dnsmasq {
|
|
|
|
echo "Configuring dnsmasq ..."
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local wireless_interface=$(ls /sys/class/net/ | grep wl)
|
|
|
|
local wireless_filename="/etc/dnsmasq.d/${wireless_interface}.conf"
|
|
|
|
|
|
|
|
{ echo "bogus-priv"
|
|
|
|
echo "server=/library/10.0.0.1"
|
|
|
|
echo "local=/library/"
|
|
|
|
echo "address=/#/10.0.0.1"
|
|
|
|
echo "interface=${wireless_interface}"
|
|
|
|
echo "domain=library"
|
|
|
|
echo "dhcp-range=10.0.0.50,10.0.0.200,255.255.255.0,12h"
|
|
|
|
echo "dhcp-option=3,10.0.0.1"
|
|
|
|
echo "dhcp-option=6,10.0.0.1"
|
|
|
|
echo "dhcp-authoritative"; } > "${wireless_filename}"
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_hostapd {
|
|
|
|
echo "Configuring hostapd ..."
|
|
|
|
|
|
|
|
# shellcheck disable=SC2010
|
|
|
|
# shellcheck disable=SC2155
|
|
|
|
local wireless_interface=$(ls /sys/class/net/ | grep wl)
|
|
|
|
local hostapd_filename="/etc/hostapd/hostapd.conf"
|
|
|
|
|
|
|
|
{ echo "interface=${wireless_interface}"
|
|
|
|
echo "ssid=Bibliotecha"
|
|
|
|
echo "hw_mode=g"
|
|
|
|
echo "channel=11"
|
|
|
|
echo "auth_algs=1"; } > "${hostapd_filename}"
|
|
|
|
|
|
|
|
sed -i \
|
|
|
|
's/#DAEMON_CONF=""/DAEMON_CONF="\/etc\/hostapd\/hostapd.conf"/g' \
|
|
|
|
/etc/default/hostapd
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_etc_hosts {
|
|
|
|
echo "Configuring /etc/hosts entry ..."
|
|
|
|
|
|
|
|
if ! grep -q "bibliotecha.library" /etc/hosts; then
|
|
|
|
echo '10.0.0.1 bibliotecha.library' >> /etc/hosts
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
function enable_networking_services {
|
|
|
|
echo "Enabling network services ..."
|
|
|
|
|
|
|
|
local services="dnsmasq hostapd"
|
|
|
|
|
|
|
|
systemctl unmask hostapd
|
|
|
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
systemctl enable ${services}
|
|
|
|
}
|
|
|
|
|
|
|
|
function install_webserver {
|
|
|
|
echo "Installing lighttpd ..."
|
|
|
|
|
|
|
|
$APT_INSTALL_CMD lighttpd
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_webserver {
|
|
|
|
echo "Configuring bibliotecha under lighttpd ..."
|
|
|
|
|
|
|
|
if ! grep -q mod_proxy /etc/lighttpd/lighttpd.conf; then
|
|
|
|
echo ""
|
|
|
|
echo 'server.modules += ("mod_proxy",)' >> /etc/lighttpd/lighttpd.conf
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! grep -q bibliotecha /etc/lighttpd/lighttpd.conf; then
|
|
|
|
echo ""
|
|
|
|
echo 'include "bibliotecha/bibliotecha.conf"' >> /etc/lighttpd/lighttpd.conf
|
|
|
|
fi
|
|
|
|
|
|
|
|
sed -i \
|
|
|
|
's/server.document-root.*/server.document-root = "\/var\/www"/g' \
|
|
|
|
/etc/lighttpd/lighttpd.conf
|
|
|
|
|
|
|
|
mkdir -p "$LIGHTTPD_CONFIG_PATH"
|
|
|
|
|
|
|
|
{ echo 'server.error-handler-404 = "/bibliotecha/index.html"'
|
|
|
|
echo ""
|
|
|
|
# shellcheck disable=SC2016
|
|
|
|
echo '$HTTP["host"] == "bibliotecha.library" {'
|
|
|
|
echo ' proxy.server = ("" => (("host" => "127.0.0.1", "port" => "8083")))'
|
|
|
|
echo '}'; } > "$LIGHTTPD_CONFIG_PATH/bibliotecha.conf"
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_captive_portal {
|
|
|
|
echo "Configuring the captive portal page ..."
|
|
|
|
|
|
|
|
$APT_INSTALL_CMD wget
|
|
|
|
|
|
|
|
captive_portal_url="https://git.vvvvvvaria.org/varia/bibliotecha-captive-portal/raw/branch/master/index.html"
|
|
|
|
|
|
|
|
mkdir -p "$CAPTIVE_PORTAL_PATH"
|
|
|
|
wget "$captive_portal_url" -O "$CAPTIVE_PORTAL_PATH/index.html"
|
|
|
|
chown -R www-data: "$CAPTIVE_PORTAL_PATH"
|
|
|
|
}
|
|
|
|
|
|
|
|
function install_calibre {
|
|
|
|
echo "Install Calibre ..."
|
|
|
|
|
|
|
|
$APT_INSTALL_CMD calibre
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_calibre_database {
|
|
|
|
echo "Configuring the Calibre database ..."
|
|
|
|
|
|
|
|
mkdir -p "$CALIBRE_DATABASE_PATH"
|
|
|
|
|
|
|
|
# A dirty hack to initialise a new calibre database
|
|
|
|
/usr/bin/calibredb restore_database --really-do-it --with-library "$CALIBRE_DATABASE_PATH"
|
|
|
|
}
|
|
|
|
|
|
|
|
function install_calibreweb {
|
|
|
|
echo "Installing Calibre-web ..."
|
|
|
|
|
|
|
|
$APT_INSTALL_CMD git python3 python3-pip python3-dev python3-venv
|
|
|
|
|
|
|
|
calibre_web_url="https://github.com/janeczku/calibre-web"
|
|
|
|
|
|
|
|
if [ ! -d "$CALIBRE_WEB_PATH" ]; then
|
|
|
|
git clone "$calibre_web_url" "$CALIBRE_WEB_PATH"
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -d "$CALIBRE_WEB_PATH/.venv" ]; then
|
|
|
|
# shellcheck disable=SC1091
|
|
|
|
cd "$CALIBRE_WEB_PATH" && \
|
|
|
|
python3 -m venv .venv && \
|
|
|
|
.venv/bin/pip install -r requirements.txt
|
|
|
|
fi
|
|
|
|
|
|
|
|
chown -R www-data: "$CALIBRE_WEB_PATH"
|
|
|
|
}
|
|
|
|
|
|
|
|
function configure_calibreweb {
|
|
|
|
echo "Configuring Calibre-web ..."
|
|
|
|
|
|
|
|
{ echo "Description=Calibre-Web"
|
|
|
|
echo ""
|
|
|
|
echo "[Service]"
|
|
|
|
echo "Type=simple"
|
|
|
|
echo "User=root"
|
|
|
|
echo "ExecStart=$CALIBRE_WEB_PATH/.venv/bin/python $CALIBRE_WEB_PATH/cps.py"
|
|
|
|
echo "WorkingDirectory=$CALIBRE_WEB_PATH"
|
|
|
|
echo ""
|
|
|
|
echo "[Install]"
|
|
|
|
echo "WantedBy=multi-user.target"; } > /etc/systemd/system/cps.service
|
|
|
|
|
|
|
|
systemctl enable cps.service
|
|
|
|
}
|
|
|
|
|
|
|
|
function show_post_install_banner {
|
|
|
|
echo ""
|
|
|
|
echo "Installation complete!"
|
|
|
|
echo ""
|
|
|
|
}
|
|
|
|
|
|
|
|
function install_new_motd {
|
|
|
|
echo "Installing the new MOTD ..."
|
|
|
|
|
|
|
|
{ echo ""
|
|
|
|
echo ""
|
|
|
|
echo " ____ _ _ _ _ _ _ "
|
|
|
|
echo " | _ \(_) | | (_) | | | |"
|
|
|
|
echo " | |_) |_| |__ | |_ ___ | |_ ___ ___| |__ __ _ "
|
|
|
|
echo " | _ <| | '_ \| | |/ _ \| __/ _ \/ __| '_ \ / _' |"
|
|
|
|
echo " | |_) | | |_) | | | (_) | || __/ (__| | | | (_| |"
|
|
|
|
echo " |____/|_|_.__/|_|_|\___/ \__\___|\___|_| |_|\__,_|"
|
|
|
|
echo ""
|
|
|
|
echo " Digital books need libraries too"
|
|
|
|
echo ""
|
|
|
|
echo ""; } > /etc/motd
|
|
|
|
}
|
|
|
|
|
|
|
|
function reboot_system {
|
|
|
|
echo "Rebooting system ..."
|
|
|
|
|
|
|
|
reboot
|
|
|
|
}
|
|
|
|
|
|
|
|
function run_installation {
|
|
|
|
ensure_root_account
|
|
|
|
ensure_buster_based_distribution
|
|
|
|
ensure_predictable_network_interfaces
|
|
|
|
|
|
|
|
show_bibliotecha_banner
|
|
|
|
show_introduction_text
|
|
|
|
|
|
|
|
run_apt_update
|
|
|
|
|
|
|
|
install_networking_packages
|
|
|
|
stop_networking_services
|
|
|
|
disable_avahi_service
|
|
|
|
configure_network_interfaces
|
|
|
|
configure_dnsmasq
|
|
|
|
configure_hostapd
|
|
|
|
configure_etc_hosts
|
|
|
|
enable_networking_services
|
|
|
|
|
|
|
|
install_webserver
|
|
|
|
configure_webserver
|
|
|
|
configure_captive_portal
|
|
|
|
|
|
|
|
install_calibre
|
|
|
|
configure_calibre_database
|
|
|
|
install_calibreweb
|
|
|
|
configure_calibreweb
|
|
|
|
|
|
|
|
show_post_install_banner
|
|
|
|
install_new_motd
|
|
|
|
reboot_system
|
|
|
|
}
|
|
|
|
|
|
|
|
run_installation
|
|
|
|
exit 0
|