Skip to main content

Bash Script Installation on Debian

Based on the Manual Installation steps, I have created a simple bash script to automate the BookStack with LEMP stack install.

Copy the following code into a bash file, and run the script with sudo.

As of 2024-04-28, this script has been tested to run sucessfully on Debian 12.

#!/bin/bash

#Simple script to install BookStack with LEMP Stack 
#Script follows the manual Installation method documented at https://www.bookstackapp.com/docs/admin/installation/#manual

#Get all the variables for the configs 
echo -e "This is a simple script for installing Bookstack with MariaDB database, NGINX webserver, and PHP 8.3. \n"

#Modify the following to suit your prferences
php_version=8.3
bookstack_db_username=bookstack
bookstack_db_name=bookstack

#Prompt for DB user password
while true
do
    read -sp "Enter a password for the new Bookstack database user:" db_user_pass1
    echo ""
    read -sp "Enter the password again:" db_user_pass2
    echo ""
    if [ "$db_user_pass1" == "$db_user_pass2" ]
    then
        break
    else
        echo "Password did not match. Try again."
    fi
done

#Prompt for DB root user password
while true
do
    read -sp "Enter a new MariaDB Root User password:" db_root_pass1
    echo ""
    read -sp "Enter the password again:" db_root_pass2
    echo ""
    if [ "$db_root_pass1" == "$db_root_pass2" ]
    then
        break
    else
        echo "Password did not match. Try again."
    fi
done

while true
do
    read -p "Enter your Bookstack Server's FQDN:" server_FQDN1
    echo ""
    read -p "Enter the FQDN again:" server_FQDN2
    echo ""
    if [ "$server_FQDN1" == "$server_FQDN2" ]
    then
        break
    else
        echo "FQDN did not match. Try again."
    fi
done

# Ask user if they want to define SSL cert location
read -p "Do you want to use SSL cert for NGINX? (y/n): " define_ssl_cert

if [ "$define_ssl_cert" == "y" ]
then
    # Prompt for SSL cert and key location
    while true
    do
        read -p "Enter the location of your SSL Cert (example: /etc/ssl/cert/cert_name): " ssl_cert_path
        read -p "Enter the location of your SSL Key (example: /etc/ssl/private/key_name): " ssl_key_path

        # Check if the provided SSL cert and key location exists
        if [ -f "$ssl_cert_path" ] && [ -f "$ssl_key_path" ]
        then
            break
        else
            echo "Invalid SSL Cert or Key location. Try again."
        fi
    done
else
    echo "Skipping SSL Cert configuration..."
fi


#Install system utilities
sudo apt install -y gnupg git unzip curl 

#Install Nginx
sudo apt install -y nginx

#Start nginx on boot
sudo systemctl enable nginx

#Install MariaDB
sudo apt install -y mariadb-server mariadb-client

#start mariadb on boot
sudo systemctl enable mariadb

#Add PHP Sury Repo
curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
sudo apt update

#install BookStack required PHP Packages
sudo apt install -y php$php_version php$php_version-{curl,mbstring,ldap,xml,zip,gd,mysql,fpm}

#start php8.1-fpm on boot
sudo systemctl enable php$php_version-fpm

#Create local BookStack Database
sudo mysql -u root --execute="CREATE DATABASE $bookstack_db_name;"
sudo mysql -u root --execute="CREATE USER '$bookstack_db_username'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$db_user_pass2');"
sudo mysql -u root --execute="GRANT ALL ON $bookstack_db_name.* TO '$bookstack_db_username'@'localhost';FLUSH PRIVILEGES;"

#Perform mysql_secure_installation queries
#Drop the anonymous users
sudo mysql -u root -e "DELETE FROM mysql.user WHERE User=''"
#Drop the demo database
sudo mysql -u root -e "DROP DATABASE IF EXISTS test"

#Make sure that NOBODY can access the DB without a password. Any subsequent tries to run queries this way will get access denied because lack of usr/pwd param'
sudo mysql -u root --execute="SET PASSWORD FOR 'root'@'localhost' = PASSWORD('$db_root_pass2')"
sudo mysql -u root --execute="FLUSH PRIVILEGES"


#Install Composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
    >&2 echo 'ERROR: Invalid installer checksum'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php
php -r "unlink('composer-setup.php');"

sudo mv composer.phar /usr/local/bin/composer

#Install BookStack
cd /var/www/

sudo git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch

cd BookStack
sudo composer install --no-dev

sudo cp .env.example .env

#Set Database connections and other env detais
sudo sed -i "s/DB_DATABASE=database_database/DB_DATABASE=$bookstack_db_name/g" .env
sudo sed -i "s/DB_USERNAME=database_username/DB_USERNAME=$bookstack_db_username/g" .env
sudo sed -i "s/DB_PASSWORD=database_user_password/DB_PASSWORD=$db_user_pass2/g" .env
sed -i "s,APP_URL=https://example.com,APP_URL=https://$server_FQDN2,g" .env

#Make sure storage, bootstrap/cache & public/uploads folders are writable by the web server
sudo chown -R www-data:www-data storage bootstrap/cache public/uploads

#Generate unique application keys for encryption
sudo php artisan key:generate

#Update Database
sudo php artisan migrate

#Unlink the default NGINX config
sudo unlink /etc/nginx/sites-enabled/default

#Create blank NGINX Config
sudo touch /etc/nginx/sites-available/bookstack

#Create the NGINX config
if [ "$define_ssl_cert" == "y" ]
then
    sudo tee /etc/nginx/sites-available/bookstack > /dev/null <<EOF
    server {
        listen      443 ssl http2;
        server_name $server_FQDN2;

        #SSL Certs
        ssl_certificate $ssl_cert_path;
        ssl_certificate_key $ssl_key_path;
        
        #Disable NGINX current version reporting on error pages
        server_tokens off;

        #Force strong TLS
        ssl_protocols      TLSv1.3;
        ssl_prefer_server_ciphers   on;

        #Disable weak ciphers
        ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA HIGH !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";

        #Increase Upload Size
        client_max_body_size 12M;

        #Enable NGINX logging
        access_log /var/log/nginx/bookstack-access.log;
        error_log /var/log/nginx/bookstack-error.log;

        #Bookstack location
        root /var/www/BookStack/public;
        index index.php index.html;

        location / {
            try_files \$uri \$uri/ /index.php?\$query_string;
        }
  
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php$php_version-fpm.sock;
        }
    }
EOF
    echo "That's it! You can now access your Bookstack instance at https://$server_FQDN2."

else
    sudo tee /etc/nginx/sites-available/bookstack > /dev/null <<EOF
    server {
        listen      80;
        server_name $server_FQDN2;

        #Increase Upload Size
        client_max_body_size 12M;

        access_log /var/log/nginx/bookstack-access.log;
        error_log /var/log/nginx/bookstack-error.log;

        #Bookstack location
        root /var/www/BookStack/public;
        index index.php index.html;

        location / {
            try_files \$uri \$uri/ /index.php?\$query_string;
        }
  
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php$php_version-fpm.sock;
        }
    }
EOF
    echo "That's it! You can now access your Bookstack instance at https://$server_FQDN2."
fi

#link the NGINX config
sudo ln -s /etc/nginx/sites-available/bookstack /etc/nginx/sites-enabled/bookstack

#Restart NGINX
sudo systemctl restart nginx