From c8e890d0d9443c568309022cfca2b9c3cd8f0897 Mon Sep 17 00:00:00 2001 From: Teal Dulcet Date: Wed, 24 Oct 2018 20:31:20 -0700 Subject: [PATCH] Added more checks to scripts and outputs more system information. --- CONTRIBUTING.md | 8 ++++-- setup/bootstrap.sh | 24 ++++++++++++++-- setup/firstuser.sh | 5 ++-- setup/mail-dovecot.sh | 4 +-- setup/preflight.sh | 67 +++++++++++++++++++++++++++---------------- setup/questions.sh | 64 ++++++++++++++++++++++++++++++++--------- setup/start.sh | 5 ++++ 7 files changed, 129 insertions(+), 48 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 00e15ec7..2af4030f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,11 +20,13 @@ _If you're seeing an error message about your *IP address being listed in the Sp ### Modifying your `hosts` file -After a while, Mail-in-a-Box will be available at `192.168.50.4` (unless you changed that in your `Vagrantfile`). To be able to use the web-based bits, we recommend to add a hostname to your `hosts` file: +After a while, Mail-in-a-Box will be available at `192.168.50.4` (unless you changed that in your `Vagrantfile`). To be able to use the web-based bits, we recommend adding a hostname to your `hosts` file: - $ echo "192.168.50.4 mailinabox.lan" | sudo tee -a /etc/hosts + $ echo -e "192.168.50.4\tmailinabox.lan" | sudo tee -a /etc/hosts + or + $ sudo sed -i "s/^127.0.1.1.*/192.168.50.4\tmailinabox.lan/" /etc/hosts -You should now be able to navigate to https://mailinabox.lan/admin using your browser. There should be an initial admin user with the name `me@mailinabox.lan` and the password `12345678`. +You should now be able to navigate to https://mailinabox.lan/admin using your browser. There should be an initial admin user with the name `me@mailinabox.lan` and the randomly generated password from the output. ### Making changes diff --git a/setup/bootstrap.sh b/setup/bootstrap.sh index 74bf5e16..3901a8b0 100644 --- a/setup/bootstrap.sh +++ b/setup/bootstrap.sh @@ -2,7 +2,8 @@ ######################################################### # This script is intended to be run like this: # -# curl https://mailinabox.email/setup.sh | sudo bash +# wget https://mailinabox.email/setup.sh -qO - | sudo bash -s +# curl -s https://mailinabox.email/setup.sh | sudo bash -s # ######################################################### @@ -39,10 +40,27 @@ if [ -z "$TAG" ]; then fi fi +if [[ "$#" -ne 0 ]]; then + echo "Usage: \"wget https://mailinabox.email/setup.sh -qO - | sudo bash -s\" or \"curl -s https://mailinabox.email/setup.sh | sudo bash -s\"" >&2 + exit 1 +fi + # Are we running as root? if [[ $EUID -ne 0 ]]; then - echo "This script must be run as root. Did you leave out sudo?" - exit + echo "This script must be run as root. Did you leave out sudo?" >&2 + exit 1 +fi + +# Check if on Linux +if ! echo "$OSTYPE" | grep -iq "linux"; then + echo "Error: This script must be run on Linux." >&2 + exit 1 +fi + +# Check connectivity +if ! ping -q -c 3 mailinabox.email > /dev/null 2>&1; then + echo "Error: Could not reach mailinabox.email, please check your internet connection and run this script again." >&2 + exit 1 fi # Clone the Mail-in-a-Box repository if it doesn't exist. diff --git a/setup/firstuser.sh b/setup/firstuser.sh index f6947695..403f283a 100644 --- a/setup/firstuser.sh +++ b/setup/firstuser.sh @@ -35,9 +35,10 @@ if [ -z "`tools/mail.py user`" ]; then else # Use me@PRIMARY_HOSTNAME EMAIL_ADDR=me@$PRIMARY_HOSTNAME - EMAIL_PW=12345678 + EMAIL_PW=$(openssl rand -base64 8) echo - echo "Creating a new administrative mail account for $EMAIL_ADDR with password $EMAIL_PW." + echo -e "Creating a new administrative mail account for: $EMAIL_ADDR\n\t\t\t\t with password: $EMAIL_PW" + echo "Warning: This is a security risk. Please change the password after your first login." echo fi else diff --git a/setup/mail-dovecot.sh b/setup/mail-dovecot.sh index c3d2ee57..0f3dcd48 100755 --- a/setup/mail-dovecot.sh +++ b/setup/mail-dovecot.sh @@ -45,8 +45,8 @@ apt_install \ # - https://www.dovecot.org/list/dovecot/2012-August/137569.html # - https://www.dovecot.org/list/dovecot/2011-December/132455.html tools/editconf.py /etc/dovecot/conf.d/10-master.conf \ - default_process_limit=$(echo "`nproc` * 250" | bc) \ - default_vsz_limit=$(echo "`free -tm | tail -1 | awk '{print $2}'` / 3" | bc)M \ + default_process_limit="$((CPU_CORES * 250))" \ + default_vsz_limit="$(($(free -tm | tail -1 | awk '{print $2}') / 3))M" \ log_path=/var/log/mail.log # The inotify `max_user_instances` default is 128, which constrains diff --git a/setup/preflight.sh b/setup/preflight.sh index 2547c410..8339da4f 100644 --- a/setup/preflight.sh +++ b/setup/preflight.sh @@ -7,14 +7,26 @@ if [[ $EUID -ne 0 ]]; then exit fi -# Check that we are running on Ubuntu 18.04 LTS (or 18.04.xx). -if [ "`lsb_release -d | sed 's/.*:\s*//' | sed 's/18\.04\.[0-9]/18.04/' `" != "Ubuntu 18.04 LTS" ]; then - echo "Mail-in-a-Box only supports being installed on Ubuntu 18.04, sorry. You are running:" - echo - lsb_release -d | sed 's/.*:\s*//' - echo - echo "We can't write scripts that run on every possible setup, sorry." - exit +# Check if on Linux +if ! echo "$OSTYPE" | grep -iq "linux"; then + echo "Error: This script must be run on Linux." >&2 + exit 1 +fi + +. /etc/os-release + +# Check that we are running on Ubuntu 14.04 LTS (or 14.04.xx). +if ! echo "$ID" | grep -iq "ubuntu" || ! echo "$VERSION_ID" | grep -iq "18.04"; then + echo "Mail-in-a-Box only supports being installed on Ubuntu 18.04, sorry. You are running:" >&2 + echo >&2 + echo "${PRETTY_NAME:-$ID-$VERSION_ID}" >&2 + echo >&2 + echo "We can't write scripts that run on every possible setup, sorry." >&2 +fi + +# Check for the Windows Subsystem for Linux (WSL) +if uname -r | grep -iq "microsoft"; then + echo "Warning: The Windows Subsystem for Linux (WSL) is not yet fully supported by this script." fi # Check that we have enough memory. @@ -25,21 +37,28 @@ fi # We will display a warning if the memory is below 768 MB which is 750000 kibibytes # # Skip the check if we appear to be running inside of Vagrant, because that's really just for testing. -TOTAL_PHYSICAL_MEM=$(head -n 1 /proc/meminfo | awk '{print $2}') -if [ $TOTAL_PHYSICAL_MEM -lt 490000 ]; then -if [ ! -d /vagrant ]; then - TOTAL_PHYSICAL_MEM=$(expr \( \( $TOTAL_PHYSICAL_MEM \* 1024 \) / 1000 \) / 1000) - echo "Your Mail-in-a-Box needs more memory (RAM) to function properly." - echo "Please provision a machine with at least 512 MB, 1 GB recommended." - echo "This machine has $TOTAL_PHYSICAL_MEM MB memory." - exit +TOTAL_PHYSICAL_MEM=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo) +TOTAL_SWAP=$(awk '/^SwapTotal:/ {print $2}' /proc/meminfo) +if [ "$TOTAL_PHYSICAL_MEM" -lt 490000 ]; then + if [ ! -d /vagrant ]; then + echo "Your Mail-in-a-Box needs more memory (RAM) to function properly." >&2 + echo "Please provision a machine with at least 512 MB, 1 GB (1024 MB) recommended." >&2 + echo "This machine has $(printf "%'d" $((((TOTAL_PHYSICAL_MEM * 1024) / 1000) / 1000))) MB ($(printf "%'d" $((TOTAL_PHYSICAL_MEM / 1024))) MiB) memory." + exit 1 + fi fi fi -if [ $TOTAL_PHYSICAL_MEM -lt 750000 ]; then +if [ "$TOTAL_PHYSICAL_MEM" -lt 750000 ]; then echo "WARNING: Your Mail-in-a-Box has less than 768 MB of memory." echo " It might run unreliably when under heavy load." fi +# Check connectivity +if ! ping -q -c 3 mailinabox.email > /dev/null 2>&1; then + echo "Error: Could not reach mailinabox.email, please check your internet connection and run this script again." >&2 + exit 1 +fi + # Check that tempfs is mounted with exec MOUNTED_TMP_AS_NO_EXEC=$(grep "/tmp.*noexec" /proc/mounts || /bin/true) if [ -n "$MOUNTED_TMP_AS_NO_EXEC" ]; then @@ -55,12 +74,10 @@ fi # Check that we are running on x86_64 or i686 architecture, which are the only # ones we support / test. -ARCHITECTURE=$(uname -m) -if [ "$ARCHITECTURE" != "x86_64" ] && [ "$ARCHITECTURE" != "i686" ]; then - echo - echo "WARNING:" - echo "Mail-in-a-Box has only been tested on x86_64 and i686 platform" - echo "architectures. Your architecture, $ARCHITECTURE, may not work." - echo "You are on your own." - echo +ARCHITECTURE=$(getconf LONG_BIT) +if [ "$HOSTTYPE" != "x86_64" ] && [ "$HOSTTYPE" != "i686" ]; then + echo "WARNING:" >&2 + echo "Mail-in-a-Box has only been tested on x86_64 and i686 platform architectures." >&2 + echo "Your architecture, $HOSTTYPE ($ARCHITECTURE-bit), may not work." >&2 + echo "You are on your own." >&2 fi diff --git a/setup/questions.sh b/setup/questions.sh index bf382f49..cc1e0b8b 100644 --- a/setup/questions.sh +++ b/setup/questions.sh @@ -77,9 +77,16 @@ address, so we're suggesting $DEFAULT_PRIMARY_HOSTNAME. $DEFAULT_PRIMARY_HOSTNAME \ PRIMARY_HOSTNAME + RE='^.+\.localdomain$' + RE1='^.{4,253}$' + RE2='^([[:alnum:]][[:alnum:]\-]{0,61}[[:alnum:]]\.)+[a-zA-Z]{2,63}$' if [ -z "$PRIMARY_HOSTNAME" ]; then # user hit ESC/cancel - exit + exit 1 + elif [[ $PRIMARY_HOSTNAME =~ $RE ]]; then + echo "Warning: Hostname cannot be *.localdomain." + elif ! [[ $PRIMARY_HOSTNAME =~ $RE1 && $PRIMARY_HOSTNAME =~ $RE2 ]]; then + echo "Warning: Hostname is not a valid fully qualified domain name (FQDN)." fi fi @@ -194,19 +201,50 @@ if [ -z "${STORAGE_ROOT:-}" ]; then fi # Show the configuration, since the user may have not entered it manually. -echo -echo "Primary Hostname: $PRIMARY_HOSTNAME" -echo "Public IP Address: $PUBLIC_IP" -if [ ! -z "$PUBLIC_IPV6" ]; then - echo "Public IPv6 Address: $PUBLIC_IPV6" +echo -e "\nLinux Distribution:\t\t${PRETTY_NAME:-$ID-$VERSION_ID}" +CPU=( $(sed -n 's/^model name[[:space:]]*: *//p' /proc/cpuinfo | uniq) ) +if [ -n "$CPU" ]; then + echo -e "Processor (CPU):\t\t${CPU[*]}" fi -if [ "$PRIVATE_IP" != "$PUBLIC_IP" ]; then - echo "Private IP Address: $PRIVATE_IP" +CPU_CORES=$(nproc --all) +echo -e "CPU Cores:\t\t\t$CPU_CORES" +echo -e "Architecture:\t\t\t$HOSTTYPE ($ARCHITECTURE-bit)" +echo -e "Total memory (RAM):\t\t$(printf "%'d" $((TOTAL_PHYSICAL_MEM / 1024))) MiB ($(printf "%'d" $((((TOTAL_PHYSICAL_MEM * 1024) / 1000) / 1000))) MB)" +echo -e "Total swap space:\t\t$(printf "%'d" $((TOTAL_SWAP / 1024))) MiB ($(printf "%'d" $((((TOTAL_SWAP * 1024) / 1000) / 1000))) MB)" +if command -v lspci >/dev/null; then + GPU=( $(lspci 2>/dev/null | grep -i 'vga\|3d\|2d' | sed -n 's/^.*: //p') ) fi -if [ "$PRIVATE_IPV6" != "$PUBLIC_IPV6" ]; then - echo "Private IPv6 Address: $PRIVATE_IPV6" +if [ -n "$GPU" ]; then + echo -e "Graphics Processor (GPU):\t${GPU[*]}" fi -if [ -f /usr/bin/git ] && [ -d .git ]; then - echo "Mail-in-a-Box Version: " $(git describe) +echo -e "Computer name:\t\t\t$HOSTNAME" +echo -e "Primary Hostname:\t\t$PRIMARY_HOSTNAME" +if [ -n "$PUBLIC_IPV6" ]; then + echo -e "Public IPv4 Address:\t\t$PUBLIC_IP" + echo -e "Public IPv6 Address:\t\t$PUBLIC_IPV6" +else + echo -e "Public IP Address:\t\t$PUBLIC_IP" +fi +if [ -n "$PRIVATE_IPV6" ]; then + if [ "$PRIVATE_IP" != "$PUBLIC_IP" ]; then + echo -e "Private IPv4 Address:\t\t$PRIVATE_IP" + fi + if [ "$PRIVATE_IPV6" != "$PUBLIC_IPV6" ]; then + echo -e "Private IPv6 Address:\t\t$PRIVATE_IPV6" + fi +else + if [ "$PRIVATE_IP" != "$PUBLIC_IP" ]; then + echo -e "Private IP Address:\t\t$PRIVATE_IP" + fi +fi +TIME_ZONE=$(timedatectl 2>/dev/null | grep -i 'time zone\|timezone' | sed -n 's/^.*: //p') +echo -e "Time zone:\t\t\t$TIME_ZONE\n" +if command -v systemd-detect-virt >/dev/null && CONTAINER=$(systemd-detect-virt -c); then + echo -e "Virtualization container:\t$CONTAINER\n" +fi +if command -v systemd-detect-virt >/dev/null && VM=$(systemd-detect-virt -v); then + echo -e "Virtual Machine (VM) hypervisor:$VM\n" +fi +if command -v git >/dev/null && [ -d .git ]; then + echo -e "Mail-in-a-Box Version:\t\t$(git describe)\n" fi -echo diff --git a/setup/start.sh b/setup/start.sh index 0b145022..c657b003 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -2,6 +2,11 @@ # This is the entry point for configuring the system. ##################################################### +if [[ "$#" -ne 0 ]]; then + echo "Usage: sudo $0" >&2 + exit 1 +fi + source setup/functions.sh # load our functions # Check system setup: Are we running as root on Ubuntu 18.04 on a