Skip to content

Commit dfd4005

Browse files
committed
Changed output of ubuntu 22.04 script, added checks
- Added checks for existing apache/mysql usage before run. - Segmented script into functions and added custom output handling to capture core output into log file while showing simpler, pretty messages to the user. - Changed final output into a cleaner table.
1 parent 0e2200e commit dfd4005

File tree

1 file changed

+188
-91
lines changed

1 file changed

+188
-91
lines changed

scripts/installation-ubuntu-22.04.sh

Lines changed: 188 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,115 +4,172 @@ echo "This script installs a new BookStack instance on a fresh Ubuntu 22.04 serv
44
echo "This script does not ensure system security."
55
echo ""
66

7-
# Check we're running as root and exit if not
8-
if [[ $EUID -gt 0 ]]
9-
then
10-
>&2 echo "ERROR: This script must be ran with root/sudo privileges"
11-
exit 1
12-
fi
7+
# Generate a path for a log file to output into for debugging
8+
LOGPATH=$(realpath "bookstack_install_log_$(date +%s).log")
139

1410
# Get the current user running the script
1511
SCRIPT_USER="${SUDO_USER:-$USER}"
1612

1713
# Get the current machine IP address
1814
CURRENT_IP=$(ip addr | grep 'state UP' -A4 | grep 'inet ' | awk '{print $2}' | cut -f1 -d'/')
1915

20-
# Fetch domain to use from first provided parameter,
21-
# Otherwise request the user to input their domain
16+
# Generate a password for the database
17+
DB_PASS="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13)"
18+
19+
# The directory to install BookStack into
20+
BOOKSTACK_DIR="/var/www/bookstack"
21+
22+
# Get the domain from the arguments (Requested later if not set)
2223
DOMAIN=$1
23-
if [ -z "$1" ]
24-
then
25-
echo ""
26-
echo "Enter the domain (or IP if not using a domain) you want to host BookStack on and press [ENTER]."
27-
echo "Examples: my-site.com or docs.my-site.com or ${CURRENT_IP}"
28-
read -r DOMAIN
29-
fi
30-
31-
# Ensure a domain was provided otherwise display
32-
# an error message and stop the script
33-
if [ -z "$DOMAIN" ]
34-
then
35-
>&2 echo 'ERROR: A domain must be provided to run this script'
24+
25+
# Prevent interactive prompts in applications
26+
export DEBIAN_FRONTEND=noninteractive
27+
28+
# Echo out an error message to the command line and exit the program
29+
# Also logs the message to the log file
30+
function error_out() {
31+
echo "ERROR: $1" | tee -a "$LOGPATH" 1>&2
3632
exit 1
37-
fi
33+
}
34+
35+
# Echo out an information message to both the command line and log file
36+
function info_msg() {
37+
echo "$1" | tee -a "$LOGPATH"
38+
}
39+
40+
# Run some checks before installation to help prevent messing up an existing
41+
# web-server setup.
42+
function run_pre_install_checks() {
43+
# Check we're running as root and exit if not
44+
if [[ $EUID -gt 0 ]]
45+
then
46+
error_out "This script must be ran with root/sudo privileges"
47+
fi
48+
49+
# Check if Apache appears to be installed and exit if so
50+
if [ -d "/etc/apache2/sites-enabled" ]
51+
then
52+
error_out "This script is intended for a fresh server install, existing apache config found, aborting install"
53+
fi
54+
55+
# Check if MySQL appears to be installed and exit if so
56+
if [ -d "/var/lib/mysql" ]
57+
then
58+
error_out "This script is intended for a fresh server install, existing MySQL data found, aborting install"
59+
fi
60+
}
61+
62+
# Fetch domain to use from first provided parameter,
63+
# Otherwise request the user to input their domain
64+
function run_prompt_for_domain_if_required() {
65+
if [ -z "$DOMAIN" ]
66+
then
67+
info_msg ""
68+
info_msg "Enter the domain (or IP if not using a domain) you want to host BookStack on and press [ENTER]."
69+
info_msg "Examples: my-site.com or docs.my-site.com or ${CURRENT_IP}"
70+
read -r DOMAIN
71+
fi
72+
73+
# Error out if no domain was provided
74+
if [ -z "$DOMAIN" ]
75+
then
76+
error_out "A domain must be provided to run this script"
77+
fi
78+
}
3879

3980
# Install core system packages
40-
export DEBIAN_FRONTEND=noninteractive
41-
apt update
42-
apt install -y git unzip apache2 php8.1 curl php8.1-curl php8.1-mbstring php8.1-ldap \
43-
php8.1-xml php8.1-zip php8.1-gd php8.1-mysql mysql-server-8.0 libapache2-mod-php8.1
81+
function run_package_installs() {
82+
apt update
83+
apt install -y git unzip apache2 php8.1 curl php8.1-curl php8.1-mbstring php8.1-ldap \
84+
php8.1-xml php8.1-zip php8.1-gd php8.1-mysql mysql-server-8.0 libapache2-mod-php8.1
85+
}
4486

