BookStack wiki running with Docker Compose, illustrated as books on a shelf
Self-hosting

BookStack Docker Compose: Team Wiki on Your Own VPS

Every team has that one person who knows how the backup script works, which provider holds the domain and what the office Wi-Fi password is. Everything runs smoothly until that person goes on holiday, changes jobs or simply forgets. The fix is boring and incredibly effective: write things down in a place everyone can search. In this tutorial we build exactly that place, a clean and fast wiki on your own VPS, using BookStack, MariaDB and Docker Compose, with HTTPS and working email so your colleagues can reset their own passwords without calling you at 11 PM.

BookStack is an open source documentation platform created by Dan Brown and released under the MIT license. The official site is bookstackapp.com and the code lives at github.com/BookStackApp/BookStack . It is written in PHP on top of the Laravel framework and stores its data in MySQL or MariaDB. By the end of this guide you will have it running, you will understand how it organizes content, you will know how to give each person the right level of access, and you will have SMTP configured for password resets and invitations.

What BookStack is and why it suits small teams

A wiki is a website where a group of people write and edit pages together, with links between pages, a history of every change and a search box. Wikipedia is the famous example, but most wikis are small and private: the internal manual of a company, the runbooks of a development team, a student’s course notes or the documentation of a hobbyist’s homelab.

Many wiki engines give you a blank canvas and let you build any structure you like. That sounds great and usually ends in chaos after six months. BookStack takes the opposite approach: it gives you a fixed, intuitive structure borrowed from a library, so new users understand where things go without any training. On top of that you get:

  • A friendly WYSIWYG editor (what you see is what you get, like a word processor), with an optional Markdown editor for people who prefer plain text.
  • Full text search across everything, plus tags you can filter on.
  • Revisions: every save is kept, so you can compare versions and restore an older one in two clicks.
  • Images, attachments and diagrams, including a built-in draw.io diagram editor.
  • Exports to PDF, HTML, plain text and Markdown, and in recent versions ZIP exports you can import into another BookStack instance.
  • Roles and permissions down to an individual page.
  • Multi-factor authentication (TOTP apps), plus LDAP, SAML2 and OpenID Connect if you already have a central login system.
  • A REST API for automation.

Why self-host it instead of using a SaaS wiki

Hosted wikis charge per user per month, and the bill grows every time you hire someone. A self-hosted BookStack costs you one small VPS no matter how many accounts you create. Your documentation also stays on a server you control, in a Romanian data center, which makes GDPR conversations much simpler when the wiki contains customer procedures or internal contact details.

Shelves, books, chapters and pages: how BookStack organizes content

Before installing anything, it helps to understand the four building blocks, because they influence how you will set up permissions later.

  • Page: the actual document, where you write text, paste screenshots and add tables. Everything else exists to organize pages.
  • Chapter: an optional group of pages inside a book, like a chapter in a printed manual.
  • Book: the main container. A book holds chapters and pages, and it is the level where you usually set permissions.
  • Shelf: a collection of books. Shelves are only for browsing and grouping, and the same book can sit on several shelves at once.

Here is how a small company might structure its wiki:

Shelf: Engineering
  Book: Server runbooks
    Chapter: Backups
      Page: Daily backup schedule
      Page: Restore the MariaDB database
    Chapter: Deployments
      Page: Release checklist
  Book: Onboarding for developers
    Page: Accounts you will need
Shelf: Office
  Book: HR and policies
    Page: Holiday requests

Two rules are worth remembering. First, chapters are optional: a page can live directly inside a book, so do not create chapters just for the sake of it. Second, permissions flow downward from a book to its chapters and pages, while shelves do not automatically pass their permissions to the books on them. We will come back to this in the roles section.

What you need

  • A DreamServer VPS with Debian 13 or Ubuntu 24.04, at least 1 vCPU, 1 GB of RAM and 10 GB of disk (2 GB of RAM is comfortable if you also run other things).
  • A sudo user and SSH access to the server.
  • A domain or subdomain whose DNS you can edit, for example wiki.yourcompany.ro.
  • An SMTP account for sending email: the credentials of a mailbox on your domain or a transactional email service.
  • About 30 minutes.

