Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
freedombone-installer 29.56 KiB
#!/bin/bash
#  _____               _           _
# |   __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# |   __|  _| -_| -_| . | . |     | . | . |   | -_|
# |__|  |_| |___|___|___|___|_|_|_|___|___|_|_|___|
#
#                              Freedom in the Cloud
#
# Install daemon for the web admin system
# See also freedombone-utils-webadmin
#
# License
# =======
#
# Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
#
# 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/>.

PROJECT_NAME='freedombone'

export TEXTDOMAIN=${PROJECT_NAME}-installer
export TEXTDOMAINDIR="/usr/share/locale"


INSTALL_STATE_FIRST_BOOT=0
INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED=1
INSTALL_STATE_RUNNING_COMMAND=2
INSTALL_STATE_COMMAND_FAIL=3
INSTALL_STATE_COMMAND_SUCCESS=4

install_state=$INSTALL_STATE_FIRST_BOOT

CONFIGURATION_FILE="/root/${PROJECT_NAME}.cfg"
COMPLETION_FILE="/root/${PROJECT_NAME}-completed.txt"

local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local

webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin"
setup_file="$webadmin_install_dir/setup.txt"
domain_file="$webadmin_install_dir/.temp_domain.txt"
pending_removes="$webadmin_install_dir/pending_removes.txt"
pending_installs="$webadmin_install_dir/pending_installs.txt"
install_state_file="/root/.install_state.txt"
INSTALL_DIR=/root/build
webadmin_user='admin'
webadmin_temp_password_file=/root/.temp_webadmin_password
installer_script=/root/.fbone_installer.sh

function web_admin_create_add_apps {
    appslist_add_filename="$webadmin_install_dir/apps_add.html"

    apps_add_template_filename="$webadmin_install_dir/apps_add_template.html"
    pending_installs="$webadmin_install_dir/pending_installs.txt"
    icons_dir="$webadmin_install_dir/icons"
    app_add_template_filename="$webadmin_install_dir/app_add_template.html"
    FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*"

    if [ ! -d "$icons_dir" ]; then
        mkdir -p "$icons_dir"
    fi

    if [ ! -f "$apps_add_template_filename" ]; then
        return
    fi
    cp "$apps_add_template_filename" "$appslist_add_filename"
    sed -i '/<\/body>/d' "$appslist_add_filename"
    sed -i '/<\/html>/d' "$appslist_add_filename"

    available_apps_ctr=0
    for filename in $FILES
    do
        app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')

        app_is_installed=

        # check if the app is pending installation
        app_pending_install=
        if [ -f "$pending_installs" ]; then
            if grep -q "install_${app_name}" "$pending_installs"; then
                app_is_installed=1
                app_pending_install=1
            fi
        fi

        if [ ! $app_is_installed ]; then
            app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"
            if [ -f "$app_filename" ]; then
                # get the icon for the app
                icon_filename="/usr/share/${PROJECT_NAME}/android-app/${app_name}.png"
                if [ -f "$icon_filename" ]; then
                    cp "$icon_filename" "$webadmin_install_dir/icons/${app_name}.png"
                else
                    icon_filename=
                    continue
                fi

                app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}')
                DESCRIPTION=

                if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
                    continue
                fi
                if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then
                    continue
                fi

                if grep -q "${app_name_upper}_DESCRIPTION=" "$app_filename"; then
                    DESCRIPTION="$(grep "${app_name_upper}_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')"
                fi

                if [ $available_apps_ctr -eq 0 ]; then
                    echo '    <div class="row">' >> "$appslist_add_filename"
                fi

                filename="$webadmin_install_dir/app_${app_name}.html"
                if [ -f "$filename" ]; then
                    rm "$filename"
                fi

                filename="$webadmin_install_dir/app_add_${app_name}.html"

                if [ ! $app_pending_install ]; then
                    { echo '      <div class="column">';
                      echo '        <div>';
                      echo "          <a href=\"app_add_${app_name}.html\">";
                      echo "            <img src=\"icons/${app_name}.png\" style=\"width:100%\">";
                      echo "            <center>${app_name}</center>";
                      echo '          </a>';
                      echo '        </div>';
                      echo '      </div>'; } >> "$appslist_add_filename"
                else
                    { echo '      <div class="column">';
                      echo '        <div>';
                      echo "        <img src=\"icons/${app_name}.png\" style=\"width:100%\">";
                      echo "        <center class=\"installing\">${app_name}</center>";
                      echo '        </div>';
                      echo '      </div>'; } >> "$appslist_add_filename"
                fi

                cp "$app_add_template_filename" "$filename"

                # Replace app variables
                sed -i "s|HOSTNAME|$(hostname)|g" "$filename"
                sed -i "s|APPNAME|${app_name}|g" "$filename"
                sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename"

                if grep -q 'freedns_code' "$filename"; then
                    sed -i '/freedns_code/d' "$filename"
                fi

                available_apps_ctr=$((available_apps_ctr+1))

                # four columns per row
                if [ $available_apps_ctr -eq 4 ]; then
                    echo '    </div>' >> "$appslist_add_filename"
                    available_apps_ctr=0
                fi
            fi
        fi
    done

    # Complete the rest of the four column row
    # shellcheck disable=SC2034
    for i in $(seq ${available_apps_ctr} 3)
    do
        { echo '      <div class="column">';
          echo '        <div>';
          echo '        </div>';
          echo '      </div>'; } >> "$appslist_add_filename"
    done

    echo '  </body>' >> "$appslist_add_filename"
    echo '</html>' >> "$appslist_add_filename"

    chown -R www-data:www-data "$webadmin_install_dir"
}