4587
# Set up database
46-
DB_PASS="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13)"
47-
mysql -u root --execute="CREATE DATABASE bookstack;"
48-
mysql -u root --execute="CREATE USER 'bookstack'@'localhost' IDENTIFIED WITH mysql_native_password BY '$DB_PASS';"
49-
mysql -u root --execute="GRANT ALL ON bookstack.* TO 'bookstack'@'localhost';FLUSH PRIVILEGES;"
88+
function run_database_setup() {
89+
mysql -u root --execute="CREATE DATABASE bookstack;"
90+
mysql -u root --execute="CREATE USER 'bookstack'@'localhost' IDENTIFIED WITH mysql_native_password BY '$DB_PASS';"
91+
mysql -u root --execute="GRANT ALL ON bookstack.* TO 'bookstack'@'localhost';FLUSH PRIVILEGES;"
92+
}
5093

5194
# Download BookStack
52-
cd /var/www || exit
53-
git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch bookstack
54-
BOOKSTACK_DIR="/var/www/bookstack"
55-
56-
# Move into the BookStack install directory
57-
cd $BOOKSTACK_DIR || exit
95+
function run_bookstack_download() {
96+
cd /var/www || exit
97+
git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch bookstack
98+
}
5899

59100
# Install composer
60-
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
61-
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
62-
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
101+
function run_install_composer() {
102+
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
103+
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
104+
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
63105

64-
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
65-
then
66-
>&2 echo 'ERROR: Invalid composer installer checksum'
67-
rm composer-setup.php
68-
exit 1
69-
fi
106+
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
107+
then
108+
>&2 echo 'ERROR: Invalid composer installer checksum'
109+
rm composer-setup.php
110+
exit 1
111+
fi
70112

71-
php composer-setup.php --quiet
72-
rm composer-setup.php
113+
php composer-setup.php --quiet
114+
rm composer-setup.php
73115

74-
# Move composer to global installation
75-
mv composer.phar /usr/local/bin/composer
116+
# Move composer to global installation
117+
mv composer.phar /usr/local/bin/composer
118+
}
76119

77120
# Install BookStack composer dependencies
78-
export COMPOSER_ALLOW_SUPERUSER=1
79-
php /usr/local/bin/composer install --no-dev --no-plugins
121+
function run_install_bookstack_composer_deps() {
122+
cd "$BOOKSTACK_DIR" || exit
123+
export COMPOSER_ALLOW_SUPERUSER=1
124+
php /usr/local/bin/composer install --no-dev --no-plugins
125+
}
80126

81127
# Copy and update BookStack environment variables
82-
cp .env.example .env
83-
sed -i.bak "s@APP_URL=.*\$@APP_URL=http://$DOMAIN@" .env
84-
sed -i.bak 's/DB_DATABASE=.*$/DB_DATABASE=bookstack/' .env
85-
sed -i.bak 's/DB_USERNAME=.*$/DB_USERNAME=bookstack/' .env
86-
sed -i.bak "s/DB_PASSWORD=.*\$/DB_PASSWORD=$DB_PASS/" .env
87-
88-
# Generate the application key
89-
php artisan key:generate --no-interaction --force
90-
# Migrate the databases
91-
php artisan migrate --no-interaction --force
128+
function run_update_bookstack_env() {
129+
cd "$BOOKSTACK_DIR" || exit
130+
cp .env.example .env
131+
sed -i.bak "s@APP_URL=.*\$@APP_URL=http://$DOMAIN@" .env
132+
sed -i.bak 's/DB_DATABASE=.*$/DB_DATABASE=bookstack/' .env
133+
sed -i.bak 's/DB_USERNAME=.*$/DB_USERNAME=bookstack/' .env
134+
sed -i.bak "s/DB_PASSWORD=.*\$/DB_PASSWORD=$DB_PASS/" .env
135+
# Generate the application key
136+
php artisan key:generate --no-interaction --force
137+
}
138+
139+
# Run the BookStack database migrations for the first time
140+
function run_bookstack_database_migrations() {
141+
cd "$BOOKSTACK_DIR" || exit
142+
php artisan migrate --no-interaction --force
143+
}
92144