A note on virtualization: on a KVM VPS everything below works as written. In an unprivileged LXC container, Docker only runs if the container has nesting enabled, and firewall tools like ufw may not be able to load their kernel modules. If you are on one of our LXC plans and Docker refuses to start, ask support to enable nesting, or choose KVM for Docker workloads.

How the pieces fit together

Let us define a few terms first. A container is an isolated package that contains an application and everything it needs to run, sharing the host’s kernel but not its files or processes. An image is the read-only template a container is started from. A volume (here, a folder on the VPS mounted into the container) is where data that must survive restarts and upgrades is kept. A port is a numbered door on the server through which network traffic reaches a specific program: 80 for HTTP, 443 for HTTPS, 3306 for MariaDB. A reverse proxy is a web server that receives all visitors on ports 80 and 443, handles HTTPS certificates and forwards each request to the right application behind it.

Our stack has three containers, all described in a single docker-compose.yml file. Docker Compose is the tool that reads that file and starts, stops and updates the containers together. It also creates a private network where containers find each other by service name, so BookStack reaches the database simply at the address db.

BookStack on a single VPSDocker on your VPS (private network)Usersweb browserFirewall80, 443 onlyCaddyHTTPS + certsBookStackPHP app, port 80MariaDB 11.4not published./configuploads, .env./dbdatabase filesSMTP serverreset and invite emailsoutbound 587 / 465Only Caddy publishes portsto the internet.
Figure 1: visitors only ever talk to Caddy on ports 80 and 443. BookStack and MariaDB stay on Docker's private network, and BookStack sends email outward through your SMTP server.

About the images: the BookStack project does not publish an official Docker image. Its documentation lists community images, and the most widely used one is maintained by LinuxServer.io (lscr.io/linuxserver/bookstack), which is what we use. For the database we use the official mariadb:11.4 image (11.4 is a long term support series), and for the reverse proxy the official caddy:2 image, which obtains and renews Let’s Encrypt certificates automatically.

Installing BookStack with Docker Compose, step by step

The whole installation consists of seven steps. The figure below gives you the overview, and each numbered section that follows matches one box.

BookStack installation in 7 steps1Install Dockerengine + compose2Point DNSA record to VPS3Secretsthe .env file4Compose file+ Caddyfile5Start stackdocker compose up6First loginsecure the admin7Configure emailSMTP + test
Figure 2: the seven installation steps, numbered exactly like the Step 1 to Step 7 sections below. Steps 1 to 4 prepare the server, Step 5 and Step 6 bring the wiki online, Step 7 enables password resets.

Step 1: Install Docker on Debian or Ubuntu

First we update the system, then add Docker’s official package repository so we get the current Docker Engine and the Compose v2 plugin (the distribution packages are often older).

sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
sudo curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

The line . /etc/os-release loads two variables describing your system: ID is debian or ubuntu, and VERSION_CODENAME is trixie on Debian 13 or noble on Ubuntu 24.04. That is why the same commands work on both distributions: they automatically pick the right repository.

If the upgrade installed a new kernel, reboot. On Ubuntu you can check whether a reboot is needed with ls /var/run/reboot-required: if the file exists, reboot. Debian does not create that file by default, so on Debian simply reboot after a kernel update.

Next, allow your user to run Docker without typing sudo every time, then log out and back in so the group change takes effect:

sudo usermod -aG docker $USER
exit

After reconnecting over SSH, verify the installation:

docker --version
docker compose version
docker run --rm hello-world

You should see version numbers for both tools and a “Hello from Docker!” message. Keep in mind that membership in the docker group is equivalent to root access, so only add trusted users to it.

Finally, the firewall. Ubuntu ships with ufw installed but inactive; on Debian you install it first. Always allow SSH before enabling it, or you will lock yourself out:

sudo apt install -y ufw
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443
sudo ufw enable
sudo ufw status

An important detail many people miss: ports published by Docker bypass ufw, because Docker writes its own firewall rules. This is exactly why our design publishes only Caddy’s ports 80 and 443, and never publishes MariaDB’s 3306 or BookStack’s internal port.

Step 2: Point a domain at your VPS

Caddy needs a real domain to obtain an HTTPS certificate. In your DNS provider’s panel, create an A record for the subdomain you want, for example wiki, pointing to your VPS’s public IPv4 address. If your VPS also has IPv6, add an AAAA record with that address. Check from the VPS that the name resolves:

