diff --git a/src/freedombone-installer b/src/freedombone-installer
index 12a3670443c90c6cb9d640c0e18201cfa942eae7..e3d3d3c43c1738daa2b498edaa7edcb1ca032465 100755
--- a/src/freedombone-installer
+++ b/src/freedombone-installer
@@ -33,80 +33,166 @@ export TEXTDOMAIN=${PROJECT_NAME}-installer
 export TEXTDOMAINDIR="/usr/share/locale"
 
 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
 
-pending_removes="/var/www/${local_hostname}/htdocs/admin/pending_removes.txt"
-pending_installs="/var/www/${local_hostname}/htdocs/admin/pending_installs.txt"
+webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin"
+setup_file="$webadmin_install_dir/setup.txt"
+pending_removes="$webadmin_install_dir/pending_removes.txt"
+pending_installs="$webadmin_install_dir/pending_installs.txt"
 
 while true
 do
     if [ -f /tmp/.upgrading ]; then
         sleep 2
     else
-        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 [ -f "$setup_file" ]; then
+            if ! grep -q 'install_final' "$COMPLETION_FILE"; then
+                # initial setup has not yet completed
 
-                    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
+                cp "/usr/share/${PROJECT_NAME}/webadmin/setup_installing.html" "$webadmin_install_dir/index.html"
+
+                # get the username and domain from the setup.txt file
+                # created by setup.php
+                MY_USERNAME=$(head -n 1 "$setup_file" | awk -F ',' '{print $1}')
+                DEFAULT_DOMAIN_NAME=$(head -n 1 "$setup_file" | awk -F ',' '{print $2}')
+
+                # change the username in the config file
+                if grep -q 'MY_USERNAME=' "$CONFIGURATION_FILE"; then
+                    sed -i "s|MY_USERNAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE"
+                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
+                    sed -i "s|MY_NAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE"
+                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
+                    sed -i "s|DEFAULT_DOMAIN_NAME=.*|DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME|g" "$CONFIGURATION_FILE"
+                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
+                    sed -i 's|MINIMAL_INSTALL=.*|MINIMAL_INSTALL=yes|g' "$CONFIGURATION_FILE"
+                else
+                    echo 'MINIMAL_INSTALL=yes' >> "$CONFIGURATION_FILE"
+                fi
+
+                # Do the initial setup which includes email
+                /usr/local/bin/freedombone -c "$CONFIGURATION_FILE"
+            fi
+
+            if grep -q 'install_final' "$COMPLETION_FILE"; then
+                # initial setup has completed
+
+                # switch on nginx authentication for freedombone.local
+                sed -i 's|#auth_basic|auth_basic|g' "/etc/nginx/sites-available/${local_hostname}"
+
+                # Show the web admin index page (not the initial setup page)
+                if [ -f "$webadmin_install_dir/index.prev" ]; then
+                    cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/index.html"
+                fi
+
+                # Remove the initial setup page
+                if [ -f "$webadmin_install_dir/setup.prev" ]; then
+                    rm "$webadmin_install_dir/setup.prev"
+                fi
 
-                        # Add freedns code to the config
-                        if [ "$freedns_code" ]; then
-                            # shellcheck disable=SC2086
-                            ${app_name_upper}_CODE="${freedns_code}"
+                # Replace the installing screen with the main index page when done
+                # It should reload by itself
+                if [ -f "$webadmin_install_dir/setup_installing.prev" ]; then
+                    cp "$webadmin_install_dir/index.prev" "$webadmin_install_dir/setup_installing.html"
+                fi
+
+                # set permissions for web admin site at freedombone.local
+                chown www-data:www-data "$webadmin_install_dir/index.html"
+
+                # remove the setup file created by setup.php
+                rm "$setup_file"
+
+                # restart the web server
+                systemctl restart nginx
+            fi
 
-                            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
+            sleep 1
+
+        else
+            if [ ! -f "$webadmin_install_dir/setup.prev" ]; then
+                # initial setup has completed
+
+                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
-
-                    /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
 
-        sleep 1
+                sleep 1
 
