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