getent hosts wiki.yourcompany.ro

The output should show your server’s IP. DNS changes can take a few minutes to propagate; do not continue until this works, otherwise Let’s Encrypt cannot validate your domain in Step 5.

Step 3: Create the project folder and secrets

We keep everything in one folder: the Compose file, the configuration and the data. Sensitive values go into a .env file, which Docker Compose reads automatically and substitutes into the Compose file wherever it sees ${VARIABLE}. This keeps passwords out of the main file and makes backups simple.

mkdir -p ~/bookstack && cd ~/bookstack
cat > .env <<EOF
# Public address of the wiki (no https://, no trailing slash)
WIKI_DOMAIN=wiki.yourcompany.ro

# Application key: generated once, never change it afterwards
APP_KEY=base64:$(openssl rand -base64 32)

# Database passwords (hex, so there are no special characters to escape)
DB_PASSWORD=$(openssl rand -hex 24)
DB_ROOT_PASSWORD=$(openssl rand -hex 24)

# Email settings, we fill these in at Step 7
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=wiki@yourcompany.ro
MAIL_PASSWORD=change-me
MAIL_FROM=wiki@yourcompany.ro
MAIL_FROM_NAME="Team Wiki"
EOF
chmod 600 .env
cat .env

The $(openssl rand ...) parts are executed while the file is written, so cat .env should show long random strings instead of the commands. chmod 600 makes the file readable only by your user. Now open it with nano .env and replace wiki.yourcompany.ro with your real domain.

The APP_KEY is the encryption key Laravel uses for sessions and other encrypted data. It must start with base64: and must stay the same for the life of the installation: if you change it later, everyone is logged out and some encrypted values become unreadable. Back up the .env file together with your data.

Step 4: Write the Docker Compose file and Caddyfile

Create docker-compose.yml with nano docker-compose.yml and paste:

services:
  db:
    image: mariadb:11.4
    container_name: bookstack-db
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MARIADB_DATABASE: bookstack
      MARIADB_USER: bookstack
      MARIADB_PASSWORD: ${DB_PASSWORD}
      TZ: Europe/Bucharest
    volumes:
      - ./db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s

  bookstack:
    image: lscr.io/linuxserver/bookstack:latest
    container_name: bookstack
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      PUID: "1000"
      PGID: "1000"
      TZ: Europe/Bucharest
      APP_URL: https://${WIKI_DOMAIN}
      APP_KEY: ${APP_KEY}
      DB_HOST: db
      DB_PORT: "3306"
      DB_DATABASE: bookstack
      DB_USERNAME: bookstack
      DB_PASSWORD: ${DB_PASSWORD}
      MAIL_DRIVER: smtp
      MAIL_HOST: ${MAIL_HOST}
      MAIL_PORT: ${MAIL_PORT}
      MAIL_ENCRYPTION: ${MAIL_ENCRYPTION}
      MAIL_USERNAME: ${MAIL_USERNAME}
      MAIL_PASSWORD: ${MAIL_PASSWORD}
      MAIL_FROM: ${MAIL_FROM}
      MAIL_FROM_NAME: ${MAIL_FROM_NAME}
    volumes:
      - ./config:/config

  caddy:
    image: caddy:2
    container_name: bookstack-caddy
    restart: unless-stopped
    depends_on:
      - bookstack
    environment:
      WIKI_DOMAIN: ${WIKI_DOMAIN}
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:

What each part does:

  • db: MariaDB stores pages, users and settings. The MARIADB_* variables create the database and a dedicated bookstack user on the very first start. The healthcheck lets Docker know when the database is truly ready to accept connections, not merely started.
  • bookstack: depends_on with condition: service_healthy makes BookStack wait for a healthy database, which avoids connection errors on the first boot. PUID and PGID are the user and group IDs that will own the files in ./config; check yours with id -u and id -g and adjust if they are not 1000. APP_URL must be the exact public address, because BookStack builds every link and redirect from it. Notice there is no ports: section: BookStack is reachable only through Caddy.
  • caddy: the only service with published ports. Its certificates are stored in the named volume caddy_data, so they survive restarts and you do not hit Let’s Encrypt rate limits.

