Self-Hosted Wiki: Bookstack, Wiki.js and Outline for Team Documentation
Documentation is the backbone of any team or organization. Whether it is runbooks, API documentation, onboarding guides, or internal knowledge bases, having a centralized, searchable wiki is essential. Confluence has long dominated this space, but its pricing, complexity, and Atlassian's push toward cloud-only hosting have driven teams to explore self-hosted alternatives.
Three open-source wiki platforms stand out: Bookstack (structured, book-based organization), Wiki.js (modern, Git-backed), and Outline (Notion-like collaborative editor). Each takes a fundamentally different approach to organizing knowledge.
Feature Comparison
| Feature | Bookstack | Wiki.js | Outline |
|---|---|---|---|
| Language | PHP (Laravel) | Node.js | Node.js (React) |
| Organization model | Shelves > Books > Chapters > Pages | Flat with folders and tags | Collections > Documents (nested) |
| Editor | WYSIWYG + Markdown | Multiple (Markdown, Visual, Code) | Block editor (Notion-like) |
| Real-time collaboration | No | No | Yes |
| Full-text search | Yes (database) | Yes (Elasticsearch, PostgreSQL FTS) | Yes (PostgreSQL FTS) |
| Git integration | No | Yes (sync to/from Git repos) | No |
| API | REST API | GraphQL + REST | REST API |
| SSO / OAuth | LDAP, SAML, OIDC | LDAP, OAuth, SAML, OIDC | OIDC required (Slack, Google, Azure AD) |
| Diagrams | Draw.io integration | Draw.io, PlantUML, Mermaid | Mermaid |
| RAM usage | ~150 MB | ~300 MB (+Elasticsearch if used) | ~250 MB |
| License | MIT | AGPL-3.0 | BSL 1.1 (source available) |
Docker Deployment: Bookstack
# docker-compose.yml for Bookstack
version: "3.8"
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- APP_URL=https://wiki.example.com
- DB_HOST=bookstack-db
- DB_PORT=3306
- DB_USER=bookstack
- DB_PASS=${DB_PASSWORD}
- DB_DATABASE=bookstackapp
# SMTP configuration
- MAIL_DRIVER=smtp
- MAIL_HOST=smtp.example.com
- MAIL_PORT=587
- [email protected]
- MAIL_PASSWORD=${SMTP_PASSWORD}
- MAIL_ENCRYPTION=tls
- [email protected]
volumes:
- bookstack_config:/config
ports:
- "6875:80"
depends_on:
- bookstack-db
bookstack-db:
image: mariadb:10.11
container_name: bookstack-db
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=bookstackapp
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- bookstack_db:/var/lib/mysql
volumes:
bookstack_config:
bookstack_db:
Docker Deployment: Wiki.js
# docker-compose.yml for Wiki.js
version: "3.8"
services:
wikijs:
image: ghcr.io/requarks/wiki:2
container_name: wikijs
restart: unless-stopped
environment:
- DB_TYPE=postgres
- DB_HOST=wikijs-db
- DB_PORT=5432
- DB_USER=wikijs
- DB_PASS=${DB_PASSWORD}
- DB_NAME=wiki
volumes:
- wikijs_data:/wiki/data
ports:
- "3000:3000"
depends_on:
- wikijs-db
wikijs-db:
image: postgres:16-alpine
container_name: wikijs-db
restart: unless-stopped
environment:
- POSTGRES_DB=wiki
- POSTGRES_USER=wikijs
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- wikijs_db:/var/lib/postgresql/data
volumes:
wikijs_data:
wikijs_db:
Docker Deployment: Outline
# docker-compose.yml for Outline
version: "3.8"
services:
outline:
image: outlinewiki/outline:latest
container_name: outline
restart: unless-stopped
env_file: ./outline.env
ports:
- "3000:3000"
depends_on:
- outline-db
- outline-redis
outline-db:
image: postgres:16-alpine
container_name: outline-db
restart: unless-stopped
environment:
- POSTGRES_DB=outline
- POSTGRES_USER=outline
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- outline_db:/var/lib/postgresql/data
outline-redis:
image: redis:7-alpine
container_name: outline-redis
restart: unless-stopped
volumes:
- outline_redis:/data
volumes:
outline_db:
outline_redis:
# outline.env - key configuration
NODE_ENV=production
SECRET_KEY=generated-secret-key-min-32-chars
UTILS_SECRET=generated-utils-secret-min-32-chars
DATABASE_URL=postgres://outline:password@outline-db:5432/outline
REDIS_URL=redis://outline-redis:6379
URL=https://docs.example.com
PORT=3000
FILE_STORAGE=local
FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
# Authentication (OIDC required - no local auth)
# Example with Keycloak, Authentik, or similar
OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=your-client-secret
OIDC_AUTH_URI=https://auth.example.com/authorize
OIDC_TOKEN_URI=https://auth.example.com/token
OIDC_USERINFO_URI=https://auth.example.com/userinfo
OIDC_DISPLAY_NAME=SSO Login
Search Capabilities
Bookstack
Bookstack uses database-level full-text search (MySQL/MariaDB FULLTEXT indexes). It works well for small to medium knowledge bases but does not support fuzzy matching or relevance ranking as sophisticated as dedicated search engines.
Wiki.js
Wiki.js offers the most flexible search with multiple backend options:
# Wiki.js search engine options (configured in admin panel):
# 1. Database (PostgreSQL FTS) - good default, no extra services
# 2. Elasticsearch - best for large wikis, fuzzy search, relevance
# 3. Algolia - cloud-based, fast but not self-hosted
# 4. Azure Search
# 5. Manticore Search - open-source Elasticsearch alternative
# Adding Elasticsearch to Docker Compose:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
container_name: wikijs-search
restart: unless-stopped
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- wikijs_search:/usr/share/elasticsearch/data
Outline
Outline uses PostgreSQL full-text search with good performance and relevance ranking. Search results include snippets and are ranked by relevance. It supports searching within document content, titles, and comments.
Access Control
| Feature | Bookstack | Wiki.js | Outline |
|---|---|---|---|
| Role-based access | Yes (granular, per-shelf/book/chapter/page) | Yes (per-group, per-path) | Yes (per-collection) |
| Public pages | Yes | Yes | Yes (share links) |
| Guest access | Yes (configurable) | Yes | No (auth required) |
| LDAP groups | Yes (group sync) | Yes | No (OIDC groups) |
| Page-level permissions | Yes | Yes (regex path rules) | Collection-level only |
API Integration
All three wikis provide APIs for automation:
# Bookstack REST API
curl -X GET "https://wiki.example.com/api/pages" \
-H "Authorization: Token ${BOOKSTACK_TOKEN_ID}:${BOOKSTACK_TOKEN_SECRET}"
# Create a page
curl -X POST "https://wiki.example.com/api/pages" \
-H "Authorization: Token ${TOKEN_ID}:${TOKEN_SECRET}" \
-H "Content-Type: application/json" \
-d '{
"book_id": 1,
"name": "Deployment Guide",
"markdown": "# Deployment Guide\n\nStep 1: ..."
}'
# Wiki.js GraphQL API
curl -X POST "https://docs.example.com/graphql" \
-H "Authorization: Bearer ${WIKIJS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"query": "{ pages { list { id title path } } }"
}'
# Outline REST API
curl -X POST "https://docs.example.com/api/documents.search" \
-H "Authorization: Bearer ${OUTLINE_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"query": "deployment"}'
Backup and Migration
#!/bin/bash
# wiki-backup.sh - Backup any wiki platform
set -euo pipefail
BACKUP_DIR="/backups/wiki/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Bookstack backup
docker exec bookstack-db mysqldump -u bookstack -p"${DB_PASSWORD}" bookstackapp | \
gzip > "$BACKUP_DIR/bookstack_db.sql.gz"
docker run --rm -v bookstack_config:/source:ro -v "$BACKUP_DIR":/backup \
alpine tar czf /backup/bookstack_config.tar.gz -C /source .
# Wiki.js backup
docker exec wikijs-db pg_dump -U wikijs wiki | \
gzip > "$BACKUP_DIR/wikijs_db.sql.gz"
# Outline backup
docker exec outline-db pg_dump -U outline outline | \
gzip > "$BACKUP_DIR/outline_db.sql.gz"
echo "Wiki backup complete: $BACKUP_DIR"
Which One Should You Choose?
- Choose Bookstack if you want structured documentation organized into books and chapters. Ideal for operations runbooks, technical documentation, and knowledge bases where a hierarchical organization makes sense. Lowest resource usage and simplest to maintain.
- Choose Wiki.js if you want the most flexible and feature-rich wiki with Git integration, multiple editor modes, and powerful search. Ideal for developer teams who want documentation as code.
- Choose Outline if you want a modern, Notion-like editing experience with real-time collaboration. Ideal for teams that find traditional wikis too rigid and want a more fluid, document-centric approach. Requires OIDC setup.
A wiki is only as good as the documentation people actually write in it. The best wiki platform is the one your team will actually use. If your team prefers Markdown, choose Wiki.js. If they want a Notion-like experience, choose Outline. If they want structure, choose Bookstack.
For managing wiki containers alongside your other self-hosted services, platforms like usulnet give you visibility into container health, resource usage, and backup status, ensuring your knowledge base stays available and protected.