Outline: Team Knowledge Base
Beautiful wiki for teams. Real-time collaboration, Slack integration, and powerful search.
Introduction
Outline is an open-source team knowledge base and wiki designed for teams who value beautiful, fast, and collaborative documentation. Built with modern technologies, it offers real-time collaboration, intuitive organization, and a clean, distraction-free interface.
Why Choose Outline?
- Beautiful Interface: Clean, modern design focused on content
- Real-Time Collaboration: Multiple users editing simultaneously
- Markdown Support: Write in markdown with live preview
- Powerful Search: Fast full-text search across all documents
- Collections: Organize documents into structured collections
- Version History: Track all changes with complete history
- Integrations: Slack, webhooks, and API access
- Authentication: Support for various SSO providers
Use Cases
- Team documentation and wikis
- Product documentation
- Company knowledge bases
- Project documentation
- Standard operating procedures
- Onboarding documentation
- Meeting notes and decisions
- Technical specifications
Prerequisites
Before you begin, ensure you have:
- Docker and Docker Compose installed
- 2GB of available RAM (4GB recommended)
- 10-20GB of disk space
- Domain name with DNS configured
- SSL certificate (Let’s Encrypt recommended)
- SMTP server for email notifications
- Authentication provider (Slack, Google, etc.) or OIDC
Required Services
Outline requires several supporting services:
- PostgreSQL: Primary database
- Redis: Caching and sessions
- MinIO or S3: File storage
- SMTP: Email notifications
Docker Compose Configuration
Complete Stack Setup
Create a directory structure:
mkdir -p ~/homelab/outline/{redis,postgres,minio}
cd ~/homelab/outline Create a comprehensive docker-compose.yml:
version: '3.8'
services:
outline:
image: outlinewiki/outline:latest
container_name: outline
restart: unless-stopped
depends_on:
- postgres
- redis
- minio
networks:
- outline_network
- proxy
expose:
- 3000
environment:
# Database
- DATABASE_URL=postgres://outline:CHANGE_ME_PASSWORD@postgres:5432/outline
- PGSSLMODE=disable
# Redis
- REDIS_URL=redis://redis:6379
# Storage (MinIO)
- AWS_ACCESS_KEY_ID=minio_access_key
- AWS_SECRET_ACCESS_KEY=CHANGE_ME_MINIO_SECRET
- AWS_REGION=us-east-1
- AWS_S3_UPLOAD_BUCKET_URL=http://minio:9000
- AWS_S3_UPLOAD_BUCKET_NAME=outline
- AWS_S3_FORCE_PATH_STYLE=true
- AWS_S3_ACL=private
# Base URL
- URL=https://wiki.yourdomain.com
- PORT=3000
# Secret keys (generate with: openssl rand -hex 32)
- SECRET_KEY=GENERATE_SECRET_KEY_HERE
- UTILS_SECRET=GENERATE_UTILS_SECRET_HERE
# Authentication - Slack example
- SLACK_CLIENT_ID=your_slack_client_id
- SLACK_CLIENT_SECRET=your_slack_client_secret
# Optional: Google OAuth
# - GOOGLE_CLIENT_ID=your_google_client_id
# - GOOGLE_CLIENT_SECRET=your_google_client_secret
# Optional: OIDC Generic
# - OIDC_CLIENT_ID=your_oidc_client_id
# - OIDC_CLIENT_SECRET=your_oidc_client_secret
# - OIDC_AUTH_URI=https://your-provider/authorize
# - OIDC_TOKEN_URI=https://your-provider/token
# - OIDC_USERINFO_URI=https://your-provider/userinfo
# - OIDC_USERNAME_CLAIM=preferred_username
# - OIDC_DISPLAY_NAME=Custom SSO
# - OIDC_SCOPES=openid profile email
# SMTP Settings
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=465
- SMTP_USERNAME=your-[email protected]
- SMTP_PASSWORD=your_app_password
- [email protected]
- SMTP_SECURE=true
# Optional features
- ENABLE_UPDATES=true
- WEB_CONCURRENCY=1
- MAXIMUM_IMPORT_SIZE=5242880
- LOG_LEVEL=info
- DEFAULT_LANGUAGE=en_US
- FORCE_HTTPS=true
labels:
- "traefik.enable=true"
- "traefik.http.routers.outline.rule=Host(`wiki.yourdomain.com`)"
- "traefik.http.routers.outline.entrypoints=websecure"
- "traefik.http.routers.outline.tls=true"
- "traefik.http.routers.outline.tls.certresolver=letsencrypt"
- "traefik.http.services.outline.loadbalancer.server.port=3000"
volumes:
- outline-data:/var/lib/outline/data
postgres:
image: postgres:15-alpine
container_name: outline_postgres
restart: unless-stopped
networks:
- outline_network
environment:
- POSTGRES_USER=outline
- POSTGRES_PASSWORD=CHANGE_ME_PASSWORD
- POSTGRES_DB=outline
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U outline"]
interval: 30s
timeout: 10s
retries: 5
redis:
image: redis:7-alpine
container_name: outline_redis
restart: unless-stopped
networks:
- outline_network
volumes:
- redis-data:/data
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 5
minio:
image: minio/minio:latest
container_name: outline_minio
restart: unless-stopped
networks:
- outline_network
command: server /data --console-address ":9001"
environment:
- MINIO_ROOT_USER=minio_access_key
- MINIO_ROOT_PASSWORD=CHANGE_ME_MINIO_SECRET
- MINIO_BROWSER_REDIRECT_URL=https://minio.yourdomain.com
volumes:
- minio-data:/data
expose:
- 9000
- 9001
labels:
- "traefik.enable=true"
# MinIO Console
- "traefik.http.routers.minio-console.rule=Host(`minio.yourdomain.com`)"
- "traefik.http.routers.minio-console.entrypoints=websecure"
- "traefik.http.routers.minio-console.tls=true"
- "traefik.http.routers.minio-console.tls.certresolver=letsencrypt"
- "traefik.http.routers.minio-console.service=minio-console"
- "traefik.http.services.minio-console.loadbalancer.server.port=9001"
# MinIO API
- "traefik.http.routers.minio-api.rule=Host(`minio-api.yourdomain.com`)"
- "traefik.http.routers.minio-api.entrypoints=websecure"
- "traefik.http.routers.minio-api.tls=true"
- "traefik.http.routers.minio-api.tls.certresolver=letsencrypt"
- "traefik.http.routers.minio-api.service=minio-api"
- "traefik.http.services.minio-api.loadbalancer.server.port=9000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
networks:
outline_network:
driver: bridge
proxy:
external: true
volumes:
outline-data:
postgres-data:
redis-data:
minio-data: Environment Configuration
Create a .env file for sensitive variables:
# Database
POSTGRES_USER=outline
POSTGRES_PASSWORD=STRONG_PASSWORD_HERE
POSTGRES_DB=outline
# Redis
REDIS_URL=redis://redis:6379
# MinIO S3
MINIO_ROOT_USER=minio_access_key
MINIO_ROOT_PASSWORD=STRONG_MINIO_PASSWORD
# Outline Secrets
SECRET_KEY=GENERATE_WITH_OPENSSL_RAND_HEX_32
UTILS_SECRET=GENERATE_WITH_OPENSSL_RAND_HEX_32
# URLs
OUTLINE_URL=https://wiki.yourdomain.com
MINIO_URL=http://minio:9000
# SMTP
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
[email protected]
SMTP_PASSWORD=your_app_password
[email protected] Generate secret keys:
openssl rand -hex 32 # For SECRET_KEY
openssl rand -hex 32 # For UTILS_SECRET Deployment Process
Step 1: Create MinIO Bucket
Before starting Outline, create the S3 bucket:
# Start only MinIO first
docker-compose up -d minio
# Wait for MinIO to be ready
sleep 10
# Access MinIO console at https://minio.yourdomain.com
# Or create bucket via CLI:
docker exec outline_minio mc alias set myminio http://localhost:9000 minio_access_key CHANGE_ME_MINIO_SECRET
docker exec outline_minio mc mb myminio/outline
docker exec outline_minio mc policy set download myminio/outline Step 2: Initialize Database
Start PostgreSQL and create the schema:
# Start postgres and redis
docker-compose up -d postgres redis
# Wait for services to be ready
sleep 15
# Initialize Outline database
docker-compose run --rm outline yarn db:migrate Step 3: Start Outline
# Start all services
docker-compose up -d
# Monitor logs
docker-compose logs -f outline Step 4: Access Outline
Navigate to your configured URL: https://wiki.yourdomain.com
Authentication Setup
Slack Authentication
- Go to https://api.slack.com/apps
- Create a new app
- Configure OAuth redirect:
https://wiki.yourdomain.com/auth/slack.callback - Add OAuth scopes:
identity.basic,identity.email,identity.avatar - Install to workspace
- Copy Client ID and Secret to environment variables
Google OAuth
- Go to Google Cloud Console
- Create OAuth 2.0 credentials
- Authorized redirect URI:
https://wiki.yourdomain.com/auth/google.callback - Copy Client ID and Secret
Generic OIDC (e.g., Authelia, Keycloak)
environment:
- OIDC_CLIENT_ID=outline
- OIDC_CLIENT_SECRET=your_client_secret
- OIDC_AUTH_URI=https://auth.yourdomain.com/api/oidc/authorization
- OIDC_TOKEN_URI=https://auth.yourdomain.com/api/oidc/token
- OIDC_USERINFO_URI=https://auth.yourdomain.com/api/oidc/userinfo
- OIDC_USERNAME_CLAIM=preferred_username
- OIDC_DISPLAY_NAME=Authelia
- OIDC_SCOPES=openid profile email Data Import and Export
Import from Other Platforms
Outline supports importing from:
Confluence
# Export from Confluence as HTML
# Use Outline's import feature: Settings → Import → Confluence Notion
# Export from Notion as Markdown & CSV
# Import via: Settings → Import → Notion Google Docs
# Use Google Docs API or manual copy/paste
# Formatting is preserved Export Options
Full Database Export
# Export all documents
docker exec outline_postgres pg_dump -U outline outline > outline_backup.sql
# Export attachments from MinIO
docker exec outline_minio mc mirror myminio/outline /backup/outline-files Individual Document Export
- Click document menu → Export
- Choose format: Markdown, HTML, or PDF
API-Based Import Script
#!/bin/bash
# import-markdown-to-outline.sh
API_TOKEN="YOUR_API_TOKEN"
OUTLINE_URL="https://wiki.yourdomain.com"
COLLECTION_ID="your_collection_id"
for file in *.md; do
title=$(basename "$file" .md)
content=$(cat "$file")
curl -X POST "$OUTLINE_URL/api/documents.create" -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" -d "{
"title": "$title",
"text": $(echo "$content" | jq -Rs .),
"collectionId": "$COLLECTION_ID",
"publish": true
}"
done Backup Strategies
Automated Backup Script
#!/bin/bash
# backup-outline.sh
BACKUP_DIR="/mnt/backups/outline"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR"
# Backup PostgreSQL database
docker exec outline_postgres pg_dump -U outline outline | gzip > "$BACKUP_DIR/outline_db_$TIMESTAMP.sql.gz"
# Backup Redis data
docker exec outline_redis redis-cli BGSAVE
sleep 5
docker cp outline_redis:/data/dump.rdb "$BACKUP_DIR/redis_$TIMESTAMP.rdb"
# Backup MinIO data (S3 files)
docker exec outline_minio mc mirror myminio/outline "$BACKUP_DIR/minio_$TIMESTAMP/"
# Create archive
tar -czf "$BACKUP_DIR/outline_complete_$TIMESTAMP.tar.gz" "$BACKUP_DIR/outline_db_$TIMESTAMP.sql.gz" "$BACKUP_DIR/redis_$TIMESTAMP.rdb" "$BACKUP_DIR/minio_$TIMESTAMP/"
# Cleanup temporary files
rm -rf "$BACKUP_DIR/outline_db_$TIMESTAMP.sql.gz" "$BACKUP_DIR/redis_$TIMESTAMP.rdb" "$BACKUP_DIR/minio_$TIMESTAMP/"
# Remove old backups
find "$BACKUP_DIR" -name "outline_complete_*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: outline_complete_$TIMESTAMP.tar.gz" Schedule Automatic Backups
chmod +x backup-outline.sh
# Add to crontab
crontab -e
# Daily backup at 2 AM
0 2 * * * /path/to/backup-outline.sh >> /var/log/outline-backup.log 2>&1 Restore from Backup
#!/bin/bash
# restore-outline.sh
BACKUP_FILE="$1"
TEMP_DIR="/tmp/outline_restore"
# Stop services
docker-compose down
# Extract backup
mkdir -p "$TEMP_DIR"
tar -xzf "$BACKUP_FILE" -C "$TEMP_DIR"
# Restore PostgreSQL
docker-compose up -d postgres
sleep 10
gunzip < "$TEMP_DIR"/outline_db_*.sql.gz | docker exec -i outline_postgres psql -U outline
# Restore Redis
docker cp "$TEMP_DIR"/redis_*.rdb outline_redis:/data/dump.rdb
docker-compose restart redis
# Restore MinIO
docker-compose up -d minio
sleep 10
docker exec outline_minio mc mirror "$TEMP_DIR"/minio_*/ myminio/outline
# Cleanup
rm -rf "$TEMP_DIR"
# Start all services
docker-compose up -d
echo "Restore completed successfully" Advanced Configuration
Custom Branding
Add your logo and customize colors:
environment:
- TEAM_LOGO=https://yourdomain.com/logo.png
- PRIMARY_COLOR=#4E5C6E Webhook Integration
Set up webhooks for Slack notifications:
environment:
- SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL API Access
Generate an API token:
- User menu → Settings → API Tokens
- Create new token
- Use in requests:
curl -H "Authorization: Bearer YOUR_TOKEN" https://wiki.yourdomain.com/api/documents.list Rate Limiting
Configure rate limits:
environment:
- RATE_LIMITER_ENABLED=true
- RATE_LIMITER_REQUESTS=100
- RATE_LIMITER_DURATION_WINDOW=60000 Troubleshooting
Common Issues
Outline won’t start
# Check all services
docker-compose ps
# View logs
docker-compose logs outline
# Common issues:
# 1. Database not ready
docker-compose logs postgres
# 2. Redis connection failed
docker-compose logs redis
# 3. MinIO bucket not created
docker exec outline_minio mc ls myminio/ Database Migration Errors
# Reset migrations
docker-compose run --rm outline yarn db:migrate:undo
docker-compose run --rm outline yarn db:migrate
# Check database connection
docker exec outline_postgres psql -U outline -d outline -c "dt" File Upload Issues
# Verify MinIO bucket exists
docker exec outline_minio mc ls myminio/outline
# Check bucket policy
docker exec outline_minio mc policy get myminio/outline
# Test S3 connectivity from Outline
docker exec outline curl -v http://minio:9000 Authentication Problems
# Verify callback URLs match
# Outline: https://wiki.yourdomain.com/auth/slack.callback
# Must match exactly in OAuth provider
# Check environment variables
docker exec outline env | grep -E "SLACK|GOOGLE|OIDC"
# Review auth logs
docker-compose logs outline | grep -i auth Performance Issues
# Check resource usage
docker stats
# Increase memory limits
services:
outline:
deploy:
resources:
limits:
memory: 2G
# Optimize PostgreSQL
docker exec outline_postgres psql -U outline -d outline
# Run: VACUUM ANALYZE; Debug Mode
Enable detailed logging:
environment:
- LOG_LEVEL=debug
- DEBUG=outline:* Health Checks
Monitor service health:
# Check Outline health
curl https://wiki.yourdomain.com/_health
# Check PostgreSQL
docker exec outline_postgres pg_isready -U outline
# Check Redis
docker exec outline_redis redis-cli ping
# Check MinIO
curl http://localhost:9000/minio/health/live Security Best Practices
Network Security
- Use HTTPS Only: Always enable SSL/TLS
- Firewall Rules: Restrict database access
- Secure Secrets: Use Docker secrets or vault
- Regular Updates: Keep all images updated
Database Security
# Strong passwords
POSTGRES_PASSWORD=$(openssl rand -base64 32)
# Limit connections
# In postgres docker-compose:
command:
- "postgres"
- "-c"
- "max_connections=50" File Security
# MinIO bucket policy - private by default
environment:
- AWS_S3_ACL=private Maintenance
Regular Updates
# Update all services
docker-compose pull
docker-compose down
docker-compose up -d
# Run migrations if needed
docker-compose run --rm outline yarn db:migrate Database Maintenance
# Vacuum database monthly
docker exec outline_postgres psql -U outline -d outline -c "VACUUM ANALYZE;"
# Check database size
docker exec outline_postgres psql -U outline -d outline -c "l+" Log Rotation
Configure log rotation:
services:
outline:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3" Monitoring
Set up monitoring with Prometheus:
services:
outline:
environment:
- PROMETHEUS_METRICS=true
- PROMETHEUS_PORT=9090
expose:
- 9090 Tips and Best Practices
Content Organization
- Use Collections: Group related documents
- Consistent Naming: Develop naming conventions
- Templates: Create document templates
- Tags: Use sparingly but effectively
- Cross-linking: Link related documents
Collaboration
- Permissions: Set appropriate access levels
- Comments: Enable for team feedback
- Notifications: Configure email alerts
- Version History: Review changes regularly
Performance
- Image Optimization: Compress before uploading
- Regular Backups: Automate daily backups
- Database Tuning: Optimize PostgreSQL settings
- CDN: Use for static assets if needed
Additional Resources
- Official Documentation: https://docs.getoutline.com
- GitHub Repository: https://github.com/outline/outline
- Docker Hub: https://hub.docker.com/r/outlinewiki/outline
- Community Forum: https://github.com/outline/outline/discussions
- API Documentation: https://www.getoutline.com/developers
Conclusion
Outline provides a modern, beautiful platform for team knowledge management. While the setup requires multiple services (PostgreSQL, Redis, MinIO), the result is a powerful, scalable wiki system with excellent collaboration features.
The key to success with Outline is proper authentication configuration, regular backups, and establishing good documentation practices within your team. Start with a simple setup, configure authentication properly, and expand features as your needs grow.
With proper maintenance and good organizational habits, Outline becomes the central hub for team knowledge, documentation, and collaboration.
Happy documenting!