#!/bin/bash # _____ _ _ # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___ # | __| _| -_| -_| . | . | | . | . | | -_| # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___| # # Freedom in the Cloud # # Web based administration user interface # typically abailanle on http://freedombone.local # # A background daemon running the freedombone-installer # command is used to add and remove apps and handle # initial setup of the box # # License # ======= # # Copyright © 2014-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/>. WEBADMIN_LOGIN_TEXT=$"Welcome to ${PROJECT_NAME}" function web_admin_get_hostname { # shellcheck disable=SC2154 if [ ! "$rootdir" ]; then # 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 else local_hostname=${PROJECT_NAME}.local fi # where the web admin files are webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" } function web_admin_configure_installer_daemon { if [ -f /etc/systemd/system/webadmin.service ]; then return fi { echo '[Unit]'; echo 'Description=Installer daemon for web admin'; echo 'After=network.target'; echo ''; echo '[Service]'; echo 'User=root'; echo "ExecStart=/usr/local/bin/${PROJECT_NAME}-installer"; echo "ExecReload=/bin/kill \$MAINPID"; echo 'KillMode=process'; echo 'Restart=always'; echo ''; echo '[Install]'; echo 'WantedBy=multi-user.target'; } > /etc/systemd/system/webadmin.service systemctl enable webadmin systemctl daemon-reload systemctl start webadmin } function web_admin_avahi { if [ -f /etc/avahi/services/webadmin.service ]; then return fi { echo '<?xml version="1.0" standalone="no"?><!--*-nxml-*-->'; echo '<!DOCTYPE service-group SYSTEM "avahi-service.dtd">'; echo '<service-group>'; echo ' <name replace-wildcards="yes">%h http</name>'; echo ' <service>'; echo ' <type>_http._tcp</type>'; echo ' <port>80</port>'; echo ' </service>'; echo ' <service>'; echo ' <type>_https._tcp</type>'; echo ' <port>443</port>'; echo ' </service>'; echo '</service-group>'; } > /etc/avahi/services/webadmin.service systemctl restart avahi-daemon } function web_admin_create_users { web_admin_get_hostname users_file="$webadmin_install_dir/users.html" if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then if [ ! -f "$webadmin_install_dir/.running_install_command" ]; then if [ -f "$users_file" ]; then rm "$users_file" fi if [ ! -d "$INSTALL_DIR/tempwebadmin" ]; then mkdir -p "$INSTALL_DIR/tempwebadmin" fi mv "$webadmin_install_dir/userprofile_"*.html "$INSTALL_DIR/tempwebadmin" return fi fi ADMIN_USER=$(get_completion_param "Admin user") 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_"* for d in /home/*/ ; do USERNAME=$(echo "$d" | awk -F '/' '{print $3}') if [[ $(is_valid_user "$USERNAME") == "1" ]]; then 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" == "$ADMIN_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" fi done { echo ' <div class="chip">'; echo " <a href=\"new_user.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 web_admin_create_add_apps { web_admin_get_hostname appslist_add_filename="$webadmin_install_dir/apps_add.html" if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then if [ ! -f "$webadmin_install_dir/.running_install_command" ]; then if [ -f "$appslist_add_filename" ]; then rm "$appslist_add_filename" fi if [ ! -d "$INSTALL_DIR/tempwebadmin" ]; then mkdir -p "$INSTALL_DIR/tempwebadmin" fi mv "$webadmin_install_dir/app_add_"*.html "$INSTALL_DIR/tempwebadmin" return fi fi read_config_param DDNS_PROVIDER read_config_param ONION_ONLY 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 app_index=0 for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') app_index=0 app_is_installed= # shellcheck disable=SC2068 for a in ${APPS_INSTALLED[@]} do installed_app_name=${APPS_INSTALLED_NAMES[$app_index]} if [[ "$installed_app_name" == "$app_name" ]]; then app_is_installed=1 break fi app_index=$((app_index+1)) done # 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 if grep -q "VARIANTS=''" "$app_filename"; then continue fi if grep -q 'VARIANTS=""' "$app_filename"; then continue fi # 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)}') SHORT_DESCRIPTION= 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 SHORT_DESCRIPTION="$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')" 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" # remove domain if onion only if [[ "$ONION_ONLY" != 'no' ]]; then if grep -q 'install_domain' "$filename"; then sed -i '/install_domain/d' "$filename" fi sed -i "/installappconfirm.php/a <input type=\"hidden\" name=\"install_domain\" value=\"${app_name}.$(hostname)\">" "$filename" fi # remove freedns if necessary if [[ "$DDNS_PROVIDER" != *"freedns"* ]]; then if grep -q 'freedns_code' "$filename"; then sed -i '/freedns_code/d' "$filename" fi 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 if [ ${available_apps_ctr} -gt 0 ]; then # 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 ' </div>' >> "$appslist_add_filename" fi { echo ' <br><br>'; echo ' </body>'; echo '</html>'; } >> "$appslist_add_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_create_installed_apps { web_admin_get_hostname appslist_filename="$webadmin_install_dir/apps.html" if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then if [ ! -f "$webadmin_install_dir/.running_install_command" ]; then if [ -f "$appslist_filename" ]; then rm "$appslist_filename" fi if [ ! -d "$INSTALL_DIR/tempwebadmin" ]; then mkdir -p "$INSTALL_DIR/tempwebadmin" fi mv "$webadmin_install_dir/app_"*.html "$INSTALL_DIR/tempwebadmin" return fi fi appslist_template_filename="$webadmin_install_dir/apps_template.html" app_template_filename="$webadmin_install_dir/app_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" total_apps_ctr=0 installed_apps_ctr=0 app_index=0 # shellcheck disable=SC2068,SC2034 for a in ${APPS_INSTALLED[@]} do app_name=${APPS_INSTALLED_NAMES[$app_index]} if [ "$app_name" ]; then app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" if [ -f "$app_filename" ]; then # check if the app is being removed app_being_removed= if [ -f "$pending_removes" ]; then if grep -q "remove_${app_name}" "$pending_removes"; then app_being_removed=1 fi fi if [ ! $app_being_removed ]; 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= fi app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') SHORT_DESCRIPTION= DESCRIPTION= if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then app_index=$((app_index+1)) continue fi if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then app_index=$((app_index+1)) continue fi SHORT_DESCRIPTION="$(grep "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')" 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 read_config_param "${app_name_upper}_DOMAIN_NAME" read_config_param ONION_ONLY if [[ "$ONION_ONLY" == 'no' ]]; then if grep -q "INSTALLED_ON_DEFAULT_DOMAIN=1" "$app_filename"; then read_config_param DEFAULT_DOMAIN_NAME domain_name=$DEFAULT_DOMAIN_NAME else test_domain_name="${app_name_upper}_DOMAIN_NAME" domain_name=${!test_domain_name} fi else domain_name=$(cat "/var/lib/tor/hidden_service_${app_name}/hostname") fi onion_domain_name= if [ -f "/var/lib/tor/hidden_service_${app_name}/hostname" ]; then onion_domain_name=$(cat "/var/lib/tor/hidden_service_${app_name}/hostname") fi if [ "$domain_name" ]; then if [[ "$domain_name" != *'.onion' ]]; then domain_name="https://${domain_name}" else domain_name="http://${onion_domain_name}" fi fi if [ $installed_apps_ctr -eq 0 ]; then echo ' <div class="row">' >> "$appslist_filename" fi filename="$webadmin_install_dir/app_add_${app_name}.html" if [ -f "$filename" ]; then rm "$filename" fi filename="$webadmin_install_dir/app_${app_name}.html" { echo ' <div class="column">'; echo ' <div>'; echo " <a href=\"app_${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_filename" cp "$app_template_filename" "$filename" # Replace app variables sed -i "s|HOSTNAME|$(hostname)|g" "$filename" sed -i "s|APPNAME|${app_name}|g" "$filename" sed -i "s|ONIONURL|http://${onion_domain_name}|g" "$filename" if [[ "$ONION_ONLY" != 'no' ]]; then sed -i '/APPURL/d' "$filename" else sed -i "s|APPURL|${domain_name}|g" "$filename" fi sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename" installed_apps_ctr=$((installed_apps_ctr+1)) total_apps_ctr=$((total_apps_ctr+1)) # four columns per row if [ $installed_apps_ctr -eq 4 ]; then echo ' </div>' >> "$appslist_filename" installed_apps_ctr=0 fi fi fi fi app_index=$((app_index+1)) done if [ ${installed_apps_ctr} -gt 0 ]; then # 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 ' </div>' >> "$appslist_filename" fi if [ $total_apps_ctr -gt 0 ]; then sed -i "/\"appstext\"/d" "$appslist_filename" fi { echo ' <br><br>'; echo ' </body>'; echo '</html>'; } >> "$appslist_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_get_language_subdir { # Gets the subdirectory for the current language # This is an upper case version of the first two characters of # the config variable DEFAULT_LANGUAGE read_config_param DEFAULT_LANGUAGE if [ ! "$DEFAULT_LANGUAGE" ]; then echo 'EN' return fi lang_lower="${DEFAULT_LANGUAGE:0:2}" echo "$lang_lower" | awk '{print toupper($0)}' } function web_admin_onion_only { # In onion only mode domain names or ddns codes # don't need to be provided web_admin_get_hostname # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$rootdir$webadmin_install_dir/app_add_template.html" # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$rootdir$webadmin_install_dir/add_app_confirm_template.html" sed -i '/install_domain/d' "$rootdir$webadmin_install_dir/app_add_template.html" sed -i '/install_domain/d' "$rootdir$webadmin_install_dir/add_app_confirm_template.html" sed -i 's|onion_only=false;|onion_only=true;|g' "$rootdir$webadmin_install_dir/installapp.php" sed -i 's|onion_only=false;|onion_only=true;|g' "$rootdir$webadmin_install_dir/installappconfirm.php" sed -i 's|setup_domain.html|setup_installing.html|g' "$rootdir$webadmin_install_dir/setupconfirm.php" } function web_admin_reset { web_admin_get_hostname # reset the box back to the setup screen if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi if [ -d "$webadmin_install_dir" ]; then touch "$webadmin_install_dir/.setupscreenactive" fi install_web_admin systemctl restart nginx } function web_admin_setup_login { if [ ! -f /usr/bin/htpasswd ]; then $INSTALL_PACKAGES apache2-utils fi # if an nginx password file has not been created for web admin if [ -f /etc/nginx/.webadminpasswd ]; then return fi web_admin_get_hostname # 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 webadmin_password="$(create_password "${MINIMUM_PASSWORD_LENGTH}")" # 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 "admin" if ! grep -q 'admin:' /etc/nginx/.webadminpasswd; then echo $'/etc/nginx/.webadminpasswd password not created for admin' if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi exit 2428956 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 } function image_install_web_admin { if [ "$INSTALLING_MESH" ]; then return fi language_subdir=$(web_admin_get_language_subdir) web_admin_get_hostname # shellcheck disable=SC2154 mkdir -p "$rootdir$webadmin_install_dir" cp -r "$rootdir/usr/share/${PROJECT_NAME}/webadmin"/* "$rootdir$webadmin_install_dir" cp "$rootdir/usr/share/${PROJECT_NAME}/webadmin/${language_subdir}"/*.html "$rootdir$webadmin_install_dir" cp "$rootdir$webadmin_install_dir/${language_subdir}"/index.html "$rootdir$webadmin_install_dir"/index.prev # include onion only status in the config file # because add/remove app screens alter depending upon this if ! grep -q 'ONION_ONLY=' "$rootdir$CONFIGURATION_FILE"; then echo "ONION_ONLY=$ONION_ONLY" >> "$rootdir$CONFIGURATION_FILE" else sed -i "s|ONION_ONLY=.*|ONION_ONLY=$ONION_ONLY|g" "$rootdir$CONFIGURATION_FILE" fi if [[ "$ONION_ONLY" != 'no' ]]; then web_admin_onion_only fi touch "$rootdir$webadmin_install_dir/.setupscreenactive" nginx_file=${rootdir}/etc/nginx/sites-available/${local_hostname} { echo 'server {'; echo ' listen 80 default_server;'; echo ' #listen [::]:80;'; echo " server_name ${local_hostname};"; echo " root /var/www/${local_hostname}/htdocs;"; echo ' index index.html;'; echo ''; echo ' access_log /dev/null;'; echo ' error_log /dev/null;'; echo ''; echo ' location ^~ /admin {'; echo " #auth_basic \"${WEBADMIN_LOGIN_TEXT}\";"; echo " #auth_basic_user_file /etc/nginx/.webadminpasswd;"; echo " root /var/www/${local_hostname}/htdocs;"; echo ' index index.html;'; echo " error_page 405 = \$uri;"; echo ' location ~ \.php {'; echo ' include snippets/fastcgi-php.conf;'; echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;'; echo ' fastcgi_read_timeout 30;'; echo ' }'; echo ' }'; echo ''; echo ' location /icons {'; echo ' autoindex on;'; echo ' break;'; echo ' }'; echo ''; echo ' rewrite ^/plinth/(.*)$ /api.json last;'; echo ''; echo ' location / {'; echo " root /var/www/${local_hostname}/htdocs/plinth;"; echo ' index api.json /api.json;'; echo " error_page 405 = \$uri;"; echo ' }'; echo '}'; } > "$nginx_file" # enable the webadmin site chroot "$rootdir" ln -s "/etc/nginx/sites-available/${local_hostname}" /etc/nginx/sites-enabled/ chroot "$rootdir" chown -R www-data:www-data "/var/www/${local_hostname}/htdocs" chroot "$rootdir" chmod g+w "/var/www/${local_hostname}/htdocs" chroot "$rootdir" chmod a+w "$webadmin_install_dir" { echo '[Unit]'; echo 'Description=Installer daemon for web admin'; echo 'After=network.target'; echo ''; echo '[Service]'; echo 'User=root'; echo "ExecStart=/usr/local/bin/${PROJECT_NAME}-installer"; echo "ExecReload=/bin/kill \$MAINPID"; echo 'KillMode=process'; echo 'Restart=always'; echo ''; echo '[Install]'; echo 'WantedBy=multi-user.target'; } > "$rootdir/etc/systemd/system/webadmin.service" chroot "$rootdir" systemctl enable webadmin } function regenerate_webadmin_dynamic_dns { read_config_param DDNS_PROVIDER read_config_param DDNS_USERNAME read_config_param DDNS_PASSWORD local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/dynamicdns_template.html" ]; then cp "$webadmin_install_dir/dynamicdns_template.html" "$webadmin_install_dir/dynamicdns.html" ddns="$DDNS_PROVIDER" if [[ "$ddns" == 'default@freedns.afraid.org' ]]; then ddns='freedns' fi if [[ "$ddns" == 'dyn.com' ]]; then ddns='dyn' fi sed -i "s|\"$ddns\"|\"$ddns\" selected|g" "$webadmin_install_dir/dynamicdns.html" sed -i "s|DDNS_USERNAME|$DDNS_USERNAME|g" "$webadmin_install_dir/dynamicdns.html" # Note: For security don't populate the password #sed -i "s|DDNS_PASSWORD|$DDNS_PASSWORD|g" "$webadmin_install_dir/dynamicdns.html" chown www-data:www-data "$webadmin_install_dir/dynamicdns.html" fi } function webadmin_update_system_monitor { test_drive=/dev/sda1 if ! ls $test_drive; then if ls /dev/mmcblk0p2; then test_drive=/dev/mmcblk0p2 else test_drive= fi fi disk_use=$(df -h | grep $test_drive) disk_use_percent=0 if [[ "$disk_use" != *"$test_drive"* ]]; then disk_use_percent=$(df -h | grep /dev/mmcblk0p1 | awk -F ' ' '{print $5}') fi used_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $3}') total_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $2}') used_memory_percent=$((used_memory * 100 / total_memory)) cpu_temperature=0 if [ -f /sys/class/thermal/thermal_zone0/temp ]; then cpu_temp=$(cat /sys/class/thermal/thermal_zone*/temp | head -n 1) if [ "$cpu_temp" ]; then cpu_temperature=$((cpu_temp / 1000)) fi fi disk_io_speed=20 disk_io_speed_percent=10 if [ "$test_drive" ]; then disk_io_speed=$(hdparm -t $test_drive | awk -F '= ' '{print $2}' | awk -F ' ' '{print $1}' | tail -n 1 | awk -F '.' '{print $1}') if [ "$disk_io_speed" ]; then disk_io_speed_percent=$((disk_io_speed * 100 / 500)) if [ $disk_io_speed_percent -gt 100 ]; then disk_io_speed_percent=100 fi fi fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/system_monitor_template.html" ]; then cp "$webadmin_install_dir/system_monitor_template.html" "$webadmin_install_dir/system_monitor.html" if [[ "$disk_use_percent" == *'%'* ]]; then sed -i "s|<div name=\"diskspace\" class=\"w3-container.*|<div name=\"diskspace\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$disk_use_percent\">$disk_use_percent</div>|g" "$webadmin_install_dir/system_monitor.html" fi sed -i "s|<div name=\"memory\" class=\"w3-container.*|<div name=\"memory\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${used_memory_percent}%\">${used_memory_percent}%</div>|g" "$webadmin_install_dir/system_monitor.html" if [ $cpu_temperature -gt 0 ]; then sed -i "s|<div name=\"cputemp\" class=\"w3-container.*|<div name=\"cputemp\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${cpu_temperature}%\">${cpu_temperature}C</div>|g" "$webadmin_install_dir/system_monitor.html" else sed -i "/\"cputemp\"/d" "$webadmin_install_dir/system_monitor.html" sed -i '/titletextcputemp/d' "$webadmin_install_dir/system_monitor.html" fi sed -i "s|<div name=\"diskio\" class=\"w3-container.*|<div name=\"diskio\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${disk_io_speed_percent}%\">${disk_io_speed} MB/s</div>|g" "$webadmin_install_dir/system_monitor.html" chown www-data:www-data "$webadmin_install_dir/system_monitor.html" fi } function webadmin_change_language { read_config_param DEFAULT_LANGUAGE language="$DEFAULT_LANGUAGE" local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/language_template.html" ]; then if grep -q "\"$language\"" "$webadmin_install_dir/language_template.html"; then cp "$webadmin_install_dir/language_template.html" "$webadmin_install_dir/language.html" sed -i "s|\"$language\"|\"$language\" selected|g" "$webadmin_install_dir/language.html" chown www-data:www-data "$webadmin_install_dir/language.html" fi fi } function webadmin_update_version { local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/about.html" ]; then VERSION=$(grep "VERSION=" "/usr/local/bin/${PROJECT_NAME}-vars" | grep -v DEBIAN | awk -F '"' '{print $2}') versionstr=$"Version $VERSION" sed -i "s|\"versiontext\".*|\"versiontext\">$versionstr</p>|g" "$webadmin_install_dir/about.html" fi } 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) web_admin_get_hostname # 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 if [ ! -f "$webadmin_install_dir/.setupscreenactive" ]; then # a password was created basic_auth_str='auth_basic' fi fi fi 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"/* "$webadmin_install_dir" cp "/usr/share/${PROJECT_NAME}/webadmin/${language_subdir}"/*.html "$webadmin_install_dir" cp "$webadmin_install_dir/${language_subdir}"/index.html "$webadmin_install_dir"/index.prev if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then 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 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 fi web_admin_installed=1 else echo $"No web admin language subdirectory for ${language_subdir}" fi else echo $"Directory not found /usr/share/${PROJECT_NAME}/webadmin" fi if [ ! $web_admin_installed ]; then placeholderstr=$"This is a placeholder for the web admin panel on ${local_hostname}" { echo '<html>'; echo ' <body>'; echo " ${placeholderstr}"; echo ' </body>'; echo '</html>'; } > "$webadmin_install_dir/index.html" fi nginx_file=/etc/nginx/sites-available/$local_hostname { echo 'server {'; echo ' listen 80 default_server;'; echo ' #listen [::]:80;'; echo " server_name ${local_hostname};"; echo " root /var/www/${local_hostname}/htdocs;"; echo ' index index.html;'; echo ''; echo ' access_log /dev/null;'; echo ' error_log /dev/null;'; echo ''; echo ' location ^~ /admin {'; 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;"; echo ' location ~ \.php {'; echo ' include snippets/fastcgi-php.conf;'; echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;'; echo ' fastcgi_read_timeout 30;'; echo ' }'; echo ' }'; echo ''; echo ' location /icons {'; echo ' autoindex on;'; echo ' break;'; echo ' }'; echo ''; echo ' rewrite ^/plinth/(.*)$ /api.json last;'; echo ''; echo ' location / {'; echo " root /var/www/${local_hostname}/htdocs/plinth;"; echo ' index api.json /api.json;'; echo " error_page 405 = \$uri;"; echo ' }'; echo '}'; echo ''; echo 'server {'; echo ' listen 443 default_server ssl;'; echo ' #listen [::]:443 ssl;'; echo " server_name ${local_hostname};"; echo " root /var/www/${local_hostname}/htdocs;"; echo ' index index.html;'; echo ''; echo ' access_log /dev/null;'; echo ' error_log /dev/null;'; echo ''; } > "$nginx_file" nginx_ssl "${local_hostname}" nginx_security_options "${local_hostname}" { echo ' add_header Strict-Transport-Security max-age=0;'; echo ''; echo ' location ^~ /admin {'; 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;"; echo ' location ~ \.php {'; echo ' include snippets/fastcgi-php.conf;'; echo ' fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;'; echo ' fastcgi_read_timeout 30;'; echo ' }'; echo ' }'; echo ''; echo ' location /icons {'; echo ' autoindex on;'; echo ' break;'; echo ' }'; echo ''; echo ' rewrite ^/plinth/(.*)$ /api.json last;'; echo ''; echo ' location / {'; echo " root /var/www/${local_hostname}/htdocs/plinth;"; echo ' index api.json /api.json;'; echo " error_page 405 = \$uri;"; echo ' }'; echo '}'; } >> "$nginx_file" if [ ! -f "/etc/ssl/certs/${local_hostname}.crt" ]; then "${PROJECT_NAME}-addcert" -h "${local_hostname}" --dhkey "${DH_KEYLENGTH}" fi sed -i "s|ssl_certificate .*|ssl_certificate /etc/ssl/certs/${local_hostname}.crt;|g" "$nginx_file" sed -i "s|ssl_certificate_key .*|ssl_certificate_key /etc/ssl/private/${local_hostname}.key;|g" "$nginx_file" nginx_ensite "${local_hostname}" # Compatibility with FreedomBox android app # The installed apps get published to a json file called api.json # in this directory if [ ! -d "/var/www/${local_hostname}/htdocs/plinth" ]; then mkdir -p "/var/www/${local_hostname}/htdocs/plinth" fi web_admin_create_users # make list of apps which can be added web_admin_create_add_apps # make the list of apps web_admin_create_installed_apps web_admin_setup_login chown -R www-data:www-data "/var/www/${local_hostname}/htdocs" chmod g+w "/var/www/${local_hostname}/htdocs" chmod a+w "$webadmin_install_dir" web_admin_avahi web_admin_configure_installer_daemon regenerate_webadmin_blocklist regenerate_webadmin_dynamic_dns webadmin_update_system_monitor webadmin_change_language webadmin_update_version } # NOTE: deliberately no exit 0