--- /dev/null
+#! /bin/bash
+
+ESC=$'\e'
+col_red="${ESC}[1;31m"
+col_green_bold="${ESC}[1;32m"
+col_green="${ESC}[32m"
+col_yellow="${ESC}[1;33m"
+#col_cyan="${ESC}[1;36m"
+col_reset="${ESC}[0m"
+
+opt_destdir=/srv/musiikki
+opt_adminpwfile=${opt_destdir}/htpasswd
+opt_verbose=1
+opt_uid=
+opt_gid=
+opt_apt=
+opt_hostname=
+opt_essid=
+opt_wpakey=
+opt_subnet=
+
+# default name of Raspian
+default_hostname=raspberrypi
+
+echo_ok()
+{
+ echo "${col_green}$*${col_reset}"
+}
+
+echo_ok_bold()
+{
+ echo "${col_green_bold}$*${col_reset}"
+}
+
+echo_error()
+{
+ echo "${col_red}$*${col_reset}"
+}
+
+echo_verbose()
+{
+ test $opt_verbose -eq 1 || return
+
+ echo -n "$*"
+}
+
+echo_newline_verbose()
+{
+ test $opt_verbose -eq 1 || return
+
+ echo ""
+}
+
+# ------------------------------------------------------------
+
+assert_system_uidgid()
+{
+ test -z "$opt_uid" || return
+
+ if [ -d ${opt_destdir} ]
+ then
+ opt_uid=$(stat --format=%u ${opt_destdir})
+ opt_gid=$(stat --format=%g ${opt_destdir})
+ else
+ echo -n "${col_yellow}Set file owner to${col_reset}: "
+ read opt_uid
+
+ echo -n "${col_yellow}Set file group to${col_reset}: "
+ read opt_gid
+ fi
+}
+
+assert_system_hostname()
+{
+ test -z "$opt_hostname" || return
+
+ echo -n "${col_yellow}Set hostname to${col_reset}: "
+ read opt_hostname
+}
+
+assert_system_essid()
+{
+ test -z "$opt_essid" || return
+
+ if [ -f /etc/musiikki.conf ]
+ then
+ opt_essid=$(grep '^title=' /etc/musiikki.conf)
+ opt_essid=${opt_essid#title=}
+ else
+ if [ -f /etc/hostapd/hostapd.conf ]
+ then
+ opt_essid=$(grep '^ssid=' /etc/hostapd/hostapd.conf)
+ opt_essid=${opt_essid#ssid=}
+ else
+ echo -n "${col_yellow}Set Wireless ESSID to${col_reset}: "
+ read opt_essid
+ fi
+ fi
+}
+
+assert_system_wpakey()
+{
+ test -z "$opt_wpakey" || return
+
+ if [ -f /etc/hostapd/hostapd.conf ]
+ then
+ opt_wpakey=$(grep '^wpa_passphrase=' /etc/hostapd/hostapd.conf)
+ opt_wpakey=${opt_wpakey#wpa_passphrase=}
+ else
+ echo -n "${col_yellow}Set Wireless WPA key to${col_reset}: "
+ read opt_wpakey
+ fi
+}
+
+assert_system_subnet()
+{
+ test -z "$opt_subnet" || return
+
+
+ if grep -q '^server\.bind' /etc/lighttpd/lighttpd.conf
+ then
+ opt_subnet=$(grep '^server\.bind\s' /etc/lighttpd/lighttpd.conf)
+ opt_subnet=${opt_subnet#*\"}
+ opt_subnet=${opt_subnet%.1\"*}
+ else
+ echo -n "${col_yellow}Set subnet (3 octets only) to${col_reset}: "
+ read opt_subnet
+ fi
+}
+
+# ------------------------------------------------------------
+
+welcome()
+{
+ echo
+ echo_ok_bold "Installing Infodrom MediaServer"
+ echo
+}
+
+assert_root()
+{
+ if [ "$(/usr/bin/whoami)" != "root" ]
+ then
+ echo_error "The installation needs to be done as root"
+ return 1
+ fi
+
+ return 0
+}
+
+assert_directory()
+{
+ if [ ! -x install-system ]
+ then
+ echo_error "Current directory lacks executable install-system"
+ return 1
+ fi
+
+ if [ ! -d bin ]
+ then
+ echo_error "Current directory lacks bin directory"
+ return 1
+ fi
+
+ if [ ! -d config-templates ]
+ then
+ echo_error "Current directory lacks config-templates directory"
+ return 1
+ fi
+
+ if [ "$(pwd)" != "${opt_destdir}" -a -x /usr/bin/rsync ]
+ then
+ assert_system_uidgid
+
+ # Relocate ourself
+ rsync -arH ./ ${opt_destdir}/
+ chown -R ${opt_uid}.${opt_gid} ${opt_destdir}
+ fi
+
+ return 0
+}
+
+assert_hostname()
+{
+ if [ "$(cat /etc/hostname)" = "$default_hostname" ]
+ then
+ echo_verbose "Default hostname found"; echo_newline_verbose
+ assert_system_hostname
+ echo $opt_hostname > /etc/hostname
+ printf "192.168.1.1\t%s\n" "$opt_hostname" >> /etc/hosts
+ fi
+}
+
+assert_programs()
+{
+
+ echo_verbose "Looking for programs: "
+
+ echo_verbose "sed... "
+ if [ ! -x /bin/sed ]
+ then
+ echo_newline_verbose
+ echo_error "Program sed missing"
+ return 1
+ fi
+
+ echo_verbose "dpkg... "
+ if [ ! -x /usr/bin/dpkg ]
+ then
+ echo_newline_verbose
+ echo_error "Program dpkg missing"
+ return 1
+ fi
+
+ echo_verbose "apt-get... "
+ if [ -x /usr/bin/apt-get ]
+ then
+ opt_apt=/usr/bin/apt-get
+ else
+ echo_verbose "apt... "
+ if [ -x /usr/bin/apt ]
+ then
+ opt_apt=/usr/bin/apt
+ else
+ echo_verbose "aptitude... "
+ if [ -x /usr/bin/aptitude ]
+ then
+ opt_apt=/usr/bin/aptitude
+ else
+ echo_newline_verbose
+ echo_error "High-level package manager missing (apt-get/apt/aptitude)"
+ return 1
+ fi
+ fi
+ fi
+
+ echo_newline_verbose
+
+ return 0
+}
+
+assert_no_recommends()
+{
+ if ! grep -q 'APT::Install-Recommends False;' /etc/apt/apt.conf.d/*
+ then
+ echo_ok "Configure APT not to install recommended packages"
+ echo 'APT::Install-Recommends False;' > /etc/apt/apt.conf.d/40recommends
+ fi
+}
+
+install_packages()
+{
+ if [ -z "$opt_apt" ]
+ then
+ echo_error "No high-level package manager available"
+ return 1
+ fi
+
+ set -e
+ $opt_apt update
+ $opt_apt install -y $*
+ set +e
+
+ return 0
+}
+
+remove_packages()
+{
+ if [ -z "$opt_apt" ]
+ then
+ echo_error "No high-level package manager available"
+ return 1
+ fi
+
+ set -e
+ $opt_apt purge -y $*
+ set +e
+
+ return 0
+}
+
+package_exists()
+{
+ local pkg=$1
+
+ if [ -f "/var/lib/dpkg/info/${pkg}.list" ]
+ then
+ return 0
+ else
+ return 1
+ fi
+}
+
+assert_packages()
+{
+ missing=
+
+ echo_verbose "Looking for installed packages: "
+
+ for pkg in sudo super rsync hostapd isc-dhcp-server minidlna lighttpd samba php7.0-cgi php7.0-json
+ do
+ echo_verbose "${pkg}... "
+ if ! package_exists ${pkg}
+ then
+ missing="$missing $pkg"
+ fi
+ done
+
+ echo_newline_verbose
+
+ if [ -n "$missing" ]
+ then
+ echo_ok "Installing$missing"
+ install_packages $missing || return 1
+ echo_ok "Successfully installed$missing"
+ fi
+
+ toomuch=
+
+ echo_verbose "Looking for installed packages: "
+
+ for pkg in triggerhappy avahi-daemon
+ do
+ echo_verbose "${pkg}... "
+ if package_exists ${pkg}
+ then
+ toomuch="$toomuch $pkg"
+ fi
+ done
+
+ echo_newline_verbose
+
+ if [ -n "$toomuch" ]
+ then
+ echo_ok "Removing$toomuch"
+ remove_packages $toomuch || return 1
+ echo_ok "Successfully removed$toomuch"
+ fi
+}
+
+assert_musiikki()
+{
+ if [ ! -f /etc/musiikki.conf ]
+ then
+ assert_system_essid
+
+ echo_ok "Installing main configuration"
+ sed "s/{essid}/${opt_essid}/g;s!{basedir}!${opt_destdir}!g;s!{htpasswd}!${opt_adminpwfile}!g" config-templates/musiikki.conf.template > /root/.template
+ install -o root -g root -m 644 /root/.template /etc/musiikki.conf
+ rm -f /root/.template
+ fi
+}
+
+assert_hostapd()
+{
+ if [ ! -f /etc/hostapd/hostapd.conf ]
+ then
+ assert_system_essid
+ assert_system_wpakey
+
+ echo_ok "Create hostapd configuration"
+ sed "s/{essid}/${opt_essid}/g;s/{wpakey}/${opt_wpakey}/g" config-templates/hostapd.conf.template > /root/.template
+ install -o root -g root -m 644 /root/.template /etc/hostapd/hostapd.conf
+ rm -f /root/.template
+ fi
+
+ if grep -q '#DAEMON_CONF=""' /etc/default/hostapd
+ then
+ echo_ok "Activate hostapd"
+ sed -i 's!#DAEMON_CONF=""!DAEMON_CONF="/etc/hostapd/hostapd.conf"!' /etc/default/hostapd
+ fi
+}
+
+assert_dhcpd()
+{
+ assert_system_subnet
+
+ if ! grep -q "^subnet ${opt_subnet}.0 " /etc/dhcp/dhcpd.conf
+ then
+ echo_ok "Add DHCP configuration"
+ sed "s/{subnet}/${opt_subnet}/g" config-templates/dhcpd.conf.template >> /etc/dhcp/dhcpd.conf
+ fi
+
+ if grep -q 'INTERFACESv4=""' /etc/default/isc-dhcp-server
+ then
+ echo_ok "Add WLAN interface to DCHP config"
+ sed -i 's/INTERFACESv4=".*"/INTERFACESv4="wlan0"/' /etc/default/isc-dhcp-server
+ fi
+}
+
+assert_super()
+{
+ echo_verbose "Asserting permissions "
+ for prg in $(cd bin && echo *)
+ do
+ test $prg != musiikki-rescan || continue
+
+ echo_verbose "${prg}... "
+ if ! grep -q "^${prg}" /etc/super.tab
+ then
+ printf "%s\t%s/bin/%s www-data u+g=root password=n\n" ${prg} ${opt_destdir} ${prg} >> /etc/super.tab
+ fi
+ done
+
+ echo_newline_verbose
+}
+
+assert_minidlna()
+{
+ assert_system_essid
+ assert_system_subnet
+
+ if ! grep -q "^friendly_name=${opt_essid}" /etc/minidlna.conf
+ then
+ sed -i "s!#friendly_name=!friendly_name=${opt_essid}!;s!^media_dir=.*!!" /etc/minidlna.conf
+ sed -i "s!#listening_ip=!listening_ip=${opt_subnet}.1!" /etc/minidlna.conf
+ sed -i "s!#db_dir=.*!db_dir=/media/music/cache!" /etc/minidlna.conf
+
+ echo "" >> /etc/minidlna.conf
+ echo "model_name=${opt_essid}" >> /etc/minidlna.conf
+ echo "media_dir=A,/media/music/music" >> /etc/minidlna.conf
+ echo "media_dir=P,/media/music/pictures" >> /etc/minidlna.conf
+ echo "media_dir=V,/media/music/video" >> /etc/minidlna.conf
+ fi
+
+ chmod o+rx /var/cache/minidlna
+}
+
+assert_lighttpd()
+{
+ echo_verbose "Asserting lighttpd modules "
+
+
+ echo_verbose "05-auth... "
+ if [ ! -f /etc/lighttpd/conf-enabled/05-auth.conf ]
+ then
+ assert_system_essid
+
+ cat <<EOT > /etc/lighttpd/conf-enabled/05-auth.conf
+# /usr/share/doc/lighttpd/authentication.txt.gz
+
+server.modules += ( "mod_auth" )
+
+auth.backend = "plain"
+auth.backend.plain.userfile = "${opt_adminpwfile}"
+# auth.backend.plain.groupfile = "lighttpd.group"
+
+auth.require = ( "/admin/" =>
+ (
+ "method" => "basic",
+ "realm" => "${opt_essid}",
+ "require" => "user=admin",
+ )
+ )
+EOT
+ fi
+
+ for name in 10-fastcgi 15-fastcgi-php
+ do
+ echo_verbose "${name}... "
+ if [ ! -f /etc/lighttpd/conf-enabled/${name}.conf ]
+ then
+ ln -s ../conf-available/${name}.conf /etc/lighttpd/conf-enabled/${name}.conf
+ fi
+ done
+
+ echo_newline_verbose
+
+ if [ ! -f ${opt_adminpwfile} ]
+ then
+ echo -n "${col_yellow}Set web admin password to${col_reset}: "
+ read admin_pw
+
+ echo "admin:${admin_pw}" > ${opt_adminpwfile}
+ fi
+
+ chown www-data.www-data ${opt_adminpwfile}
+
+ if ! grep -q '^server.tag' /etc/lighttpd/lighttpd.conf
+ then
+ assert_system_essid
+ assert_system_subnet
+
+ sed -i "s!^server.document-root\\s*=\\s*\".*\"!server.document-root = \"${opt_destdir}/html\"!" /etc/lighttpd/lighttpd.conf
+ echo "server.tag = \"${opt_essid}\"" >> /etc/lighttpd/lighttpd.conf
+ echo "server.bind = \"${opt_subnet}.1\"" >> /etc/lighttpd/lighttpd.conf
+ fi
+}
+
+assert_samba()
+{
+ if ! grep -q '^\[musicread\]$' /etc/samba/smb.conf
+ then
+ echo_ok "Add shares to Samba"
+ sed "s/{essid}/${opt_essid}/g" config-templates/smb.conf.template >> /etc/samba/smb.conf
+ fi
+
+ if ! grep -q '^musicread:' /etc/passwd
+ then
+ assert_system_essid
+
+ echo_ok "Create read/only Samba account"
+ adduser --quiet --disabled-password --system --group --no-create-home --home /var/lib/misc --gecos "${opt_essid} read/only account" musicread
+ fi
+
+ if ! grep -q '^musicwrite:' /etc/passwd
+ then
+ assert_system_essid
+
+ echo_ok "Create read/write Samba account"
+ adduser --quiet --disabled-password --system --group --no-create-home --home /var/lib/misc --gecos "${opt_essid} read/write account" musicwrite
+ fi
+}
+
+assert_cron()
+{
+ if [ ! -f /etc/cron.d/musiikki ]
+ then
+ echo_ok "Install crontab"
+ cp config-templates/cron.d.template /etc/cron.d/musiikki
+ fi
+
+ if [ ! -d /var/local/musiikki ]
+ then
+ install -d -o minidlna -g minidlna -m 755 /var/local/musiikki
+ fi
+
+ if [ ! -d /var/local/musiikki/rescan ]
+ then
+ install -d -o minidlna -g minidlna -m 777 /var/local/musiikki/rescan
+ fi
+}
+
+
+welcome
+
+assert_root || exit 2
+assert_directory || exit 2
+assert_hostname || exit 2
+assert_programs || exit 2
+assert_no_recommends || exit 2
+assert_packages || exit 2
+
+assert_musiikki
+assert_hostapd
+assert_dhcpd
+assert_super
+assert_minidlna
+assert_lighttpd
+assert_samba
+assert_cron