93145
# Set file and folder permissions
94146
# Sets current user as owner user and www-data as owner group then
95147
# provides group write access only to required directories.
96148
# Hides the `.env` file so it's not visible to other users on the system.
97-
chown -R "$SCRIPT_USER":www-data ./
98-
chmod -R 755 ./
99-
chmod -R 775 bootstrap/cache public/uploads storage
100-
chmod 740 .env
101-
102-
# Tell git to ignore permission changes
103-
git config core.fileMode false
104-
105-
# Enable required apache modules
106-
a2enmod rewrite
107-
a2enmod php8.1
108-
109-
# Set-up the required BookStack apache config
110-
cat >/etc/apache2/sites-available/bookstack.conf <<EOL
149+
function run_set_application_file_permissions() {
150+
cd "$BOOKSTACK_DIR" || exit
151+
chown -R "$SCRIPT_USER":www-data ./
152+
chmod -R 755 ./
153+
chmod -R 775 bootstrap/cache public/uploads storage
154+
chmod 740 .env
155+
156+
# Tell git to ignore permission changes
157+
git config core.fileMode false
158+
}
159+
160+
# Setup apache with the needed modules and config
161+
function run_configure_apache() {
162+
# Enable required apache modules
163+
a2enmod rewrite
164+
a2enmod php8.1
165+
166+
# Set-up the required BookStack apache config
167+
cat >/etc/apache2/sites-available/bookstack.conf <<EOL
111168
<VirtualHost *:80>
112-
ServerName ${DOMAIN}
169+
ServerName ${DOMAIN}
113170
114-
ServerAdmin webmaster@localhost
115-
DocumentRoot /var/www/bookstack/public/
171+
ServerAdmin webmaster@localhost
172+
DocumentRoot /var/www/bookstack/public/
116173
117174
<Directory /var/www/bookstack/public/>
118175
Options -Indexes +FollowSymLinks
@@ -141,22 +198,62 @@ cat >/etc/apache2/sites-available/bookstack.conf <<EOL
141198
</IfModule>
142199
</Directory>
143200
144-
ErrorLog \${APACHE_LOG_DIR}/error.log
145-
CustomLog \${APACHE_LOG_DIR}/access.log combined
201+
ErrorLog \${APACHE_LOG_DIR}/error.log
202+
CustomLog \${APACHE_LOG_DIR}/access.log combined
146203
147204
</VirtualHost>
148205
EOL
149206

150-
# Disable the default apache site and enable BookStack
151-
a2dissite 000-default.conf
152-
a2ensite bookstack.conf
207+
# Disable the default apache site and enable BookStack
208+
a2dissite 000-default.conf
209+
a2ensite bookstack.conf
153210

154-
# Restart apache to load new config
155-
systemctl restart apache2
211+
# Restart apache to load new config
212+
systemctl restart apache2
213+
}
156214

157-
echo ""
158-
echo "Setup Finished, Your BookStack instance should now be installed."
159-
echo "You can login with the email 'admin@admin.com' and password of 'password'"
160-
echo "MySQL was installed without a root password, It is recommended that you set a root MySQL password."
161-
echo ""
162-
echo "You can access your BookStack instance at: http://$CURRENT_IP/ or http://$DOMAIN/"
215+
info_msg "This script logs full output to $LOGPATH which may help upon issues."
216+
sleep 1
217+
218+
run_pre_install_checks
219+
run_prompt_for_domain_if_required
220+
info_msg ""
221+
info_msg "Installing using the domain/IP \"$DOMAIN\""
222+
info_msg ""
223+
sleep 1
224+
225+
info_msg "[1/9] Installing required system packages... (This may take several minutes)"
226+
run_package_installs >> "$LOGPATH" 2>&1
227+
228+
info_msg "[2/9] Preparing MySQL database..."
229+
run_database_setup >> "$LOGPATH" 2>&1
230+
231+
info_msg "[3/9] Downloading BookStack to ${BOOKSTACK_DIR}..."
232+
run_bookstack_download >> "$LOGPATH" 2>&1
233+
234+
info_msg "[4/9] Installing Composer (PHP dependency manager)..."
235+
run_install_composer >> "$LOGPATH" 2>&1
236+
237+
info_msg "[5/9] Installing PHP dependencies using composer..."
238+
run_install_bookstack_composer_deps >> "$LOGPATH" 2>&1
239+
240+
info_msg "[6/9] Creating and populating BookStack .env file..."
241+
run_update_bookstack_env >> "$LOGPATH" 2>&1
242+
243+
info_msg "[7/9] Running initial BookStack database migrations..."
244+
run_bookstack_database_migrations >> "$LOGPATH" 2>&1
245+
246+
info_msg "[8/9] Setting BookStack file & folder permissions..."
247+
run_set_application_file_permissions >> "$LOGPATH" 2>&1
248+
249+
info_msg "[9/9] Configuring apache server..."
250+
run_configure_apache >> "$LOGPATH" 2>&1
251+
252+
info_msg "----------------------------------------------------------------"
253+
info_msg "Setup finished, your BookStack instance should now be installed!"
254+
info_msg "Default login email: admin@admin.com"
255+
info_msg "Default login password: password"
256+
info_msg "Access URL: http://$CURRENT_IP/ or http://$DOMAIN/"
257+
info_msg "BookStack Install Directory: $BOOKSTACK_DIR"
258+
info_msg "Install Script Log: $LOGPATH"
259+
info_msg "---------------------------------------------------------------"

0 commit comments

Comments
 (0)