function web_admin_create_installed_apps {
    appslist_filename="$webadmin_install_dir/apps.html"

    appslist_template_filename="$webadmin_install_dir/apps_template.html"
    icons_dir="$webadmin_install_dir/icons"
    pending_removes="$webadmin_install_dir/pending_removes.txt"

    if [ ! -d "$icons_dir" ]; then
        mkdir -p "$icons_dir"
    fi

    if [ ! -f "$appslist_template_filename" ]; then
        return
    fi
    cp "$appslist_template_filename" "$appslist_filename"
    sed -i '/<\/body>/d' "$appslist_filename"
    sed -i '/<\/html>/d' "$appslist_filename"

    installed_apps_ctr=0

    # Complete the rest of the four column row
    # shellcheck disable=SC2034
    for i in $(seq ${installed_apps_ctr} 3)
    do
        { echo '      <div class="column">';
          echo '        <div>';
          echo '        </div>';
          echo '      </div>'; } >> "$appslist_filename"
    done

    echo '  </body>' >> "$appslist_filename"
    echo '</html>' >> "$appslist_filename"

    chown -R www-data:www-data "$webadmin_install_dir"
}

function web_admin_create_users {
    if [ ! -d "/home/$webadmin_user" ]; then
        return
    fi

    users_file="$webadmin_install_dir/users.html"

    cp "$webadmin_install_dir"/users_template.html "$users_file"
    sed -i '/users list/,/end of users/d' "$users_file"
    sed -i '/<\/body>/d' "$users_file"
    sed -i '/<\/html>/d' "$users_file"

    echo "    <div class=\"row\">" >> "$users_file"
    echo "      <div class=\"column\">" >> "$users_file"

    rm "$webadmin_install_dir/userprofile_"*

    USERNAME="$webadmin_user"
    userfile="$webadmin_install_dir/userprofile_${USERNAME}.html"
    useremail=${USERNAME}@${HOSTNAME}
    GPG_ID=$(su -c "gpg --list-keys '$useremail'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//')
    if [ -f "/home/$USERNAME/.gnupg/gpg.conf" ]; then
        if grep -q "default-key" "/home/$USERNAME/.gnupg/gpg.conf"; then
            default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf")
            if [[ "$default_gpg_key" != *'#'* ]]; then
                default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf" | awk -F ' ' '{print $2}')
                if [ ${#default_gpg_key} -gt 3 ]; then
                    GPG_ID=$(su -c "gpg --list-keys '$default_gpg_key'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//')
                fi
            fi
        fi
    fi
    pubkey_qrcode="$webadmin_install_dir/images/userprofile_${USERNAME}.png"
    su -c "gpg --armor --export \"$GPG_ID\"" - "$USERNAME" | qrencode -t PNG -o "$pubkey_qrcode"

    { echo '        <div class="chip">';
      echo "          <a href=\"userprofile_${USERNAME}.html\">";
      echo '            <img src="images/admin_users.png" alt="Person" width="96" height="96">';
      echo "            $USERNAME";
      echo '          </a>';
      echo '        </div>'; } >> "$users_file"

    cp "$webadmin_install_dir"/userprofile.html "$userfile"
    sed -i "s|USERNAME|${USERNAME}|g" "$userfile"
    if [[ "$USERNAME" == "$webadmin_user" ]]; then
        sed -i "s|USERTYPE|Admin|g" "$userfile"
        sed -i '/remove user button/,/end of remove/d' "$userfile"
    else
        sed -i "s|USERTYPE|User|g" "$userfile"
    fi
    sed -i "s|USEREMAIL|${useremail}|g" "$userfile"
    sed -i "s|USERGPG|${GPG_ID}|g" "$userfile"

    chown www-data:www-data "$userfile"
    chown www-data:www-data "$pubkey_qrcode"

    { echo '        <div class="chip">';
      echo "          <a href=\"newuser.html\">";
      echo '            <img src="images/admin_users.png" alt="Person" width="96" height="96">';
      echo '            +';
      echo '          </a>';
      echo '        </div>';
      echo '      </div>';
      echo '    </div>';
      echo '  </body>';
      echo '</html>'; } >> "$users_file"

    chown www-data:www-data "$users_file"
}

function wait_for_enough_entropy {
    # Wait indefinitely until enough entropy is available to
    # generate the webadmin login password
    while true
    do
        ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail)
        # shellcheck disable=SC2086
        if [ $ENTROPY -gt 500 ]; then
            break
        fi
        sleep 2
    done
}

function web_admin_create_user {
    username="$1"
    password="$2"

    if [ ! "$username" ]; then
        return
    fi

    if [ ! -d "/home/$username" ]; then
        chmod 600 /etc/shadow
        chmod 600 /etc/gshadow
        useradd -m -p "$password" -s /bin/bash "$username"
        groupadd "$username"
        chmod 0000 /etc/shadow
        chmod 0000 /etc/gshadow
    else
        echo "${username}:${password}"|chpasswd
    fi
}

function web_admin_setup_login {
    if [ $install_state -ne $INSTALL_STATE_FIRST_BOOT ]; then
        return
    fi

    # if an nginx password file has not been created for web admin
    if [ -f /etc/nginx/.webadminpasswd ]; then
        return
    fi

    # this file indicates that the setup screen is active
    # and gets removed by freedombone-installer
    if [ ! -f "$webadmin_install_dir/.setupscreenactive" ]; then
        touch "$webadmin_install_dir/.setupscreenactive"
    fi

    if [ ! -f $webadmin_temp_password_file ]; then
        wait_for_enough_entropy
        webadmin_password="$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 10 ; echo -n '')"
        echo -n "$webadmin_password" > $webadmin_temp_password_file
    else
        webadmin_password=$(cat $webadmin_temp_password_file)
    fi

    web_admin_create_user "$webadmin_user" "$webadmin_password"

    # create a password for users
    if [ ! -f /etc/nginx/.webadminpasswd ]; then
        touch /etc/nginx/.webadminpasswd
    fi

    # create a password file used by nginx
    echo -n "$webadmin_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$webadmin_user"
    if ! grep -q "${webadmin_user}:" /etc/nginx/.webadminpasswd; then
        echo $"/etc/nginx/.webadminpasswd password not created for $webadmin_user"
        if [ -f /etc/nginx/.webadminpasswd ]; then
            rm /etc/nginx/.webadminpasswd
        fi
        return
    fi

    # create a setup page with the initial password inserted
    # and copy it to the index
    cp "$webadmin_install_dir"/setup.html "$webadmin_install_dir"/setup.prev
    cp "$webadmin_install_dir"/setup_confirm_template.html "$webadmin_install_dir"/setup_confirm.html
    sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup.prev"
    sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup_confirm.html"
    cp "$webadmin_install_dir"/setup.prev "$webadmin_install_dir"/index.html

    # if initial setup has not yet happened then create
    # a password file
    if ! grep -q 'install_final' "$COMPLETION_FILE"; then
        echo -n "$webadmin_password" > /root/login.txt
    fi

    echo -n "$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED" > "$install_state_file"
    install_state=$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED
}

function enable_webadmin_login {
    # switch on nginx authentication for freedombone.local
    if grep -q "#auth_basic" "/etc/nginx/sites-available/${local_hostname}"; then
        sed -i 's|#auth_basic|auth_basic|g' "/etc/nginx/sites-available/${local_hostname}"
    fi
}

function remove_initial_setup_page {
    if [ -f "$webadmin_install_dir/index.prev" ]; then
        # Replace the installing screen with the main index page when done
        # It should reload by itself
        if [ -f "$webadmin_install_dir/setup_installing.html" ]; then
            cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/setup_installing.html"
        fi

        # Replace the setup confirm screen with the main index
        if [ -f "$webadmin_install_dir/setup_confirm.html" ]; then
            cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/setup_confirm.html"
        fi

        # Replace the setup domain screen with the main index
        if [ -f "$webadmin_install_dir/setup_domain.html" ]; then
            cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/setup_domain.html"
        fi

        # Show the web admin index page (not the initial setup page)
        cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/index.html"
        rm "$webadmin_install_dir/index.prev"
    fi

    # Remove the initial setup page
    if [ -f "$webadmin_install_dir/setup.prev" ]; then
        rm "$webadmin_install_dir/setup.prev"
    fi
}

function remove_temporary_setup_files {
    # remove the file which indicates that the setup screen is active
    if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then
        rm "$webadmin_install_dir/.setupscreenactive"
    fi

    # remove the setup file created by setup.php
    if [ -f "$setup_file" ]; then
        rm "$setup_file"
    fi

    # remove the file containing the domain name
    if [ -f "$domain_file" ]; then
        rm "$domain_file"
    fi
}

function restore_webadmin_files {
    # restore files which were removed for the initial setup
    if [ -d "$INSTALL_DIR/tempwebadmin" ]; then
        mv "$INSTALL_DIR/tempwebadmin"/* "$webadmin_install_dir"
        rm -rf "$INSTALL_DIR/tempwebadmin"
    fi
}

function set_webadmin_permissions {
    # set permissions for web admin site at freedombone.local
    chown www-data:www-data "$webadmin_install_dir/*.html"
}

function run_setup_command {
    if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then
        return
    fi

    { echo '#!/bin/bash';
      echo '';
      echo '# ensure that any other running installs are killed';
      echo "install_process=\$(ps a | grep 'fbone_installer.sh' | grep -v 'grep')";
      echo "if [ \"\$install_process\" ]; then";
      echo "    if [[ \"\$install_process\" != *'grep'* ]]; then";
      echo "        install_pid=\$(echo \"\$install_process\" | awk -F ' ' '{print \$1}')";
      echo "        if [ \"\$install_pid\" ]; then";
      echo "            pkill -9 \"\$install_pid\"";
      echo '        fi';
      echo '    fi';
      echo 'fi';
      echo '';
      echo "echo \"Beginning install $(date)\" > $webadmin_install_dir/log.txt";
      echo "chown www-data:www-data $webadmin_install_dir/log.txt";
      echo '';
      echo "/usr/local/bin/freedombone -c \"$CONFIGURATION_FILE\" > $webadmin_install_dir/log.txt;";

      echo "if ! grep -q 'install_final' \"$COMPLETION_FILE\"; then";
      echo "    chown www-data:www-data $webadmin_install_dir/log.txt";
      echo "    echo '$INSTALL_STATE_COMMAND_FAIL' > $install_state_file";
      echo '    exit 364873';
      echo 'fi';
      echo '';
      echo "chown www-data:www-data $webadmin_install_dir/log.txt";
      echo '';
      echo "exit 0"; } > $installer_script
    chmod +x $installer_script

    echo -n "$INSTALL_STATE_RUNNING_COMMAND" > "$install_state_file"
    install_state=$INSTALL_STATE_RUNNING_COMMAND

    # run in a separate process
    ./$installer_script &
}

function check_install_command_state {
    if [ $install_state -ne $INSTALL_STATE_RUNNING_COMMAND ]; then
        return
    fi
    reset_install_state=
    if [ ! -f "$install_state_file" ]; then
        reset_install_state=1
    else
        curr_state=$(cat "$install_state_file")

        # shellcheck disable=SC2086
        if [ $curr_state -eq $INSTALL_STATE_COMMAND_FAIL ]; then
            reset_install_state=1
        fi

        install_has_finished=

        # shellcheck disable=SC2086
        if [ $curr_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then
            install_has_finished=1
        else
            # Also check the install log for a message
            # indicating completion has happened
            if [ -f "$webadmin_install_dir/log.txt" ]; then
                end_of_log=$(tail -n 10 "$webadmin_install_dir/log.txt" | grep ${PROJECT_NAME})
                end_of_log_message=$'installation is complete'
                if [[ "$end_of_log" == *"$end_of_log_message"* ]]; then
                    install_has_finished=1
                fi
            fi
        fi

        if [ $install_has_finished ]; then
            echo -n "$INSTALL_STATE_COMMAND_SUCCESS" > "$install_state_file"
            install_state=$INSTALL_STATE_COMMAND_SUCCESS
            restore_webadmin_files
        fi
    fi

    if [ $reset_install_state ]; then
        chown www-data:www-data "$webadmin_install_dir/log.txt"
        # remove the setup file containing login details
        if [ -f "$setup_file" ]; then
            rm "$setup_file"
        fi
        # remove the webadmin password file
        if [ -f /etc/nginx/.webadminpasswd ]; then
            rm /etc/nginx/.webadminpasswd
        fi
        echo -n "$INSTALL_STATE_FIRST_BOOT" > "$install_state_file"
        install_state=$INSTALL_STATE_FIRST_BOOT
    fi
}

function web_admin_get_language_subdir {
    if grep -q 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE"; then
        DEFAULT_LANGUAGE=$(grep 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}')
    fi
    if [ ! "$DEFAULT_LANGUAGE" ]; then
        echo 'EN'
        return
    fi
    lang_lower="${DEFAULT_LANGUAGE:0:2}"
    echo "$lang_lower" | awk '{print toupper($0)}'
}

function before_setup_runs {
    if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then
        return
    fi

    if [ ! -f /etc/nginx/.webadminpasswd ]; then
        return
    fi

    if grep -q 'install_final' "$COMPLETION_FILE"; then
        return
    fi

    curr_language=$(web_admin_get_language_subdir)

    if [ ! -f "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}/setup_installing.html" ]; then
        return
    fi

    cp "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}/setup_installing.html" "$webadmin_install_dir/index.html"

    # get the username and domain from the .temp_setup.txt file
    # created by setup.php
    MY_USERNAME=$(cat "$setup_file")
    if [ ! "$MY_USERNAME" ]; then
        MY_USERNAME="$webadmin_user"
    else
        if [[ "$MY_USERNAME" != "$webadmin_user" ]]; then
            temp_webadmin_password=$(cat $webadmin_temp_password_file)
            web_admin_create_user "$webadmin_user" "$temp_webadmin_password"
            webadmin_user="$MY_USERNAME"
        fi
    fi
    DEFAULT_DOMAIN_NAME=${local_hostname}

    if [ -f "$domain_file" ]; then
        DEFAULT_DOMAIN_NAME=$(cat "$domain_file")
    fi

    # change the username in the config file
    if grep -q 'MY_USERNAME=' "$CONFIGURATION_FILE"; then
        if ! grep -Fxq "MY_USERNAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then
            sed -i "s|MY_USERNAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE"
        fi
    else
        echo "MY_USERNAME=$MY_USERNAME" >> "$CONFIGURATION_FILE"
    fi

    # change the full name in the config file
    if grep -q 'MY_NAME=' "$CONFIGURATION_FILE"; then
        if ! grep -Fxq "MY_NAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then
            sed -i "s|MY_NAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE"
        fi
    else
        echo "MY_NAME=$MY_USERNAME" >> "$CONFIGURATION_FILE"
    fi

    # change the default domain in the config file
    if grep -q 'DEFAULT_DOMAIN_NAME=' "$CONFIGURATION_FILE"; then
        if ! grep -Fxq "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" "$CONFIGURATION_FILE"; then
            sed -i "s|DEFAULT_DOMAIN_NAME=.*|DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME|g" "$CONFIGURATION_FILE"
        fi
    else
        echo "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" >> "$CONFIGURATION_FILE"
    fi

    # ensure that minimal install is set
    if grep -q 'MINIMAL_INSTALL=' "$CONFIGURATION_FILE"; then
        if ! grep -Fxq "MINIMAL_INSTALL=yes" "$CONFIGURATION_FILE"; then
            sed -i 's|MINIMAL_INSTALL=.*|MINIMAL_INSTALL=yes|g' "$CONFIGURATION_FILE"
        fi
    else
        echo 'MINIMAL_INSTALL=yes' >> "$CONFIGURATION_FILE"
    fi

    # ensure that no DDNS provider is specified
    if grep -q 'DDNS_PROVIDER=' "$CONFIGURATION_FILE"; then
        if ! grep -Fxq "DDNS_PROVIDER=none" "$CONFIGURATION_FILE"; then
            sed -i 's|DDNS_PROVIDER=.*|DDNS_PROVIDER=none|g' "$CONFIGURATION_FILE"
        fi
    else
        echo 'DDNS_PROVIDER=none' >> "$CONFIGURATION_FILE"
    fi

    run_setup_command
}

function after_setup_has_finished {
    if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then
        return
    fi
    if [ -f /root/.initial_setup ]; then
        rm /root/.initial_setup
    fi
    enable_webadmin_login
    remove_initial_setup_page
    set_webadmin_permissions
    remove_temporary_setup_files

    if [ -f $webadmin_temp_password_file ]; then
        rm $webadmin_temp_password_file
    fi

    web_admin_create_users
    web_admin_create_installed_apps
    web_admin_create_add_apps
    systemctl restart nginx
    if [ -f $installer_script ]; then
        rm $installer_script
    fi

    systemctl reboot -i
}

function install_apps_from_webadmin {
    if [ -f "$pending_installs" ]; then
        linestr=$(head -n 1 "$pending_installs")
        if [[ "$linestr" == "install_"* ]]; then
            app_name=$(echo "$linestr" | awk -F '_' '{print $2}' | awk -F ',' '{print $1}')
            if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then
                app_domain=$(echo "$linestr" | awk -F ',' '{print $2}')
                app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}')
                freedns_code=$(echo -n "$linestr" | awk -F ',' '{print $3}')

                # indicate that we are installing
                if [[ "$linestr" != *'_running'* ]]; then
                    sed -i "s|${app_name}|${app_name}_running|g" "$pending_installs"
                fi

                if grep -q 'ONION_ONLY=no' $CONFIGURATION_FILE; then
                    # Add domain name to the config
                    if ! grep -q "${app_name_upper}_DOMAIN_NAME=" $CONFIGURATION_FILE; then
                        echo "${app_name_upper}_DOMAIN_NAME=${app_domain}" >> $CONFIGURATION_FILE
                    else
                        sed -i "s|${app_name_upper}_DOMAIN_NAME=.*|${app_name_upper}_DOMAIN_NAME=${app_domain}|g" $CONFIGURATION_FILE
                    fi

                    # Add freedns code to the config
                    if [ "$freedns_code" ]; then
                        # shellcheck disable=SC2086
                        ${app_name_upper}_CODE="${freedns_code}"

                        if ! grep -q "${app_name_upper}_CODE=" $CONFIGURATION_FILE; then
                            echo "${app_name_upper}_CODE=${freedns_code}" >> $CONFIGURATION_FILE
                        else
                            sed -i "s|${app_name_upper}_CODE=.*|${app_name_upper}_CODE=${freedns_code}|g" $CONFIGURATION_FILE
                        fi
                    fi
                fi

                /usr/local/bin/${PROJECT_NAME}-addremove add "${app_name}"
            fi
            # remove the line
            sed -i "/$linestr/d" "$pending_installs"
        else
            # if any unusual line is found then remove the file
            rm "$pending_installs"
        fi
    fi
}

function remove_apps_from_webadmin {
    if [ -f "$pending_removes" ]; then
        linestr=$(head -n 1 "$pending_removes")
        if [[ "$linestr" == "remove_"* ]]; then
            app_name=$(echo "$linestr" | awk -F '_' '{print $2}')
            if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then
                # indicate that we are removing
                if [[ "$linestr" != *'_running'* ]]; then
                    sed -i "s|${app_name}|${app_name}_running|g" "$pending_removes"
                fi
                /usr/local/bin/${PROJECT_NAME}-addremove remove "${app_name}"
            fi
            # remove the line
            sed -i "/$linestr/d" "$pending_removes"
        else
            # if any unusual line is found then remove the file
            rm "$pending_removes"
        fi
    fi
}

function update_progress_bar {
    # shellcheck disable=SC2086
    if [ $install_state -ne $INSTALL_STATE_RUNNING_COMMAND ]; then
        return
    fi
    if [ ! -f /root/.install_counter ]; then
        echo -n '1' > /root/.install_counter
    fi
    max_counter=203
    installing_page="$webadmin_install_dir/setup_installing.html"
    progress_counter=$(cat /root/.install_counter)
    progress_percent=$((progress_counter * max_counter / 100))
    if [ $progress_percent -gt 100 ]; then
        progress_percent=100
    fi
    sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$progress_percent%\">$progress_percent%</div>|g" "$installing_page"
    if ! grep -q 'w3-container w3-blue' "$webadmin_install_dir/index.html"; then
        cp "$webadmin_install_dir/setup_installing.html" "$webadmin_install_dir/index.html"
    fi
    sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$progress_percent%\">$progress_percent%</div>|g" "$webadmin_install_dir/index.html"
}

# If the freedombone command is already running then kill its process
#shellcheck disable=SC2009
install_process=$(ps a | grep '/usr/local/bin/freedombone -c' | grep -v 'grep')
if [ "$install_process" ]; then
    if [[ "$install_process" != *'grep'* ]]; then
        install_pid=$(echo "$install_process" | awk -F ' ' '{print $1}')
        if [ "$install_pid" ]; then
            pkill -9 "$install_pid"
        fi
    fi
fi

# get the current install state
if [ -f "$install_state_file" ]; then
    install_state=$(cat "$install_state_file")
    # shellcheck disable=SC2086
    if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then
        if grep -q 'install_final' "$COMPLETION_FILE"; then
            install_state=$INSTALL_STATE_COMMAND_SUCCESS
        else
            chown www-data:www-data "$webadmin_install_dir/log.txt"
            # remove the setup file containing login details
            if [ -f "$setup_file" ]; then
                rm "$setup_file"
            fi
            if [ -f /etc/nginx/.webadminpasswd ]; then
                rm /etc/nginx/.webadminpasswd
            fi
            install_state=$INSTALL_STATE_FIRST_BOOT
        fi
        echo -n "$install_state" > "$install_state_file"
    fi
else
    if grep -q 'install_final' "$COMPLETION_FILE"; then
        install_state=$INSTALL_STATE_COMMAND_SUCCESS
    else
        install_state=$INSTALL_STATE_FIRST_BOOT
    fi
    echo -n "$install_state" > "$install_state_file"
fi

while true
do
    if [ -f /tmp/.upgrading ]; then
        sleep 2
    else
        web_admin_setup_login
        if [ -d "$webadmin_install_dir" ]; then
            if [ -f "$setup_file" ]; then
                update_progress_bar
                before_setup_runs
                check_install_command_state
                after_setup_has_finished
                sleep 1
            else
                if [ $install_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then
                    install_apps_from_webadmin
                    sleep 1
                    remove_apps_from_webadmin
                fi
            fi
        fi
        sleep 1
    fi
done

exit 0