About image tags: mariadb:11.4 follows patch releases of the 11.4 LTS series, which is safe. For BookStack we use latest, which always gives you the newest release on docker compose pull. BookStack releases often and runs its database migrations automatically, so this is convenient, but it also means an update happens whenever you pull. If you prefer full control, replace latest with a specific version tag of the form version-vXX.YY.Z listed on the image page, and change it deliberately after reading the release notes.

Now create the Caddyfile with nano Caddyfile:

{$WIKI_DOMAIN} {
	encode zstd gzip
	reverse_proxy bookstack:80
}

{$WIKI_DOMAIN} is read from the environment variable we passed to the Caddy container, so the domain is defined in just one place, the .env file. reverse_proxy bookstack:80 forwards every request to the BookStack container over Docker’s private network, and encode compresses responses so pages load faster.

Step 5: Start the stack

From the ~/bookstack folder, start everything in the background (-d means detached):

cd ~/bookstack
docker compose up -d
docker compose ps

Docker downloads the three images, starts MariaDB, waits until it reports healthy, then starts BookStack and Caddy. After a minute, docker compose ps should list bookstack-db with status Up (healthy) and the other two as Up. On the first start, BookStack creates its tables, which can take 30 to 60 seconds. Watch it with:

docker compose logs -f bookstack

When you see a line ending in [ls.io-init] done., the application is ready. Press Ctrl+C to stop following the logs (the container keeps running). You can also check that Caddy obtained its certificate with docker compose logs caddy, looking for a message that says the certificate was obtained successfully.

Step 6: First login and securing the admin account

Open https://wiki.yourcompany.ro in your browser. You should get a valid padlock and the BookStack login page. The default credentials are:

  • Email: admin@admin.com
  • Password: password

Change them immediately, because everyone who has read the documentation knows them. Go to Settings (top bar), then Users, click the Admin user, set your real name and email address, type a strong new password in the password fields and save. While you are on your profile, set up multi-factor authentication with an authenticator app and store the backup codes somewhere safe.

Then visit Settings > Customization to set the application name (shown in the header and in emails), upload your logo and choose colors. Two minutes here make the wiki feel like your own tool rather than a generic install, which helps adoption more than you would expect.

Step 7: Configure email so users can reset passwords

Without email, a forgotten password means a message to you, and invitations have to be sent manually. With SMTP configured, users click “Forgot Password?” on the login page and receive a reset link, and you can invite new colleagues straight from the users page.

SMTP (Simple Mail Transfer Protocol) is the standard way programs send email. You need four things from your mail provider: the server name, the port, a username and a password. Ports matter:

  • 587 is the submission port with STARTTLS (the connection starts plain and is upgraded to encryption). This is the most common choice.
  • 465 uses implicit TLS (encrypted from the first byte). Also fine.
  • 25 is for server-to-server delivery and is blocked outbound by many providers and networks. Avoid it for this purpose.

With BookStack, MAIL_ENCRYPTION=tls means “require encryption”, and it works with both port 587 and port 465. Use null only for an internal relay that does not support TLS. Edit the mail section of .env with your real values:

nano ~/bookstack/.env
MAIL_HOST=mail.yourcompany.ro
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=wiki@yourcompany.ro
MAIL_PASSWORD=your-mailbox-password
MAIL_FROM=wiki@yourcompany.ro
MAIL_FROM_NAME="Team Wiki"

Apply the change. Compose notices that BookStack’s environment changed and recreates only that container; your data is untouched because it lives in ./config and ./db:

cd ~/bookstack
docker compose up -d

Now test it. Go to Settings > Maintenance and click Send a Test Email. BookStack sends a message to your own account’s address and shows either a success notice or the error returned by the SMTP server. Then open a private browser window, click “Forgot Password?” on the login page, enter your email and confirm the reset link arrives.

Two practical tips. Use a MAIL_FROM address on a domain your provider is allowed to send for (correct SPF and DKIM records), otherwise messages land in spam or get rejected. And if the variables ever seem to be ignored, the image also keeps BookStack’s configuration file at ./config/www/.env, where the same MAIL_* keys can be set, followed by docker compose restart bookstack.

Roles and permissions in BookStack

Now that people can actually log in and recover their accounts, it is time to decide who can see and change what. BookStack’s model has two layers.

