diff --git a/install_yunohost b/install_yunohost
index 49c55cc..6cde7fb 100755
--- a/install_yunohost
+++ b/install_yunohost
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright (C) 2015 kload, beudbeud
+# Copyright (C) 2015-2017 YunoHost
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -15,81 +15,163 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-YUNOHOST_LOG="/var/log/yunohost-installation.log"
-THIS_MACHINE_RELEASE="$(lsb_release -c | awk '{print $2}')"
+set -u
-print() {
- printf "%s\n" "$*";
-}
+# Globals
+
+readonly YUNOHOST_LOG="/var/log/yunohost-installation_$(date +%Y%m%d_%H%M%S).log"
-notify_about_install_logs() {
- print "
-Installation logs are located in $YUNOHOST_LOG
-" 1>&2
+###############################################################################
+# Main functions #
+###############################################################################
+
+function usage() {
+ echo "
+Usage :
+ `basename $0` [-a] [-d ] [-h]
+Options :
+ -a Enable automatic mode. No questions are asked.
+ This does not perform the post-install step.
+ -d Choose the distribution to install ('stable', 'testing', 'unstable').
+ Defaults to 'stable'
+ -f Ignore checks before starting the installation. Use only if you know
+ what you are doing.
+ -h Prints this help and exit
+"
}
-success() {
- tput setf 2
- print "Success !"
- tput sgr 0
- notify_about_install_logs
+function parse_options()
+{
+ AUTOMODE=0
+ DISTRIB=stable
+ BUILD_IMAGE=0
+ FORCE=0
+
+ while getopts ":aid:fh" option; do
+ case $option in
+ a)
+ AUTOMODE=1
+ export DEBIAN_FRONTEND=noninteractive
+ ;;
+ d)
+ DISTRIB=$OPTARG
+ ;;
+ f)
+ FORCE=1
+ ;;
+ i)
+ # This hidden option will allow to build generic image for Rpi/Olimex
+ BUILD_IMAGE=1
+ ;;
+ h)
+ usage
+ exit 0
+ ;;
+ :)
+ usage
+ exit 1
+ ;;
+ \?)
+ usage
+ exit 1
+ ;;
+ esac
+ done
}
-die() {
- # Print to log file
- print "
-Failure !
-The following error was caught during Yunohost installation :
+function main()
+{
+ parse_options "$@"
+
+ check_assertions
-$1
-" >> $YUNOHOST_LOG
+ step upgrade_system || die "Unable to update the system"
+ step install_script_dependencies || die "Unable to install dependencies to install script"
+ step create_custom_config || die "Creating custom configuration file /etc/yunohost/yunohost.conf failed"
+ step confirm_installation || die "Installation cancelled at your request"
+ step setup_package_source || die "Setting up deb package sources failed"
+ step apt_update || die "Error caught during 'apt-get update'"
+ step register_debconf || die "Unable to insert new values into debconf database"
+ step workaround_avahi_installation || die "Unable to install workaround for avahi installation"
+ step install_yunohost_packages || die "Installation of Yunohost packages failed"
+ step restart_services || die "Error caught during services restart"
+
+ if is_raspbian ; then
+ step del_user_pi || die "Unable to delete user pi"
+ step setup_firstboot || die "Unable to setup firstboot"
+ fi
- # Print to terminal
- tput setf 4
- print "Failure !"
- tput sgr 0
+ if [[ "$BUILD_IMAGE" == "1" ]] ; then
+ step clean_image || die "Unable to clean image"
+ fi
- print "\
-The following error was caught during YunoHost installation :
+ if is_raspbian ; then
+ # Reboot should be done before postinstall to be able to run iptables rules
+ reboot
+ fi
-$1
-" 1>&2
+ step post_install || die "Post-installation failed"
- notify_about_install_logs
- exit "${2:-1}"
+ info "Installation logs are available in $YUNOHOST_LOG"
+ success "YunoHost installation completed !"
+ exit 0
}
-step() {
- printf "[ $(date --rfc-3339=seconds) ] ----- [ entering %-30s ]\n" "$1" >> $YUNOHOST_LOG
- $*
- local return_code="$?"
- return $return_code
+###############################################################################
+# Helpers #
+###############################################################################
+
+readonly normal=$(printf '\033[0m')
+readonly bold=$(printf '\033[1m')
+readonly faint=$(printf '\033[2m')
+readonly underline=$(printf '\033[4m')
+readonly negative=$(printf '\033[7m')
+readonly red=$(printf '\033[31m')
+readonly green=$(printf '\033[32m')
+readonly orange=$(printf '\033[33m')
+readonly blue=$(printf '\033[34m')
+readonly yellow=$(printf '\033[93m')
+readonly white=$(printf '\033[39m')
+
+function success()
+{
+ local msg=${1}
+ echo "[${bold}${green} OK ${normal}] ${msg}" | tee -a $YUNOHOST_LOG
}
-ensure_root() {
- if [[ "$(id -u)" != "0" ]] ;
- then
- return 1
- fi
- return 0
+function info()
+{
+ local msg=${1}
+ echo "[${bold}${blue}INFO${normal}] ${msg}" | tee -a $YUNOHOST_LOG
}
-ensure_pi_logout() {
- who | grep pi > /dev/null && return 1
- return 0
+function warn()
+{
+ local msg=${1}
+ echo "[${bold}${orange}WARN${normal}] ${msg}" | tee -a $YUNOHOST_LOG >&2
}
-is_raspbian() {
- # On Raspbian image lsb_release is available
- if [[ "$(lsb_release -i -s 2> /dev/null)" != "Raspbian" ]] ;
- then
- return 1
- fi
- return 0
+function error()
+{
+ local msg=${1}
+ echo "[${bold}${red}FAIL${normal}] ${msg}" | tee -a $YUNOHOST_LOG >&2
}
-apt_get_wrapper() {
+function die() {
+ error "$1"
+ info "Installation logs are available in $YUNOHOST_LOG"
+ exit 1
+}
+
+function step() {
+ info "Running $1"
+ $*
+ local return_code="$?"
+ return $return_code
+}
+
+function apt_get_wrapper() {
if [[ "$AUTOMODE" == "0" ]] ;
then
debconf-apt-progress \
@@ -101,26 +183,68 @@ apt_get_wrapper() {
fi
}
-upgrade_system() {
+
+function apt_update() {
+ apt_get_wrapper update
+}
+
+###############################################################################
+# Installation steps #
+###############################################################################
+
+function check_assertions()
+{
+ # Assert we're on Debian
+ # Note : we do not rely on lsb_release to avoid installing a dependency
+ # only to check this...
+ [[ -f "/etc/debian_version" ]] || die "This script can only be ran on Debian."
+
+ # Assert we're on Stretch
+ # Note : we do not rely on lsb_release to avoid installing a dependency
+ # only to check this...
+ [[ "$(cat /etc/debian_version)" =~ ^9.* ]] || die "This script can only be ran on Debian Stretch."
+
+ # Assert we're root
+ [[ "$(id -u)" == "0" ]] || die "This script must be run as root."
+
+ # Assert systemd is installed
+ command -v systemctl > /dev/null || die "YunoHost requires systemd to be installed."
+
+ # If we're on Raspbian, we want the user 'pi' to be logged out because
+ # it's going to be deleted for security reasons...
+ if is_raspbian ; then
+ user_pi_logged_out || die "The user pi should be logged out."
+ fi
+
+ # Check possible conflict with apache, bind9.
+ [[ -z "$(dpkg --get-selections | grep -v deinstall | grep 'bind9 ')" ]] || [[ "$FORCE" == "1" ]] \
+ || die "Bind9 is installed and might conflict with dnsmasq. Uninstall it first, or if you know what you are doing, run this script with -f."
+
+ [[ -z "$(dpkg --get-selections | grep -v deinstall | grep 'apache2 ')" ]] || [[ "$FORCE" == "1" ]] \
+ || die "Apache is installed and might conflict with nginx. Uninstall it first, or if you know what you are doing, run this script with -f."
+
+}
+
+function upgrade_system() {
apt_get_wrapper update \
|| return 1
apt_get_wrapper -y dist-upgrade \
|| return 2
-
+
if is_raspbian ; then
apt_get_wrapper -o Dpkg::Options::="--force-confold" \
-y --force-yes install rpi-update \
|| return 3
-
+
rpi-update >> $YUNOHOST_LOG 2>&1 \
|| return 4
fi
}
-installscript_dependencies() {
+function install_script_dependencies() {
# dependencies of the install script itself
local DEPENDENCIES="lsb-release wget whiptail"
@@ -133,30 +257,9 @@ installscript_dependencies() {
-y --force-yes install \
$DEPENDENCIES \
|| return 1
-
- #
- # Temporary comment for stretch...
- # To be removed if really not needed
- #
- #if is_raspbian ; then
- # DEPENDENCIES="ssl-cert lua-event lua-expat lua-socket lua-sec lua-filesystem"
- # apt_get_wrapper -o Dpkg::Options::="--force-confold" \
- # -y --force-yes install \
- # $DEPENDENCIES \
- # || return 1
- # wget -q https://build.yunohost.org/metronome_3.7.9+33b7572-1_armhf.deb \
- # || return 1
- # sha256sum -c <<<"d19c6b08afb8674d1257dc3349a60e88218c4c01133c53c1fdcb02e86b415a40 metronome_3.7.9+33b7572-1_armhf.deb" \
- # || return 1
- # dpkg -i metronome_3.7.9+33b7572-1_armhf.deb >> $YUNOHOST_LOG 2>&1 \
- # || return 1
- # apt-mark hold metronome >> $YUNOHOST_LOG 2>&1 \
- # || return 1
- #fi
-
}
-create_custom_config() {
+function create_custom_config() {
# Create YunoHost configuration folder
mkdir -p /etc/yunohost/
@@ -164,7 +267,7 @@ create_custom_config() {
touch /etc/yunohost/from_script
}
-confirm_installation() {
+function confirm_installation() {
[[ "$AUTOMODE" == "1" ]] && return 0
local text="
@@ -183,18 +286,9 @@ Are you sure you want to proceed with the installation of Yunohost?
whiptail --title "Yunohost Installation" --yesno "$text" 20 78
}
-setup_package_source() {
- local CUSTOMAPT=/etc/apt/sources.list.d/yunohost.list
+function setup_package_source() {
- # Check current system version and dependencies
-
- if [[ ! $THIS_MACHINE_RELEASE =~ ^jessie|stretch$ ]]; then
- echo "Current $DISTRIB only works on Debian Jessie or Stretch for the moment."
- return 1
- elif ! command -v systemctl > /dev/null ; then
- echo "Current $DISTRIB only works with systemd for the moment."
- return 1
- fi
+ local CUSTOMAPT=/etc/apt/sources.list.d/yunohost.list
# Debian repository
@@ -214,12 +308,8 @@ setup_package_source() {
wget -O- https://vinaigrette.yunohost.org/yunohost.asc -q | apt-key add -qq - >/dev/null 2>&1
}
-apt_update() {
- apt_get_wrapper update
-}
-
-register_debconf() {
- debconf-set-selections << EOF
+function register_debconf() {
+ debconf-set-selections << EOF
slapd slapd/password1 password yunohost
slapd slapd/password2 password yunohost
slapd slapd/domain string yunohost.org
@@ -243,7 +333,7 @@ libnss-ldapd libnss-ldapd/nsswitch multiselect group, passwd, shadow
EOF
}
-workaround_avahi_installation() {
+function workaround_avahi_installation() {
# When attempting several installation of Yunohost on the same host
# with a light VM system like LXC
@@ -262,7 +352,7 @@ workaround_avahi_installation() {
# Return without error if avahi already exists
if id avahi > /dev/null 2>&1 ; then
- print "User avahi already exists (with uid $(id avahi)), skipping avahi workaround" >> $YUNOHOST_LOG
+ info "User avahi already exists (with uid $(id avahi)), skipping avahi workaround"
return 0
fi
@@ -273,7 +363,7 @@ workaround_avahi_installation() {
avahi_id=$((500 + RANDOM % 500))
done
- print "Workaround for avahi : creating avahi user with uid $avahi_id" >> $YUNOHOST_LOG
+ info "Workaround for avahi : creating avahi user with uid $avahi_id"
# Use the same adduser parameter as in the avahi-daemon postinst script
# Just specify --uid explicitely
@@ -283,11 +373,11 @@ workaround_avahi_installation() {
--uid $avahi_id
}
-install_yunohost_packages() {
+function install_yunohost_packages() {
# Allow sudo removal even if no root password has been set (on some DO
# droplet or Vagrant virtual machines), as YunoHost use sudo-ldap
export SUDO_FORCE_REMOVE=yes
-
+
# On some machines (e.g. OVH VPS), the /etc/resolv.conf is immutable
# We need to make it mutable for the resolvconf dependency to be installed
chattr -i /etc/resolv.conf 2>/dev/null || true
@@ -299,7 +389,7 @@ install_yunohost_packages() {
yunohost yunohost-admin postfix
}
-restart_services() {
+function restart_services() {
service slapd restart
# service yunohost-firewall start
service unscd restart
@@ -309,57 +399,7 @@ restart_services() {
return 0
}
-del_user_pi() {
- deluser --remove-all-files pi >> $YUNOHOST_LOG 2>&1
-}
-
-change_hostname() {
- sed -i 's/raspberrypi/yunohost/g' /etc/hosts
- sed -i 's/raspberrypi/yunohost/g' /etc/hostname
-}
-
-setup_firstboot() {
-
- cat > /etc/init.d/yunohost-firstboot << EOF
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides: expand rootfs and Generates new ssh host keys on first boot
-# Required-Start: \$remote_fs \$syslog
-# Required-Stop: \$remote_fs \$syslog
-# Default-Start: 2 3 4 5
-# Default-Stop:
-# Short-Description: Generates new ssh host keys on first boot
-# Description: Generates apt-get --purge clean new ssh host keys on $
-### END INIT INFO
-echo "Expanding rootfs ..."
-raspi-config --expand-rootfs
-echo "Removing myself ..."
-insserv -r /etc/init.d/yunohost-firstboot
-rm -f /etc/init.d/yunohost-firstboot
-rm /etc/yunohost/firstboot
-echo "Rebooting ..."
-reboot
-EOF
- chmod a+x /etc/init.d/yunohost-firstboot
- insserv /etc/init.d/yunohost-firstboot
- touch /etc/yunohost/firstboot
-}
-
-clean_image() {
- # Delete SSH keys
- rm -f /etc/ssh/ssh_host_* >> $YUNOHOST_LOG 2>&1
- yes | ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa >> $YUNOHOST_LOG 2>&1
- yes | ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa >> $YUNOHOST_LOG 2>&1
- yes | ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa -b 521 >> $YUNOHOST_LOG 2>&1
-
- # Deleting logs ...
- find /var/log -type f -exec rm {} \; >> $YUNOHOST_LOG 2>&1
-
- # Purging apt ...
- apt-get --purge clean >> $YUNOHOST_LOG 2>&1
-}
-
-post_install() {
+function post_install() {
# No postinstall in auto mode
[[ "$AUTOMODE" == "1" ]] && return 0
@@ -406,140 +446,74 @@ Do you want to try again now?
return 0
}
-usage() {
- print "
-Usage :
- `basename $0` [-a] [-d ] [-h]
-
-Options :
- -a Enable automatic mode. No questions are asked.
- This does not perform the post-install step.
- -d Choose the distribution to install ('stable', 'testing', 'unstable').
- Defaults to 'stable'
- -h Prints this help and exit
-"
-}
+###############################################################################
+# Raspbian specific stuff #
+###############################################################################
-# Treat unset variables as an error when performing
-# parameter expansion. An error message will be written
-# to the standard error, and a non-interactive shell will exit.
-set -u
-
-AUTOMODE=0
-DISTRIB=stable
-BUILD_IMAGE=0
-while getopts ":aid:h" option; do
- case $option in
- a)
- AUTOMODE=1
- export DEBIAN_FRONTEND=noninteractive
- ;;
- d)
- DISTRIB=$OPTARG
- ;;
- i)
- # This hidden option will allow to build generic image for Rpi/Olimex
- BUILD_IMAGE=1
- ;;
- h)
- usage
- exit 0
- ;;
- :)
- usage
- exit 1
- ;;
- \?)
- usage
- exit 1
- ;;
- esac
-done
-
-if ! step ensure_root ; then
- die "This script must be run as root" 1
-fi
-
-if is_raspbian ; then
- if ! step ensure_pi_logout ; then
- die "The user pi should be logged out" 14
+function is_raspbian() {
+ # On Raspbian image lsb_release is available
+ if [[ "$(lsb_release -i -s 2> /dev/null)" != "Raspbian" ]] ;
+ then
+ return 1
fi
-fi
-
-if ! step upgrade_system ; then
- die "Unable to update the system" 2
-fi
-
-if ! step installscript_dependencies ; then
- die "Unable to install dependencies to install script" 3
-fi
-
-if ! step create_custom_config ; then
- die "Creating custom configuration file /etc/yunohost/yunohost.conf failed" 4
-fi
-
-# if ! step set_domain ; then
-# die "Setting hostname failed" 5
-# fi
-
-if ! step confirm_installation ; then
- die "Installation cancelled at your request" 6
-fi
-
-if ! step setup_package_source ; then
- die "Setting up deb package sources failed" 7
-fi
-
-if ! step apt_update ; then
- die "Error caught during 'apt-get update'" 8
-fi
+ return 0
+}
-if ! step register_debconf ; then
- die "Unable to insert new values into debconf database" 9
-fi
+function user_pi_logged_out() {
+ who | grep pi > /dev/null && return 1
+ return 0
+}
-if ! step workaround_avahi_installation ; then
- die "Unable to install workaround for avahi installation" 10
-fi
+function del_user_pi() {
+ deluser --remove-all-files pi >> $YUNOHOST_LOG 2>&1
+}
-if ! step install_yunohost_packages ; then
- die "Installation of Yunohost packages failed" 11
-fi
+function setup_firstboot() {
-if ! step restart_services ; then
- die "Error caught during services restart" 12
-fi
+ cat > /etc/init.d/yunohost-firstboot << EOF
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: expand rootfs and Generates new ssh host keys on first boot
+# Required-Start: \$remote_fs \$syslog
+# Required-Stop: \$remote_fs \$syslog
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Generates new ssh host keys on first boot
+# Description: Generates apt-get --purge clean new ssh host keys on $
+### END INIT INFO
+echo "Expanding rootfs ..."
+raspi-config --expand-rootfs
+echo "Removing myself ..."
+insserv -r /etc/init.d/yunohost-firstboot
+rm -f /etc/init.d/yunohost-firstboot
+rm /etc/yunohost/firstboot
+echo "Rebooting ..."
+reboot
+EOF
+ chmod a+x /etc/init.d/yunohost-firstboot
+ insserv /etc/init.d/yunohost-firstboot
+ touch /etc/yunohost/firstboot
+}
-if is_raspbian ; then
- if ! step del_user_pi ; then
- die "Unable to delete user pi" 15
- fi
+###############################################################################
+# Image building specific stuff #
+###############################################################################
- if ! step change_hostname ; then
- die "Unable to change hostname" 16
- fi
-
- if ! step setup_firstboot ; then
- die "Unable to setup firstboot" 17
- fi
-fi
+function clean_image() {
+ # Delete SSH keys
+ rm -f /etc/ssh/ssh_host_* >> $YUNOHOST_LOG 2>&1
+ yes | ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa >> $YUNOHOST_LOG 2>&1
+ yes | ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa >> $YUNOHOST_LOG 2>&1
+ yes | ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa -b 521 >> $YUNOHOST_LOG 2>&1
-if [[ "$BUILD_IMAGE" == "1" ]] ; then
- if ! step clean_image ; then
- die "Unable to clean image" 18
- fi
-fi
+ # Deleting logs ...
+ find /var/log -type f -exec rm {} \; >> $YUNOHOST_LOG 2>&1
-if is_raspbian ; then
- # Reboot should be done before postinstall to be able to run iptables rules
- reboot
-fi
+ # Purging apt ...
+ apt-get --purge clean >> $YUNOHOST_LOG 2>&1
+}
-if ! step post_install ; then
- die "Post-installation failed" 13
-fi
+###############################################################################
-# Success !
-success
-exit 0
+main "$@"