BookStack is an open source documentation platform built on Laravel that organizes content into shelves, books, chapters and pages, with a WYSIWYG and Markdown editor, full-text search and role-based permissions. In this tutorial you will install BookStack on Ubuntu 24.04 from its official Git release branch, serve it with Nginx and PHP-FPM 8.3 over HTTPS, configure outgoing email, and set up a clean update procedure and nightly backups.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 1 GB of RAM (2 GB recommended) and 10 GB of free disk space.
- A non-root user with
sudoprivileges. The commands use$USER, so run them as that user. - A domain or subdomain (this guide uses
your_domain) with a DNSArecord pointing toyour_server_ip. - Ports 80 and 443 open to the internet.
Step 1 - Installing Nginx, PHP and MariaDB
BookStack requires PHP 8.2 or newer with a handful of extensions, a MySQL-compatible database and Composer to install its PHP dependencies. Ubuntu 24.04 provides all of them:
sudo apt update
sudo apt install nginx mariadb-server git unzip composer php-fpm php-cli php-mysql php-xml php-mbstring php-curl php-gd php-zip
Check the PHP and Composer versions:
php -v
composer --version
PHP 8.3.6 (cli) (built: ...) (NTS)
...
Composer version 2.7.1 ...
Open the firewall for SSH and web traffic:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Step 2 - Creating the database
MariaDB on Ubuntu authenticates root through the Unix socket, so sudo mariadb opens a shell without a password. Run the hardening script first (answer n to switching to unix_socket authentication, since it is already in use, and Y to the rest):
sudo mariadb-secure-installation
Open the MariaDB shell:
sudo mariadb
Create a database and a user for BookStack, replacing your_db_password with a strong password:
CREATE DATABASE bookstack CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'bookstack'@'localhost' IDENTIFIED BY 'your_db_password';
GRANT ALL PRIVILEGES ON bookstack.* TO 'bookstack'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Confirm the account works:
mariadb -u bookstack -p -e 'SHOW DATABASES;'
+--------------------+
| Database |
+--------------------+
| bookstack |
| information_schema |
+--------------------+
Step 3 - Downloading BookStack
BookStack publishes every stable version on the release branch of its repository, which also makes updates a simple git pull. Create the application directory owned by your user, with the www-data group so PHP-FPM can read it:
sudo install -d -o "$USER" -g www-data /var/www/bookstack
git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch /var/www/bookstack
Install the PHP dependencies. --no-dev skips testing tools that are not needed in production:
cd /var/www/bookstack
composer install --no-dev
...
Generating optimized autoload files
...
Step 4 - Configuring the environment file
BookStack reads its settings from .env. Create it from the example:
cp .env.example .env
nano .env
Set the public URL and the database credentials from Step 2. Leave the other lines as they are for now:
APP_URL=https://your_domain
DB_HOST=localhost
DB_DATABASE=bookstack
DB_USERNAME=bookstack
DB_PASSWORD=your_db_password
APP_URL must match the address users type in the browser exactly, including https:// and without a trailing slash, otherwise styles and links break.
Generate the application key, which encrypts sessions and stored secrets. The --force flag is needed because BookStack runs in production mode:
php artisan key:generate --force
INFO Application key set successfully.
Step 5 - Setting permissions and creating the schema
The code stays owned by your user and is only readable by PHP-FPM. BookStack needs write access to three directories: storage (logs, cache, sessions, attachments), bootstrap/cache and public/uploads (images). The .env file holds the database password, so only your user and the www-data group can read it:
sudo chmod -R 755 /var/www/bookstack
sudo chmod -R 775 /var/www/bookstack/storage /var/www/bookstack/bootstrap/cache /var/www/bookstack/public/uploads
sudo chmod 640 /var/www/bookstack/.env
Run the database migrations as www-data, so any files they create in storage belong to the web server:
cd /var/www/bookstack
sudo -u www-data php artisan migrate --force
INFO Preparing database.
...
INFO Running migrations.
...
Step 6 - Configuring Nginx and HTTPS
Allow larger uploads in PHP-FPM with a small override file:
sudo nano /etc/php/8.3/fpm/conf.d/99-bookstack.ini
upload_max_filesize = 50M
post_max_size = 50M
memory_limit = 256M
Restart PHP-FPM:
sudo systemctl restart php8.3-fpm
Create the Nginx server block. The document root is the public directory, so the rest of the code, including .env, is never reachable over HTTP:
sudo nano /etc/nginx/sites-available/bookstack
server {
listen 80;
listen [::]:80;
server_name your_domain;
root /var/www/bookstack/public;
index index.php;
client_max_body_size 50m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
Enable the site, remove the default one and reload Nginx:
sudo ln -s /etc/nginx/sites-available/bookstack /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Request a Let's Encrypt certificate. Certbot adds the HTTPS listener and a redirect from HTTP:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your_domain
sudo certbot renew --dry-run
Check that the login page is served over HTTPS:
curl -sI https://your_domain/login | head -n 1
HTTP/2 200
Step 7 - Securing the admin account
The migrations create a default administrator with the email [email protected] and the password password. Log in at https://your_domain with those credentials, open the user menu at the top right, choose My Account (or Edit Profile), and change both the email address and the password immediately.
Then review Settings > Features & Security. For an internal knowledge base, keep Allow public access disabled and decide whether people may register themselves or only be invited by an administrator from Settings > Users.
Step 8 - Configuring outgoing email
BookStack sends emails for user invitations, password resets and notifications. Open .env again:
nano /var/www/bookstack/.env
Replace the MAIL_ lines with your SMTP provider's details:
MAIL_DRIVER=smtp
MAIL_FROM=bookstack@your_domain
MAIL_FROM_NAME="BookStack"
MAIL_HOST=smtp.your_provider.com
MAIL_PORT=587
MAIL_USERNAME=your_smtp_user
MAIL_PASSWORD=your_smtp_password
MAIL_ENCRYPTION=null
On port 587, STARTTLS is negotiated automatically when the server supports it. If your provider uses implicit TLS on port 465, set MAIL_PORT=465 and MAIL_ENCRYPTION=tls.
Clear the cached configuration so BookStack picks up the change:
cd /var/www/bookstack
sudo -u www-data php artisan config:clear
Go to Settings > Maintenance and click Send Test Email. The message is delivered to the email address of your account.
Step 9 - Updating BookStack
New releases are published on the release branch. To update, pull the latest code, refresh dependencies, run migrations and clear the caches. Take a backup first (Step 10):
cd /var/www/bookstack
git pull origin release
composer install --no-dev
sudo -u www-data php artisan migrate --force
sudo -u www-data php artisan cache:clear
sudo -u www-data php artisan config:clear
sudo -u www-data php artisan view:clear
The installed version appears at the bottom of Settings. Read the release notes on the BookStack blog before each update, since some versions include manual steps.
Step 10 - Scheduling backups
A BookStack backup needs the database, the .env file, uploaded images in public/uploads, attachments in storage/uploads and any custom theme in themes. Create a backup script:
sudo nano /usr/local/sbin/bookstack-backup
#!/usr/bin/env bash
set -euo pipefail
umask 077
APP_DIR=/var/www/bookstack
BACKUP_DIR=/var/backups/bookstack
STAMP=$(date +%F-%H%M)
mkdir -p "$BACKUP_DIR"
# Runs as root, so MariaDB authenticates through the Unix socket
mariadb-dump --single-transaction --default-character-set=utf8mb4 bookstack \
| gzip > "$BACKUP_DIR/bookstack-db-$STAMP.sql.gz"
tar -czf "$BACKUP_DIR/bookstack-files-$STAMP.tar.gz" -C "$APP_DIR" \
.env public/uploads storage/uploads themes
find "$BACKUP_DIR" -type f -mtime +14 -delete
Make it executable, run it and list the result:
sudo chmod 700 /usr/local/sbin/bookstack-backup
sudo /usr/local/sbin/bookstack-backup
sudo ls -lh /var/backups/bookstack
-rw------- 1 root root 240K Sep 25 12:10 bookstack-db-2026-09-25-1210.sql.gz
-rw------- 1 root root 3.4M Sep 25 12:10 bookstack-files-2026-09-25-1210.tar.gz
Schedule it every night:
echo '45 2 * * * root /usr/local/sbin/bookstack-backup' | sudo tee /etc/cron.d/bookstack-backup
To restore on a fresh install, import the SQL dump into the new database, extract the files archive into /var/www/bookstack, and run sudo -u www-data php artisan migrate --force. Keep a copy of the backups off the server.
Troubleshooting
- The page loads without styles or links point to the wrong host:
APP_URLin.envdoes not match the URL in the browser. Fix it, then runsudo -u www-data php artisan config:clear. - HTTP 500 after installation or an update: check
/var/www/bookstack/storage/logs/laravel.log. "Permission denied" errors mean thechmod 775from Step 5 needs to be run again onstorage,bootstrap/cacheandpublic/uploads. - Image uploads fail for large files: raise
upload_max_filesizeandpost_max_sizein/etc/php/8.3/fpm/conf.d/99-bookstack.iniandclient_max_body_sizein Nginx, then restart PHP-FPM and reload Nginx. git pullrefuses to run because of local changes: you edited a tracked file. Move customizations to thethemesdirectory, which BookStack provides for that purpose, and restore the file withgit checkout -- <file>.
Conclusion
BookStack is now running on Ubuntu 24.04 behind Nginx with HTTPS, with a secured admin account, working email, a repeatable update procedure and nightly backups. Next, create a shelf and your first book, define roles with per-book permissions under Settings > Roles, and, if your organization uses a directory service, connect BookStack to LDAP, SAML2 or OpenID Connect by following the authentication section of the official documentation.