Layer one: roles

A role is a named set of permissions, and every user has one or more roles. A fresh install has three regular roles plus one special role:

RoleTypical useWhat it can do by default
AdminYou, maybe one backup personEverything, including settings, users and roles
EditorColleagues who write documentationCreate, edit and delete content
ViewerRead-only users, interns, clientsView content only
PublicVisitors who are not logged inUsed only if public access is enabled

Open Settings > Roles and click a role to see two sections. System permissions control administrative abilities: managing app settings, users, roles, all content permissions, exporting content, changing the page editor and using the API. Asset permissions are a grid of shelves, books, chapters, pages, images, attachments and comments against create, view, edit and delete, where each cell can be “All” or “Own” (only items the user created). For example, a “Contributor” role could create pages but edit and delete only its own, which is a nice middle ground for a large team.

Layer two: content-level permissions

Any shelf, book, chapter or page has a Permissions action in its sidebar. There you can override the role defaults for that specific item, for example making the “HR and policies” book visible only to the Admin role and a new “HR” role, even though Editors can normally see everything. Overrides set on a book apply to all its chapters and pages, unless a chapter or page has its own override.

Shelves are the exception: their permissions control who sees the shelf itself, not the books on it. If you want the books to follow, use the Copy permissions to books button on the shelf’s permissions page.

Inviting users, public access and self-registration

  • Invite: in Settings > Users > Add New User, enter the name, email and role, and tick the option to send an invite by email. The user receives a link to choose their own password, so you never handle it. This is the first payoff of Step 7.
  • Public access: in Settings > Features & Security you can allow public viewing. Visitors then get whatever the Public role allows. Great for public product documentation, dangerous for an internal wiki, so double-check the Public role before switching it on.
  • Registration: in Settings > Registration you can let people create their own accounts, choose the default role for them, require email confirmation and restrict sign-ups to your company domain, for example yourcompany.ro.

Backups and updates

Your wiki will quickly become important, so back it up from day one. Two things need saving: the database and the ./config folder (uploaded images, attachments and BookStack’s configuration), plus your .env, Compose file and Caddyfile.

cd ~/bookstack
docker compose exec -T db sh -c 'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction bookstack' > bookstack-db-$(date +%F).sql
sudo tar czf bookstack-files-$(date +%F).tar.gz config .env docker-compose.yml Caddyfile
ls -lh bookstack-*

The first command runs mariadb-dump inside the database container (where the root password is already available as an environment variable) and writes a consistent SQL file on the VPS. The second archives the files. Copy both off the server, because a backup living on the same disk does not survive the loss of that disk. To restore on a new server, recreate the folder with the same .env, unpack the archive, start only the database with docker compose up -d db, import with docker compose exec -T db sh -c 'mariadb -u root -p"$MARIADB_ROOT_PASSWORD" bookstack' < bookstack-db-DATE.sql, then run docker compose up -d.

Updating is three commands, but take a backup first:

cd ~/bookstack
docker compose pull
docker compose up -d
docker image prune -f

pull downloads newer images, up -d recreates the containers that changed, and BookStack applies its database migrations on start. If you ever move MariaDB to a new major series (for example from 11.4 to a future LTS), back up first and add MARIADB_AUTO_UPGRADE: "1" to the db environment so the data files are upgraded automatically.

How much does it actually use?

BookStack is pleasantly light. On an idle small team wiki with a few hundred pages, the three containers together use roughly a third of a gigabyte of RAM. The figures below are approximate and grow with traffic and content, but they show why the smallest VPS plans are enough.

Idle RAM usage, small team wiki (approx.)0100200300400RAM, MB (approx.)Whole stack fits easily in a 1 GB VPS~180 MB~130 MB~30 MB~340 MBMariaDBBookStackCaddyTotalContainer
Figure 3: approximate idle memory per container, measured with docker stats on a small wiki. Expect higher values under load, during exports to PDF or with very large page counts.

You can check your own numbers at any time with docker stats --no-stream, which prints CPU and memory usage per container.