-        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"
+                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
-                    /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
 
diff --git a/src/freedombone-utils-webadmin b/src/freedombone-utils-webadmin
index 5eef954ffde902b97f273c496565da4a4158b10c..6eb4608194d331e4f95e783e33198af1e35981a0 100755
--- a/src/freedombone-utils-webadmin
+++ b/src/freedombone-utils-webadmin
@@ -457,27 +457,37 @@ function web_admin_setup_login {
         $INSTALL_PACKAGES apache2-utils
     fi
 
-    read_config_param MY_USERNAME
-    webadmin_password=$("${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a webadmin)
-    if [ ! "$webadmin_password" ]; then
+    # if an nginx password file has not been created for web admin
+    if [ ! -f /etc/nginx/.webadminpasswd ]; then
         webadmin_password="$(create_password "${MINIMUM_PASSWORD_LENGTH}")"
-        "${PROJECT_NAME}-pass" -u "$MY_USERNAME" -a webadmin -p "$webadmin_password"
 
         # create a password for users
         if [ ! -f /etc/nginx/.webadminpasswd ]; then
             touch /etc/nginx/.webadminpasswd
         fi
-        if grep -q "$MY_USERNAME:" /etc/nginx/.webadminpasswd; then
-            sed -i "/$MY_USERNAME:/d" /etc/nginx/.webadminpasswd
+        if grep -q "admin:" /etc/nginx/.webadminpasswd; then
+            sed -i "/admin:/d" /etc/nginx/.webadminpasswd
         fi
 
-        echo -n "$webadmin_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$MY_USERNAME"
+        # create a password file used by nginx
+        echo -n "$webadmin_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "admin"
         if [ ! -f /etc/nginx/.webadminpasswd ]; then
             echo $'/etc/nginx/.webadminpasswd not found'
-            exit 5637653
+            exit 2428956
         fi
 
-        #echo -n "$webadmin_password" > "/var/www/${local_hostname}/htdocs/admin/initiallogin.txt"
+        # create a setup page with the initial password inserted
+        # and copy it to the index
+        cp "$webadmin_install_dir/index.html" "$webadmin_install_dir/index.prev"
+        cp "$webadmin_install_dir/setup.html" "$webadmin_install_dir/setup.prev"
+        sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup.prev"
+        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
     fi
 }
 
@@ -485,20 +495,41 @@ function install_web_admin {
     # This is intended as an admin web user interface
     # similar to Plinth or the yunohost
 
+    # get the language subdirectory name
+    # This is usually EN
     language_subdir=$(web_admin_get_language_subdir)
 
+    # get the local name (usually freedombone.local) from avahi config
     local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local
+    # where the web admin files are
+    webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin"
+
+    # whether or not to add authentication to freedombone.local
+    basic_auth_str='#auth_basic'
+    if grep -q 'install_final' "$COMPLETION_FILE"; then
+        # initial installation has completed
+        if [ -f /etc/nginx/.webadminpasswd ]; then
+            # a password was created
+            basic_auth_str='auth_basic'
+        fi
+    fi
 
-    if [ ! -d "/var/www/${local_hostname}/htdocs/admin" ]; then
-        mkdir -p "/var/www/${local_hostname}/htdocs/admin"
+    if [ ! -d "$webadmin_install_dir" ]; then
+        mkdir -p "$webadmin_install_dir"
     fi
 
     web_admin_installed=
     if [ -d "/usr/share/${PROJECT_NAME}/webadmin" ]; then
         if [ -d "/usr/share/${PROJECT_NAME}/webadmin/${language_subdir}" ]; then
-            cp -r "/usr/share/${PROJECT_NAME}/webadmin"/* "/var/www/${local_hostname}/htdocs/admin"
-            cp "/usr/share/${PROJECT_NAME}/webadmin/${language_subdir}"/*.html "/var/www/${local_hostname}/htdocs/admin"
+            cp -r "/usr/share/${PROJECT_NAME}/webadmin"/* "$webadmin_install_dir"
+            cp "/usr/share/${PROJECT_NAME}/webadmin/${language_subdir}"/*.html "$webadmin_install_dir"
+
+            if [ -f "$webadmin_install_dir/setup.prev" ]; then
+                # We are still waiting for initial setup to happen
+                cp "$webadmin_install_dir/setup.prev" "$webadmin_install_dir/index.html"
+            fi
 
+            # if this is an onion only install then modify some php scripts
             read_config_param ONION_ONLY
             if [[ "$ONION_ONLY" != 'no' ]]; then
                 web_admin_onion_only
@@ -518,7 +549,7 @@ function install_web_admin {
           echo '  <body>';
           echo "  ${placeholderstr}";
           echo '  </body>';
-          echo '</html>'; } > "/var/www/${local_hostname}/htdocs/admin/index.html"
+          echo '</html>'; } > "$webadmin_install_dir/index.html"
     fi
 
     nginx_file=/etc/nginx/sites-available/$local_hostname
@@ -533,8 +564,8 @@ function install_web_admin {
       echo '  error_log /dev/null;';
       echo '';
       echo '  location ^~ /admin {';
-      echo "    #auth_basic \"${WEBADMIN_LOGIN_TEXT}\";";
-      echo '    #auth_basic_user_file /etc/nginx/.webadminpasswd;';
+      echo "    ${basic_auth_str} \"${WEBADMIN_LOGIN_TEXT}\";";
+      echo "    ${basic_auth_str}_user_file /etc/nginx/.webadminpasswd;";
       echo "    root /var/www/${local_hostname}/htdocs;";
       echo '    index index.html;';
       echo "    error_page 405 = \$uri;";
@@ -576,8 +607,8 @@ function install_web_admin {
     { echo '  add_header Strict-Transport-Security max-age=0;';
       echo '';
       echo '  location ^~ /admin {';
-      echo "    #auth_basic \"${WEBADMIN_LOGIN_TEXT}\";";
-      echo '    #auth_basic_user_file /etc/nginx/.webadminpasswd;';
+      echo "    ${basic_auth_str} \"${WEBADMIN_LOGIN_TEXT}\";";
+      echo "    ${basic_auth_str}_user_file /etc/nginx/.webadminpasswd;";
       echo "    root /var/www/${local_hostname}/htdocs;";
       echo '    index index.html;';
       echo "    error_page 405 = \$uri;";
diff --git a/webadmin/EN/setup.html b/webadmin/EN/setup.html
new file mode 100644
index 0000000000000000000000000000000000000000..ee090685bfaf245fa4a076e19c0622befdb7e5a2
--- /dev/null
+++ b/webadmin/EN/setup.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Refresh" content="30">
+    <style>
+      #headerpic {
+          width: 60%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 220px;
+      }
+
+      #loginicon {
+          width: 20%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 220px;
+      }
+
+      .header {
+          text-align: center;
+          padding: 32px;
+      }
+
+      #iconpic {
+          width: 20%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 120px;
+      }
+
+      .card {
+          box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
+          max-width: 600px;
+          margin: auto;
+          text-align: center;
+          font-family: arial;
+          clear: both;
+      }
+
+      .card input[type=text] {
+          width: 90%;
+          clear: both;
+          text-align: center;
+      }
+
+      .appurl {
+          color: grey;
+          font-size: 100%;
+      }
+
+      .welcomeheader {
+          color: black;
+          font-size: 200%;
+          font-weight: bold;
+      }
+
+      .welcometext {
+          color: black;
+          font-size: 90%;
+      }
+
+      .logintext {
+          color: black;
+          font-size: 120%;
+          font-weight: bold;
+          color: #981737;
+      }
+
+      button {
+          border: none;
+          outline: 0;
+          display: inline-block;
+          padding: 8px;
+          color: white;
+          background-color: #000;
+          text-align: center;
+          cursor: pointer;
+          width: 100%;
+          font-size: 18px;
+      }
+
+      a {
+          text-decoration: none;
+          color: black;
+      }
+
+      button:hover, a:hover {
+          opacity: 0.7;
+      }
+
+      .chip {
+          display: inline-block;
+          padding: 0 25px;
+          height: 50px;
+          font-size: 70%;
+          line-height: 50px;
+          border-radius: 25px;
+          background-color: #f1f1f1;
+      }
+
+      .chip img {
+          float: left;
+          margin: 0 10px 0 -25px;
+          height: 50px;
+          width: 50px;
+          border-radius: 50%;
+      }
+    </style>
+  </head>
+  <body>
+    <div class="card">
+      <div class="header">
+        <img id="headerpic" class="img-responsive" src="images/logo.png">
+      </div>
+      <img id="welcomeicon" class="img-responsive" src="images/login.png">
+      <p class="welcometext">Thankyou for choosing the Freedombone home internet appliance.</p>
+
+      <p class="welcometext">Please take a moment to write down the following credentials, or store them in your preferred password manager. <i>You will not be able to log in again otherwise.</i></p>
+
+      <p class="logintext">Username: admin<br>
+        Password: WEBADMINPASSWORD
+      </p>
+
+      <br>
+
+      <form action="setup.php" method="post">
+        <input type="hidden" name="my_username" value="admin">
+        <input type="hidden" name="default_domain_name" value="freedombone.local">
+        <input type="submit" name="setup" value="Continue">
+      </form>
+
+      <br>
+
+    </div>
+  </body>
+</html>
diff --git a/webadmin/EN/setup_installing.html b/webadmin/EN/setup_installing.html
new file mode 100644
index 0000000000000000000000000000000000000000..a05d76015aaff082f12d68329be12e508fed045e
--- /dev/null
+++ b/webadmin/EN/setup_installing.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Refresh" content="10">
+    <style>
+      #headerpic {
+          width: 60%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 220px;
+      }
+
+      .header {
+          text-align: center;
+          padding: 32px;
+      }
+
+      #iconpic {
+          width: 20%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 120px;
+      }
+
+      .appurl {
+          color: grey;
+          font-size: 100%;
+      }
+
+      .appdesc {
+          color: black;
+          font-size: 65%;
+      }
+
+      button {
+          border: none;
+          outline: 0;
+          display: inline-block;
+          padding: 8px;
+          color: white;
+          background-color: #000;
+          text-align: center;
+          cursor: pointer;
+          width: 100%;
+          font-size: 18px;
+      }
+
+      a {
+          text-decoration: none;
+          color: black;
+      }
+
+      button:hover, a:hover {
+          opacity: 0.7;
+      }
+
+    </style>
+  </head>
+  <body>
+    <div class="header">
+      <a href="index.html"><img id="headerpic" class="img-responsive" src="images/logo.png"></a>
+
+      <h2>Your appliance is being configured</h2>
+
+      <p>This may take some time. Please be patient.</p>
+
+      <form action="index.html">
+        <input type="submit" value="Go Back" />
+      </form>
+    </div>
+
+  </body>
+</html>
diff --git a/webadmin/images/login.png b/webadmin/images/login.png
new file mode 100644
index 0000000000000000000000000000000000000000..634b125484de88003f584501179beb9e0fce544b
Binary files /dev/null and b/webadmin/images/login.png differ
diff --git a/webadmin/setup.php b/webadmin/setup.php
new file mode 100755
index 0000000000000000000000000000000000000000..8facfcf45e52dae43cc415c793673ecfef5c8766
--- /dev/null
+++ b/webadmin/setup.php
@@ -0,0 +1,19 @@
+<?php
+
+if (isset($_POST['setup'])) {
+    $my_username = htmlspecialchars($_POST['my_username']);
+    $default_domain_name = htmlspecialchars($_POST['default_domain_name']);
+
+    if(!file_exists("setup.txt")) {
+        $setup_file = fopen("setup.txt", "w") or die("Unable to create setup file");
+        fwrite($setup_file, $my_username.",".$default_domain_name."\n");
+        fclose($);
+    }
+
+    $output_filename = "setup_installing.html";
+    $htmlfile = fopen("$output_filename", "r") or die("Unable to open $output_filename");
+    echo fread($htmlfile,filesize("$output_filename"));
+    fclose($htmlfile);
+}
+
+?>