Add Installation script and config templates
authorJoey Schulze <joey@infodrom.org>
Sat, 24 Nov 2018 16:38:30 +0000 (17:38 +0100)
committerJoey Schulze <joey@infodrom.org>
Sun, 25 Nov 2018 16:03:00 +0000 (17:03 +0100)
bin/musiikki-rescan
config-templates/cron.d.template [new file with mode: 0644]
config-templates/dhcpd.conf.template [new file with mode: 0644]
config-templates/hostapd.conf.template [new file with mode: 0644]
config-templates/musiikki.conf.template [new file with mode: 0644]
config-templates/smb.conf.template [new file with mode: 0644]
install-system [new file with mode: 0755]

index 4d4c068..0c912b8 100755 (executable)
@@ -21,9 +21,9 @@ fi
 # during this operation.
 #
 
-if [ -f "${rescan_file}" ]
+if [ -f "${rescan_file}" -a "${rescan_file}" -nt "${cache}" ]
 then
     rm "${rescan_file}"
-    rm -f ${cache}
+    /usr/sbin/minidlnad -R
     /usr/sbin/service minidlna restart
 fi
diff --git a/config-templates/cron.d.template b/config-templates/cron.d.template
new file mode 100644 (file)
index 0000000..56285a7
--- /dev/null
@@ -0,0 +1,3 @@
+*/5 * * * *    root    /src/musiikki/musiikki-rescan
+
+3 4 * * *      minidlna        touch /var/local/musiikki/rescan/trigger
diff --git a/config-templates/dhcpd.conf.template b/config-templates/dhcpd.conf.template
new file mode 100644 (file)
index 0000000..6edbea8
--- /dev/null
@@ -0,0 +1,9 @@
+
+subnet {subnet}.0 netmask 255.255.255.0 {
+  range {subnet}.10 {subnet}.254;
+  option broadcast-address {subnet}.255;
+  option routers {subnet}.1;
+  option domain-name ".local";
+  option domain-name-servers 127.0.0.1;
+}
+
diff --git a/config-templates/hostapd.conf.template b/config-templates/hostapd.conf.template
new file mode 100644 (file)
index 0000000..f7192d0
--- /dev/null
@@ -0,0 +1,25 @@
+interface=wlan0
+# driver=rtl871xdrv
+ssid={essid}
+country_code=US
+hw_mode=g
+channel=6
+# Accept alls MAC addresses
+macaddr_acl=0
+# Use WPA
+auth_algs=1
+ignore_broadcast_ssid=0
+# Use WPA2
+wpa=2
+#wpa_key_mgmt=WPA-PSK WPA-EAP
+# Use a pre-shared key
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+# wpa_group_rekey=86400
+# ieee80211n=1
+# Use AES, instead of TKIP
+rsn_pairwise=CCMP
+#rsn_preauth=1
+wme_enabled=1
+wmm_enabled=1
+wpa_passphrase={wpakey}
diff --git a/config-templates/musiikki.conf.template b/config-templates/musiikki.conf.template
new file mode 100644 (file)
index 0000000..16b2bae
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# /etc/musiikki.conf - Configuration for DLNA MediaServer
+#
+
+# Application title
+#
+title={essid}
+
+# Path to trigger file for rescanning music directory
+#
+rescan_file=/var/local/musiikki/rescan/trigger
+
+# Path to library files
+#
+root={basedir}
+
+# Path to files.db
+#
+cache=/media/music/cache/files.db
+
+# Path to Favourites Icon
+#
+favicon=/favicon.ico
+
+# Path to admin password file
+#
+password={htpasswd}
+
diff --git a/config-templates/smb.conf.template b/config-templates/smb.conf.template
new file mode 100644 (file)
index 0000000..66fecec
--- /dev/null
@@ -0,0 +1,21 @@
+[musicread]
+   comment = {essid} read/only
+   path = /media/music/music
+   read only = yes
+   browseable = yes
+   public = no
+   force user = www-data
+   force group = www-data
+   create mask = 0644
+   valid users = musicread
+
+[musicwrite]
+   comment = {essid} read/write
+   path = /media/music/music
+   read only = no
+   browseable = yes
+   public = no
+   force user = joey
+   force group = joey
+   create mask = 0644
+   valid users = musicwrite
diff --git a/install-system b/install-system
new file mode 100755 (executable)
index 0000000..c41efd3
--- /dev/null
@@ -0,0 +1,551 @@
+#! /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