| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844 | #!/bin/bash
#
# .---.                  .              .
# |                      |              |
# |--- .--. .-.  .-.  .-.|  .-. .--.--. |.-.  .-. .--.  .-.
# |    |   (.-' (.-' (   | (   )|  |  | |   )(   )|  | (.-'
# '    '     --'  --'  -' -  -' '  '   -' -'   -' '   -  --'
#
#                    Freedom in the Cloud
#
# SKS Keyserver
#
# License
# =======
#
# Copyright (C) 2017 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/>.
VARIANTS='full full-vim'
IN_DEFAULT_INSTALL=0
SHOW_ON_ABOUT=1
KEYSERVER_WEB_REPO="https://github.com/mattrude/pgpkeyserver-lite"
KEYSERVER_WEB_COMMIT='a038cb79b927c99bf7da62f20d2c6a2f20374339'
KEYSERVER_PORT=11371
KEYSERVER_ONION_PORT=8122
KEYSERVER_DOMAIN_NAME=
KEYSERVER_CODE=
keyserver_variables=(ONION_ONLY
                     MY_USERNAME
                     DEFAULT_DOMAIN_NAME
                     KEYSERVER_DOMAIN_NAME
                     KEYSERVER_CODE)
function check_keyserver_directory_size {
    dirsize=$(du /var/lib/sks/DB | awk -F ' ' '{print $1}')
    # 500M
    if [ $dirsize -gt 500000 ]; then
        echo "1"
        return
    fi
    echo "0"
}
function keyserver_watchdog {
    ADMIN_USERNAME=$(cat $COMPLETION_FILE | grep "Admin user" | awk -F ':' '{print $2}')
    ADMIN_EMAIL_ADDRESS=${ADMIN_USERNAME}@${HOSTNAME}
    keyserver_size_warning=$"The SKS keyserver database is getting large. Check that you aren't being spammed"
    keyserver_disabled_warning=$"The SKS keyserver has been disabled because it is getting too large. This is to prevent flooding attacks from crashing the server. You may need to restore the keyserver from backup."
    keyserver_mail_subject_line=$"${PROJECT_NAME} keyserver warning"
    keyserver_mail_subject_line_disabled=$"${PROJECT_NAME} keyserver disabled"
    read_config_param KEYSERVER_DOMAIN_NAME
    # check database size hourly
    keyserver_watchdog_script=/tmp/keyserver-watchdog
    echo '#!/bin/bash' > $keyserver_watchdog_script
    echo "dirsize=\$(du /var/lib/sks/DB | awk -F ' ' '{print \$1}')" >> $keyserver_watchdog_script
    echo 'if [ $dirsize -gt 450000 ]; then' >> $keyserver_watchdog_script
    echo "  echo \"$keyserver_size_warning\" | mail -s \"$keyserver_mail_subject_line\" $ADMIN_EMAIL_ADDRESS" >> $keyserver_watchdog_script
    echo '  if [ $dirsize -gt 500000 ]; then' >> $keyserver_watchdog_script
    echo "    nginx_dissite $KEYSERVER_DOMAIN_NAME" >> $keyserver_watchdog_script
    echo '    systemctl stop sks' >> $keyserver_watchdog_script
    echo '    systemctl disable sks' >> $keyserver_watchdog_script
    echo "    echo \"$keyserver_disabled_warning\" | mail -s \"$keyserver_mail_subject_line_disabled\" $ADMIN_EMAIL_ADDRESS" >> $keyserver_watchdog_script
    echo '  fi' >> $keyserver_watchdog_script
    echo 'fi' >> $keyserver_watchdog_script
    chmod +x $keyserver_watchdog_script
    if [ ! -f /etc/cron.hourly/keyserver-watchdog ]; then
        cp $keyserver_watchdog_script /etc/cron.hourly/keyserver-watchdog
    else
        HASH1=$(sha256sum $keyserver_watchdog_script | awk -F ' ' '{print $1}')
        HASH2=$(sha256sum /etc/cron.hourly/keyserver-watchdog | awk -F ' ' '{print $1}')
        if [[ "$HASH1" != "$HASH2" ]]; then
            cp $keyserver_watchdog_script /etc/cron.hourly/keyserver-watchdog
        fi
    fi
    rm $keyserver_watchdog_script
}
function configure_firewall_for_keyserver {
    if [[ $ONION_ONLY != "no" ]]; then
        return
    fi
    firewall_add keyserver 11370 tcp
    firewall_add keyserver 11371 tcp
    firewall_add keyserver 11372 tcp
    mark_completed $FUNCNAME
}
function keyserver_reset_database {
    if [ -d /var/lib/sks/DB ]; then
        rm -rf /var/lib/sks/DB
    fi
    sks build
    chown -Rc debian-sks: /var/lib/sks
    systemctl restart sks
}
function logging_on_keyserver {
    echo -n ''
}
function logging_off_keyserver {
    echo -n ''
}
function reconfigure_keyserver {
    echo -n ''
}
function upgrade_keyserver {
    keyserver_watchdog
    CURR_KEYSERVER_WEB_COMMIT=$(get_completion_param "keyserver web commit")
    if [[ "$CURR_KEYSERVER_WEB_COMMIT" == "$KEYSERVER_WEB_COMMIT" ]]; then
        return
    fi
    if grep -q "keyserver domain" $COMPLETION_FILE; then
        KEYSERVER_DOMAIN_NAME=$(get_completion_param "keyserver domain")
    fi
    # update to the next commit
    function_check set_repo_commit
    set_repo_commit /var/www/$KEYSERVER_DOMAIN_NAME/htdocs "keyserver web commit" "$KEYSERVER_WEB_COMMIT" $KEYSERVER_WEB_REPO
    read_config_param MY_USERNAME
    USER_EMAIL_ADDRESS=$MY_USERNAME@$HOSTNAME
    GPG_ID=$(su -m root -c "gpg --list-keys $USER_EMAIL_ADDRESS | sed -n '2p' | sed 's/^[ \t]*//'" - $MY_USERNAME)
    if [ ! $GPG_ID ]; then
        echo $'No GPG ID for admin user'
        exit 846336
    fi
    if [ ${#GPG_ID} -lt 5 ]; then
        echo $'GPG ID not retrieved for admin user'
        exit 835292
    fi
    if [[ "$GPG_ID" == *"error"* ]]; then
        echo $'GPG ID not retrieved for admin user due to error'
        exit 74825
    fi
    sed -i "s|###ENTERPUBLICKEYHERE###|$GPG_ID|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/404.html
    sed -i "s|###ENTERPUBLICKEYHERE###|$GPG_ID|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/index.html
    sed -i "s|###ENTERNAMEHERE###|$USER_EMAIL_ADDRESS|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/404.html
    sed -i "s|###ENTERNAMEHERE###|$USER_EMAIL_ADDRESS|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/index.html
    chown -R www-data:www-data /var/www/$KEYSERVER_DOMAIN_NAME/htdocs
}
function backup_local_keyserver {
    # remove any unused log files
    cd /var/lib/sks/DB
    db_archive -d
    source_directory=/etc/sks
    if [ -d $source_directory ]; then
        systemctl stop sks
        dest_directory=keyserverconfig
        function_check backup_directory_to_usb
        backup_directory_to_usb $source_directory $dest_directory
        systemctl start sks
    fi
    if [[ "$(check_keyserver_directory_size)" != "0" ]]; then
        echo $'WARNING: Keyserver database size is too large to backup'
        return
    fi
    source_directory=/var/lib/sks/DB
    if [ -d $source_directory ]; then
        systemctl stop sks
        dest_directory=keyserver
        function_check backup_directory_to_usb
        backup_directory_to_usb $source_directory $dest_directory
        systemctl start sks
    fi
}
function restore_local_keyserver {
    if [ ! -d /var/lib/sks/DB ]; then
        return
    fi
    echo $"Restoring SKS Keyserver"
    systemctl stop sks
    temp_restore_dir=/root/tempkeyserverconfig
    function_check restore_directory_from_usb
    restore_directory_from_usb $temp_restore_dir keyserverconfig
    cp -r $temp_restore_dir/etc/sks/* /etc/sks/
    rm -rf $temp_restore_dir
    chown -Rc debian-sks: /etc/sks/sksconf
    chown -Rc debian-sks: /etc/sks/mailsync
    temp_restore_dir=/root/tempkeyserver
    function_check restore_directory_from_usb
    restore_directory_from_usb $temp_restore_dir keyserver
    mv /var/lib/sks/DB /var/lib/sks/DB_prev
    cp -r $temp_restore_dir/var/lib/sks/DB /var/lib/sks/DB
    if [ ! "$?" = "0" ]; then
        # restore the old database
        rm -rf /var/lib/sks/DB
        mv /var/lib/sks/DB_prev /var/lib/sks/DB
        rm -rf $temp_restore_dir
        function_check set_user_permissions
        set_user_permissions
        function_check backup_unmount_drive
        backup_unmount_drive
        exit 5627294
    fi
    rm -rf $temp_restore_dir
    chown -Rc debian-sks: /var/lib/sks
    # remove the old database
    rm -rf /var/lib/sks/DB_prev
    systemctl enable sks
    systemctl start sks
    nginx_ensite $KEYSERVER_DOMAIN_NAME
}
function backup_remote_keyserver {
    # remove any unused log files
    cd /var/lib/sks/DB
    db_archive -d
    source_directory=/etc/sks
    if [ -d $source_directory ]; then
        systemctl stop sks
        dest_directory=keyserverconfig
        function_check backup_directory_to_friend
        backup_directory_to_friend $source_directory $dest_directory
        systemctl start sks
    fi
    if [[ "$(check_keyserver_directory_size)" != "0" ]]; then
        echo $'WARNING: Keyserver database size is too large to backup'
        return
    fi
    source_directory=/var/lib/sks/DB
    if [ -d $source_directory ]; then
        systemctl stop sks
        dest_directory=keyserver
        function_check backup_directory_to_friend
        backup_directory_to_friend $source_directory $dest_directory
        systemctl start sks
    fi
}
function restore_remote_keyserver {
    if [ ! -d /var/lib/sks/DB ]; then
        return
    fi
    echo $"Restoring SKS Keyserver"
    systemctl stop sks
    temp_restore_dir=/root/tempkeyserverconfig
    function_check restore_directory_from_friend
    restore_directory_from_friend $temp_restore_dir keyserverconfig
    cp -r $temp_restore_dir/etc/sks/* /etc/sks/
    rm -rf $temp_restore_dir
    chown -Rc debian-sks: /etc/sks/sksconf
    chown -Rc debian-sks: /etc/sks/mailsync
    temp_restore_dir=/root/tempkeyserver
    function_check restore_directory_from_friend
    restore_directory_from_friend $temp_restore_dir keyserver
    mv /var/lib/sks/DB /var/lib/sks/DB_prev
    cp -r $temp_restore_dir/var/lib/sks/DB /var/lib/sks/DB
    if [ ! "$?" = "0" ]; then
        # restore the old database
        rm -rf /var/lib/sks/DB
        mv /var/lib/sks/DB_prev /var/lib/sks/DB
        rm -rf $temp_restore_dir
        function_check set_user_permissions
        set_user_permissions
        return
    fi
    rm -rf $temp_restore_dir
    chown -Rc debian-sks: /var/lib/sks
    # remove the old database
    rm -rf /var/lib/sks/DB_prev
    systemctl enable sks
    systemctl start sks
    nginx_ensite $KEYSERVER_DOMAIN_NAME
}
function remove_keyserver {
    systemctl stop sks
    if [ -f /etc/cron.hourly/keyserver-watchdog ]; then
        rm /etc/cron.hourly/keyserver-watchdog
    fi
    apt-get -qy remove sks dirmngr
    read_config_param "KEYSERVER_DOMAIN_NAME"
    nginx_dissite $KEYSERVER_DOMAIN_NAME
    remove_certs ${KEYSERVER_DOMAIN_NAME}
    if [ -f /etc/nginx/sites-available/$KEYSERVER_DOMAIN_NAME ]; then
        rm -f /etc/nginx/sites-available/$KEYSERVER_DOMAIN_NAME
    fi
    if [ -d /var/www/$KEYSERVER_DOMAIN_NAME ]; then
        rm -rf /var/www/$KEYSERVER_DOMAIN_NAME
    fi
    function_check remove_ddns_domain
    remove_ddns_domain $KEYSERVER_DOMAIN_NAME
    remove_config_param KEYSERVER_DOMAIN_NAME
    remove_config_param KEYSERVER_CODE
    function_check remove_onion_service
    remove_onion_service keyserver ${KEYSERVER_ONION_PORT}
    remove_onion_service sks 11370 11371 11372
    remove_completion_param "install_keyserver"
    firewall_remove 11370 tcp
    firewall_remove 11371 tcp
    firewall_remove 11372 tcp
    sed -i '/keyserver/d' $COMPLETION_FILE
    sed -i '/sks onion/d' $COMPLETION_FILE
    if [ -d /var/lib/sks ]; then
        rm -rf /var/lib/sks
    fi
}
function install_interactive_keyserver {
    if [ ! $ONION_ONLY ]; then
        ONION_ONLY='no'
    fi
    if [[ $ONION_ONLY != "no" ]]; then
        KEYSERVER_DOMAIN_NAME='keyserver.local'
        write_config_param "KEYSERVER_DOMAIN_NAME" "$KEYSERVER_DOMAIN_NAME"
    else
        function_check interactive_site_details
        interactive_site_details "keyserver" "KEYSERVER_DOMAIN_NAME" "KEYSERVER_CODE"
    fi
    APP_INSTALLED=1
}
function keyserver_create_mailsync {
    echo $"# List of email addresses which submitted keys will be forwarded to" > /etc/sks/mailsync
    echo '' >> /etc/sks/mailsync
    chown -Rc debian-sks: /etc/sks/mailsync
}
function keyserver_create_membership {
    if [ -f /etc/sks/membership ]; then
        return
    fi
    systemctl stop sks
    echo $"# List of other $PROJECT_NAME SKS Keyservers to sync with." > /etc/sks/membership
    echo '#' >> /etc/sks/membership
    echo $"# Don't add major keyservers here, because it will take an" >> /etc/sks/membership
    echo $'# Infeasible amount of time to sync and backups will become' >> /etc/sks/membership
    echo $'# absurdly long and probably break your system. You have been warned.' >> /etc/sks/membership
    echo '' >> /etc/sks/membership
    chown -Rc debian-sks: /etc/sks/membership
    systemctl start sks
}
function keyserver_import_keys {
    # NOTE: this function isn't used, but kept for reference
    dialog --title $"Import public keys database" \
           --backtitle $"Freedombone Control Panel" \
           --defaultno \
           --yesno $"\nThis will download many gigabytes of data and so depending on your bandwidth it could take several days.\n\nContinue?" 10 60
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    if [ ! -d /var/lib/sks/dump ]; then
        mkdir -p /var/lib/sks/dump
    fi
    cd /var/lib/sks/dump
    echo $'Getting keyserver dump. This may take a few days or longer, so be patient.'
    rm -rf /var/lib/sks/dump/*
    KEYSERVER_DUMP_URL="https://keyserver.mattrude.com/dump/$(date +%F)/"
    wget -crp -e robots=off --level=1 --cut-dirs=3 -nH \
         -A pgp,txt $KEYSERVER_DUMP_URL
    cd /var/lib/sks
    echo $'Building the keyserver database from the downloaded dump'
    keyserver_reset_database
}
function keyserver_sync {
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Sync with other keyserver" \
           --form $"\nEnter details for the other server. Please be aware that it's not a good idea to sync with major keyservers which have exceptionally large databases. This is intended to sync with other $PROJECT_NAME systems each having a small database for a particular community." 16 60 3 \
           $"Domain:" 1 1 "" 1 25 32 64 \
           $"Port:" 2 1 "11370" 2 25 6 6 \
           $"Sync Email (optional):" 3 1 "pgp-public-keys@" 3 25 32 64 \
           2> $data
    sel=$?
    case $sel in
        1) return;;
        255) return;;
    esac
    other_keyserver_domain=$(cat $data | sed -n 1p)
    other_keyserver_port=$(cat $data | sed -n 2p)
    other_keyserver_email=$(cat $data | sed -n 3p)
    if [[ "$other_keyserver_domain" != *'.'* ]]; then
        return
    fi
    if [[ "$other_keyserver_domain" == *' '* ]]; then
        return
    fi
    if [[ "$other_keyserver_port" == *'.'* ]]; then
        return
    fi
    if [[ "$other_keyserver_port" == *' '* ]]; then
        return
    fi
    if [ ${#other_keyserver_domain} -lt 4 ]; then
        return
    fi
    if [ ${#other_keyserver_port} -lt 4 ]; then
        return
    fi
    # Warn if trying to sync
    if [[ "$other_keyserver_domain" == *"sks-keyservers.net" || "$other_keyserver_domain" == *"gnupg.net" || "$other_keyserver_domain" == *"pgp.com" || "$other_keyserver_domain" == *"pgp.mit.edu" || "$other_keyserver_domain" == *"the.earth.li" || "$other_keyserver_domain" == *"mayfirst.org" || "$other_keyserver_domain" == *"ubuntu.com" ]]; then
        dialog --title $"Sync with other keyserver" \
               --msgbox $"\nDon't try to sync with the major keyservers. Your system will be overloaded with an infeasible database size." 8 60
        return
    fi
    if [[ "$other_keyserver_email" != "pgp-public-keys@" ]]; then
        if [[ "$other_keyserver_email" == *"@"* ]]; then
            if [[ "$other_keyserver_email" == *"."* ]]; then
                keyserver_create_mailsync
                if ! grep -q "$other_keyserver_email" /etc/sks/mailsync; then
                    echo "$other_keyserver_email" >> /etc/sks/mailsync
                    chown -Rc debian-sks: /etc/sks/mailsync
                fi
            else
                dialog --title $"Sync with other keyserver" \
                       --msgbox $"Email doesn't look right: $other_keyserver_email" 6 60
                return
            fi
        fi
    fi
    keyserver_create_membership
    if grep -q "$other_keyserver_domain $other_keyserver_port" /etc/sks/membership; then
        return
    fi
    if grep -q "$other_keyserver_domain " /etc/sks/membership; then
        sed -i "s|$other_keyserver_domain .*|$other_keyserver_domain $other_keyserver_port|g" /etc/sks/membership
    else
        echo "$other_keyserver_domain $other_keyserver_port" >> /etc/sks/membership
    fi
    chown -Rc debian-sks: /etc/sks/membership
    systemctl restart sks
    dialog --title $"Sync with other keyserver" \
           --msgbox $"Keyserver added" 6 40
}
function keyserver_edit {
    if [ ! -f /etc/sks/membership ]; then
        return
    fi
    editor /etc/sks/membership
    chown -Rc debian-sks: /etc/sks/membership
    systemctl restart sks
}
function keyserver_remove_key {
    data=$(tempfile 2>/dev/null)
    trap "rm -f $data" 0 1 2 5 15
    dialog --title $"Remove a key" \
           --backtitle $"Freedombone Control Panel" \
           --inputbox $"Enter the ID of the key which you wish to remove:" 12 60 2>$data
    sel=$?
    case $sel in
        0)
            remove_key_id=$(<$data)
            if [ ${#remove_key_id} -gt 8 ]; then
                sks drop $remove_key_id
                dialog --title $"Remove a key" \
                       --msgbox $"The key was removed" 6 40
            fi
            ;;
    esac
}
function configure_interactive_keyserver {
    while true
    do
        data=$(tempfile 2>/dev/null)
        trap "rm -f $data" 0 1 2 5 15
        dialog --backtitle $"Freedombone Control Panel" \
               --title $"SKS Keyserver" \
               --radiolist $"Choose an operation:" 12 70 4 \
               1 $"Remove a key" off \
               2 $"Sync with other keyserver" off \
               3 $"Edit sync keyservers" off \
               4 $"Exit" on 2> $data
        sel=$?
        case $sel in
            1) return;;
            255) return;;
        esac
        case $(cat $data) in
            1) keyserver_remove_key;;
            2) keyserver_sync;;
            3) keyserver_edit;;
            4) break;;
        esac
    done
}
function install_keyserver {
    apt-get -qy install build-essential gcc ocaml libdb-dev wget sks
    keyserver_reset_database
    sed -i 's|initstart=.*|initstart=yes|g' /etc/default/sks
    apt-get -qy install dirmngr
    systemctl restart sks
    if [ ! -d /var/www/$KEYSERVER_DOMAIN_NAME ]; then
        mkdir /var/www/$KEYSERVER_DOMAIN_NAME
    fi
    cd /var/www/$KEYSERVER_DOMAIN_NAME
    if [ -d /var/www/$KEYSERVER_DOMAIN_NAME/htdocs ]; then
        rm -rf /var/www/$KEYSERVER_DOMAIN_NAME/htdocs
    fi
    if [ -d /repos/keyserverweb ]; then
        mkdir htdocs
        cp -r -p /repos/keyserverweb/. htdocs
        cd htdocs
        git pull
    else
        git_clone $KEYSERVER_WEB_REPO htdocs
    fi
    if [ ! -d /var/www/$KEYSERVER_DOMAIN_NAME/htdocs ]; then
        echo $"/var/www/$KEYSERVER_DOMAIN_NAME/htdocs not found"
        exit 6539230
    fi
    cd /var/www/$KEYSERVER_DOMAIN_NAME/htdocs
    git checkout $KEYSERVER_WEB_COMMIT -b $KEYSERVER_WEB_COMMIT
    set_completion_param "keyserver web commit" "$KEYSERVER_WEB_COMMIT"
    USER_EMAIL_ADDRESS=$MY_USERNAME@$HOSTNAME
    GPG_ID=$(su -m root -c "gpg --list-keys $USER_EMAIL_ADDRESS | sed -n '2p' | sed 's/^[ \t]*//'" - $MY_USERNAME)
    if [ ! $GPG_ID ]; then
        echo $'No GPG ID for admin user'
        exit 846336
    fi
    if [ ${#GPG_ID} -lt 5 ]; then
        echo $'GPG ID not retrieved for admin user'
        exit 835292
    fi
    if [[ "$GPG_ID" == *"error"* ]]; then
        echo $'GPG ID not retrieved for admin user due to error'
        exit 74825
    fi
    sed -i "s|###ENTERPUBLICKEYHERE###|$GPG_ID|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/404.html
    sed -i "s|###ENTERPUBLICKEYHERE###|$GPG_ID|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/index.html
    sed -i "s|###ENTERNAMEHERE###|$USER_EMAIL_ADDRESS|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/404.html
    sed -i "s|###ENTERNAMEHERE###|$USER_EMAIL_ADDRESS|g" /var/www/$KEYSERVER_DOMAIN_NAME/htdocs/index.html
    sksconf_file=/etc/sks/sksconf
    sed -i "s|#hostname:.*|hostname: $KEYSERVER_DOMAIN_NAME|g" $sksconf_file
    sed -i "s|hostname:.*|hostname: $KEYSERVER_DOMAIN_NAME|g" $sksconf_file
    sed -i "s|#hkp_port:.*|hkp_port: 11373|g" $sksconf_file
    sed -i "s|hkp_port:.*|hkp_port: 11373|g" $sksconf_file
    sed -i "s|#recon_port:.*|recon_port: 11370|g" $sksconf_file
    sed -i "s|recon_port:.*|recon_port: 11370|g" $sksconf_file
    sed -i "s|#recon_address:.*|recon_address: 0.0.0.0|g" $sksconf_file
    sed -i "s|recon_address:.*|recon_address: 0.0.0.0|g" $sksconf_file
    sed -i 's|#hkp_address:.*|hkp_address: 127.0.0.1|g' $sksconf_file
    sed -i 's|hkp_address:.*|hkp_address: 127.0.0.1|g' $sksconf_file
    sed -i "s|#from_addr:.*|from_addr: \"pgp-public-keys@$DEFAULT_DOMAIN_NAME\"|g" $sksconf_file
    sed -i "s|from_addr:.*|from_addr: \"pgp-public-keys@$DEFAULT_DOMAIN_NAME\"|g" $sksconf_file
    sed -i 's|#sendmail_cmd:|sendmail_cmd:|g' $sksconf_file
    if ! grep -q "#disable_mailsync" $sksconf_file; then
        echo '#disable_mailsync:' >> $sksconf_file
    else
        sed -i 's|disable_mailsync:|#disable_mailsync:|g' $sksconf_file
    fi
    if ! grep -q "membership_reload_interval:" $sksconf_file; then
        echo 'membership_reload_interval:     1' >> $sksconf_file
    else
        sed -i 's|#membership_reload_interval:.*|membership_reload_interval:     1|g' $sksconf_file
        sed -i 's|membership_reload_interval:.*|membership_reload_interval:     1|g' $sksconf_file
    fi
    if ! grep -q "max_matches:" $sksconf_file; then
        echo 'max_matches: 50' >> $sksconf_file
    else
        sed -i 's|#max_matches:.*|max_matches: 50|g' $sksconf_file
        sed -i 's|max_matches:.*|max_matches: 50|g' $sksconf_file
    fi
    if ! grep -q "stat_hour:" $sksconf_file; then
        echo "stat_hour: $((1 + RANDOM % 8))" >> $sksconf_file
    else
        sed -i "s|#stat_hour:.*|stat_hour: $((1 + RANDOM % 8))|g" $sksconf_file
        sed -i "s|stat_hour:.*|stat_hour: $((1 + RANDOM % 8))|g" $sksconf_file
    fi
    if ! grep -q "disable_log_diffs:" $sksconf_file; then
        echo "disable_log_diffs:" >> $sksconf_file
    else
        sed -i "s|#disable_log_diffs:.*|disable_log_diffs:|g" $sksconf_file
        sed -i "s|disable_log_diffs:.*|disable_log_diffs:|g" $sksconf_file
    fi
    if ! grep -q "debuglevel:" $sksconf_file; then
        echo "debuglevel: 0" >> $sksconf_file
    else
        sed -i "s|#debuglevel:.*|debuglevel: 0|g" $sksconf_file
        sed -i "s|debuglevel:.*|debuglevel: 0|g" $sksconf_file
    fi
    chown debian-sks: $sksconf_file
    if ! grep -q "hidden_service_sks" /etc/tor/torrc; then
        echo 'HiddenServiceDir /var/lib/tor/hidden_service_sks/' >> /etc/tor/torrc
        echo "HiddenServicePort 11370 127.0.0.1:11370" >> /etc/tor/torrc
        echo "HiddenServicePort 11373 127.0.0.1:11371" >> /etc/tor/torrc
        echo "HiddenServicePort 11372 127.0.0.1:11372" >> /etc/tor/torrc
        echo $'Added onion site for sks'
    fi
    onion_update
    wait_for_onion_service 'sks'
    if [ ! -f /var/lib/tor/hidden_service_sks/hostname ]; then
        echo $'sks onion site hostname not found'
        exit 8352982
    fi
    SKS_ONION_HOSTNAME=$(cat /var/lib/tor/hidden_service_sks/hostname)
    KEYSERVER_ONION_HOSTNAME=$(add_onion_service keyserver 80 ${KEYSERVER_ONION_PORT})
    keyserver_nginx_site=/etc/nginx/sites-available/$KEYSERVER_DOMAIN_NAME
    if [[ $ONION_ONLY == "no" ]]; then
        # NOTE: without http active on port 80 the keyserver doesn't work
        #       from the commandline
        echo 'server {' > $keyserver_nginx_site
        echo '  listen 80;' >> $keyserver_nginx_site
        echo '  listen 0.0.0.0:11371;' >> $keyserver_nginx_site
        echo '  listen [::]:80;' >> $keyserver_nginx_site
        echo "  server_name $KEYSERVER_DOMAIN_NAME;" >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  # Logs' >> $keyserver_nginx_site
        echo '  access_log /dev/null;' >> $keyserver_nginx_site
        echo '  error_log /dev/null;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  # Root' >> $keyserver_nginx_site
        echo "  root /var/www/$KEYSERVER_DOMAIN_NAME/htdocs;" >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  rewrite ^/stats /pks/lookup?op=stats;' >> $keyserver_nginx_site
        echo '  rewrite ^/s/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/search/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/g/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/get/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/d/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/download/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  location / {' >> $keyserver_nginx_site
        function_check nginx_limits
        nginx_limits $KEYSERVER_DOMAIN_NAME '128k'
        echo '  }' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  location /pks {' >> $keyserver_nginx_site
        echo '    proxy_pass         http://127.0.0.1:11373;' >> $keyserver_nginx_site
        echo '    proxy_pass_header  Server;' >> $keyserver_nginx_site
        echo "    add_header         Via \"1.1 $KEYSERVER_DOMAIN_NAME:11371 (nginx)\";" >> $keyserver_nginx_site
        echo '    proxy_ignore_client_abort on;' >> $keyserver_nginx_site
        echo '    client_max_body_size 8m;' >> $keyserver_nginx_site
        echo '    client_body_buffer_size 128k;' >> $keyserver_nginx_site
        echo '  }' >> $keyserver_nginx_site
        echo '}' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo 'server {' >> $keyserver_nginx_site
        echo '  listen 443 ssl;' >> $keyserver_nginx_site
        echo '  listen 0.0.0.0:11372 ssl;' >> $keyserver_nginx_site
        echo '  listen [::]:443 ssl;' >> $keyserver_nginx_site
        echo "  server_name $KEYSERVER_DOMAIN_NAME;" >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  error_page 404 /404.html;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  location ~ (.git|LICENSE|readme.md) {' >> $keyserver_nginx_site
        echo '    deny all;' >> $keyserver_nginx_site
        echo '    return 404;' >> $keyserver_nginx_site
        echo '  }' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  # Security' >> $keyserver_nginx_site
        function_check nginx_ssl
        nginx_ssl $KEYSERVER_DOMAIN_NAME
        function_check nginx_disable_sniffing
        nginx_disable_sniffing $KEYSERVER_DOMAIN_NAME
        echo '  add_header Strict-Transport-Security max-age=15768000;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  # Logs' >> $keyserver_nginx_site
        echo '  access_log /dev/null;' >> $keyserver_nginx_site
        echo '  error_log /dev/null;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  # Root' >> $keyserver_nginx_site
        echo "  root /var/www/$KEYSERVER_DOMAIN_NAME/htdocs;" >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  rewrite ^/stats /pks/lookup?op=stats;' >> $keyserver_nginx_site
        echo '  rewrite ^/s/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/search/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/g/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/get/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/d/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
        echo '  rewrite ^/download/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  location / {' >> $keyserver_nginx_site
        function_check nginx_limits
        nginx_limits $KEYSERVER_DOMAIN_NAME '128k'
        echo '  }' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
        echo '  location /pks {' >> $keyserver_nginx_site
        echo "    proxy_pass         http://127.0.0.1:11373;" >> $keyserver_nginx_site
        echo '    proxy_pass_header  Server;' >> $keyserver_nginx_site
        echo "    add_header         Via \"1.1 $KEYSERVER_DOMAIN_NAME:11372 (nginx)\";" >> $keyserver_nginx_site
        echo '    proxy_ignore_client_abort on;' >> $keyserver_nginx_site
        echo '    client_max_body_size 8m;' >> $keyserver_nginx_site
        echo '    client_body_buffer_size 128k;' >> $keyserver_nginx_site
        echo '  }' >> $keyserver_nginx_site
        echo '}' >> $keyserver_nginx_site
        echo '' >> $keyserver_nginx_site
    else
        echo -n '' > $keyserver_nginx_site
    fi
    echo 'server {' >> $keyserver_nginx_site
    echo "  listen 127.0.0.1:$KEYSERVER_ONION_PORT default_server;" >> $keyserver_nginx_site
    echo "  server_name $KEYSERVER_ONION_HOSTNAME;" >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  error_page 404 /404.html;' >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  location ~ (.git|LICENSE|readme.md) {' >> $keyserver_nginx_site
    echo '    deny all;' >> $keyserver_nginx_site
    echo '    return 404;' >> $keyserver_nginx_site
    echo '  }' >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    function_check nginx_disable_sniffing
    nginx_disable_sniffing $KEYSERVER_DOMAIN_NAME
    echo '' >> $keyserver_nginx_site
    echo '  # Logs' >> $keyserver_nginx_site
    echo '  access_log /dev/null;' >> $keyserver_nginx_site
    echo '  error_log /dev/null;' >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  # Root' >> $keyserver_nginx_site
    echo "  root /var/www/$KEYSERVER_DOMAIN_NAME/mail;" >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  rewrite ^/stats /pks/lookup?op=stats;' >> $keyserver_nginx_site
    echo '  rewrite ^/s/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
    echo '  rewrite ^/search/(.*) /pks/lookup?search=$1;' >> $keyserver_nginx_site
    echo '  rewrite ^/g/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
    echo '  rewrite ^/get/(.*) /pks/lookup?op=get&search=$1;' >> $keyserver_nginx_site
    echo '  rewrite ^/d/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
    echo '  rewrite ^/download/(.*) /pks/lookup?op=get&options=mr&search=$1;' >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  location / {' >> $keyserver_nginx_site
    function_check nginx_limits
    nginx_limits $KEYSERVER_DOMAIN_NAME '128k'
    echo '  }' >> $keyserver_nginx_site
    echo '' >> $keyserver_nginx_site
    echo '  location /pks {' >> $keyserver_nginx_site
    echo "    proxy_pass         http://127.0.0.1:11373;" >> $keyserver_nginx_site
    echo '    proxy_pass_header  Server;' >> $keyserver_nginx_site
    echo "    add_header         Via \"1.1 $KEYSERVER_DOMAIN_NAME:$KEYSERVER_ONION_PORT (nginx)\";" >> $keyserver_nginx_site
    echo '    proxy_ignore_client_abort on;' >> $keyserver_nginx_site
    echo '    client_max_body_size 8m;' >> $keyserver_nginx_site
    echo '    client_body_buffer_size 128k;' >> $keyserver_nginx_site
    echo '  }' >> $keyserver_nginx_site
    echo '}' >> $keyserver_nginx_site
    function_check create_site_certificate
    if [ ! -f /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.pem ]; then
        create_site_certificate $KEYSERVER_DOMAIN_NAME 'yes'
    fi
    if [ -f /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.crt ]; then
        mv /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.crt /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.pem
    fi
    if [ -f /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.pem ]; then
        chown root:root /etc/ssl/certs/${KEYSERVER_DOMAIN_NAME}.pem
        sed -i "s|.crt|.pem|g" /etc/nginx/sites-available/${KEYSERVER_DOMAIN_NAME}
    fi
    if [ -f /etc/ssl/private/${KEYSERVER_DOMAIN_NAME}.key ]; then
        chown root:root /etc/ssl/private/${KEYSERVER_DOMAIN_NAME}.key
    fi
    chown -R www-data:www-data /var/www/$KEYSERVER_DOMAIN_NAME/htdocs
    function_check nginx_ensite
    nginx_ensite $KEYSERVER_DOMAIN_NAME
    configure_firewall_for_keyserver
    # remove membership file - don't try to sync with other keyservers
    if [ -f /etc/sks/membership ]; then
        rm /etc/sks/membership
    fi
    if ! grep -q "pgp-public-keys" /etc/aliases; then
        echo 'pgp-public-keys:      "|/usr/lib/sks/sks_add_mail /etc/sks"' >> /etc/aliases
    fi
    chown -Rc debian-sks: /etc/sks/mailsync
    systemctl enable sks
    systemctl restart sks
    systemctl restart nginx
    set_completion_param "keyserver domain" "$KEYSERVER_DOMAIN_NAME"
    set_completion_param "keyserver onion domain" "$KEYSERVER_ONION_HOSTNAME"
    set_completion_param "sks onion domain" "$SKS_ONION_HOSTNAME"
    keyserver_watchdog
    APP_INSTALLED=1
}
# NOTE: deliberately no exit 0
 |