Troubleshooting and common mistakes

  • “502 Bad Gateway” right after starting: BookStack is still running its first migrations. Wait a minute and watch docker compose logs -f bookstack until you see [ls.io-init] done.
  • No HTTPS certificate, browser warning: the domain does not point to the VPS yet, or port 80 is blocked somewhere. Check getent hosts your-domain and docker compose logs caddy. Let’s Encrypt must reach your server on port 80 or 443 to validate it.
  • Broken styling or redirects to the wrong address: APP_URL does not match the address in the browser (http instead of https, a different subdomain or a trailing slash). Fix WIKI_DOMAIN and run docker compose up -d. If you change the domain of a wiki that already has content, also update links stored in pages with docker compose exec bookstack php /app/www/artisan bookstack:update-url https://old.domain https://new.domain.
  • Database connection errors after changing the password: MariaDB reads the MARIADB_* variables only on the very first start, when ./db is empty. Changing DB_PASSWORD in .env later does not change the password stored in the database. Either change it back, or update the user with ALTER USER from inside the database container.
  • Test email fails: read the exact error on the Maintenance page. “Connection timed out” usually means a wrong port or a port blocked outbound, “authentication failed” means wrong credentials, and certificate errors mean the host name does not match the server’s certificate. For more detail, run docker compose logs bookstack and look at the application log with sudo find ~/bookstack/config -name laravel.log.
  • Locked out of the admin account and email does not work: create a fresh admin from the command line with docker compose exec bookstack php /app/www/artisan bookstack:create-admin --email=you@yourcompany.ro --name=You --password=NewStrongPassword. If a user lost their MFA device, the same tool offers bookstack:reset-mfa.
  • Permission denied errors in ./config: PUID and PGID do not match the owner of the folder. Set them to the output of id -u and id -g and recreate the container.
  • Docker will not start in an LXC container: nesting is not enabled. Ask support to enable it, or use a KVM VPS.

Security notes

  • Change the default login immediately and enable MFA for every account with admin rights. Under each role you can even make MFA mandatory.
  • Never publish the database port. MariaDB should only be reachable on Docker’s private network, as in our Compose file. Remember that Docker-published ports bypass ufw.
  • Protect your secrets: keep .env at chmod 600, do not commit it to a public Git repository, and include it in your encrypted backups.
  • Review the Public role before enabling public access, and restrict self-registration to your domain if you turn it on.
  • Update regularly and read the release notes; BookStack publishes security fixes promptly.
  • Keep backups off the server and test a restore at least once, so you know it works before you need it.
  • Limit SSH: use key authentication, disable password logins and consider a tool like fail2ban.

So, is BookStack the right wiki for you?

If you want documentation that non-technical colleagues will actually use, with a structure that makes sense on the first day, solid permissions and very modest resource needs, BookStack is one of the best self-hosted options available. With the BookStack Docker Compose setup above you get a secure, HTTPS-enabled wiki that sends its own password reset emails and upgrades with three commands. If you need deep page hierarchies of unlimited depth or a fully Git-based workflow, you may prefer other tools, but for most teams the shelves-books-pages model is a strength, not a limitation.

You can deploy this stack on a VPS from us in a few minutes, or let our server administration team install, secure, back up and maintain your BookStack wiki for you.

FAQ

Is BookStack free to use commercially?

Yes. BookStack is released under the MIT license, so you can use it for any purpose, including inside a company, without paying license fees. Your only cost is the server it runs on.

How many users can a small VPS handle?

A 1 GB VPS comfortably serves a team of a few dozen people reading and editing documentation. If you have hundreds of active users, heavy PDF exports or thousands of large images, move to 2 GB of RAM or more.

Can I connect BookStack to LDAP, Active Directory or single sign-on?

Yes. BookStack supports LDAP, SAML2 and OpenID Connect, configured through additional environment variables. Users then log in with their existing company accounts, and roles can be synchronized from groups.

Can I run BookStack without a domain?

For a quick test, yes: publish BookStack’s port (for example "6875:80"), remove Caddy and set APP_URL to http://your-ip:6875. For real use, always use a domain with HTTPS, otherwise passwords travel unencrypted.

Can I move my documentation out of BookStack later?

Yes. Every book, chapter and page can be exported as PDF, HTML, plain text or Markdown, recent versions add ZIP exports that another BookStack instance can import, and the REST API lets you script larger migrations.

Trusted By & Member Of

We are proud members of leading internet infrastructure organizations.

RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX