Skip to main content

Self-Hosting Outline: Your Team Wiki 2026

·OSSAlt Team
outlinewikiself-hostingdockerguide
Share:

Outline is the best-looking open source wiki and knowledge base. It's a Notion and Confluence alternative with real-time collaboration, Markdown support, and a clean interface your team will actually enjoy using.

Requirements

  • VPS with 2 GB RAM minimum
  • Docker and Docker Compose
  • Domain name (e.g., wiki.yourdomain.com)
  • S3-compatible storage (MinIO self-hosted or AWS S3)
  • OIDC authentication provider (required — Outline has no built-in auth)
  • SMTP service

Important: Authentication Requirement

Outline requires an external authentication provider. No username/password login. Options:

ProviderDifficultyNotes
Google WorkspaceEasyIf your team uses Google
GitHubEasyGood for dev teams
Keycloak (self-hosted)MediumFull control, any team
Authentik (self-hosted)MediumModern alternative to Keycloak
Azure ADEasyIf your team uses Microsoft

Step 1: Set Up MinIO (S3 Storage)

Outline requires S3-compatible storage for file uploads:

# Add to docker-compose.yml
services:
  minio:
    image: minio/minio:latest
    container_name: outline-minio
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - minio_data:/data
    environment:
      - MINIO_ROOT_USER=outline
      - MINIO_ROOT_PASSWORD=your-minio-password
    command: server /data --console-address ":9001"

After starting MinIO:

  1. Open http://your-server:9001
  2. Create a bucket named outline
  3. Set bucket policy to allow the Outline service account

Step 2: Create Docker Compose

# docker-compose.yml
services:
  outline:
    image: outlinewiki/outline:latest
    container_name: outline
    restart: unless-stopped
    ports:
      - "3000:3000"
    env_file: .env
    depends_on:
      - postgres
      - redis
      - minio

  postgres:
    image: postgres:16-alpine
    container_name: outline-db
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=outline
      - POSTGRES_USER=outline
      - POSTGRES_PASSWORD=your-strong-password

  redis:
    image: redis:7-alpine
    container_name: outline-redis
    restart: unless-stopped
    volumes:
      - redis_data:/data

  minio:
    image: minio/minio:latest
    container_name: outline-minio
    restart: unless-stopped
    volumes:
      - minio_data:/data
    environment:
      - MINIO_ROOT_USER=outline
      - MINIO_ROOT_PASSWORD=your-minio-password
    command: server /data --console-address ":9001"

volumes:
  postgres_data:
  redis_data:
  minio_data:

Step 3: Configure Environment

Create .env:

# General
NODE_ENV=production
SECRET_KEY=your-random-secret-key-min-32-chars
UTILS_SECRET=your-random-utils-secret-min-32-chars
URL=https://wiki.yourdomain.com
PORT=3000

# Database
DATABASE_URL=postgres://outline:your-strong-password@postgres:5432/outline
DATABASE_CONNECTION_POOL_MIN=0
DATABASE_CONNECTION_POOL_MAX=10
PGSSLMODE=disable

# Redis
REDIS_URL=redis://redis:6379

# Storage (MinIO)
FILE_STORAGE=s3
FILE_STORAGE_UPLOAD_MAX_SIZE=26214400
AWS_ACCESS_KEY_ID=outline
AWS_SECRET_ACCESS_KEY=your-minio-password
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

# SMTP
SMTP_HOST=smtp.resend.com
SMTP_PORT=587
SMTP_USERNAME=resend
SMTP_PASSWORD=re_your_api_key
SMTP_FROM_EMAIL=wiki@yourdomain.com
SMTP_REPLY_EMAIL=wiki@yourdomain.com
SMTP_SECURE=true

# Authentication (Google example)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

# Or OIDC (Keycloak/Authentik)
# OIDC_CLIENT_ID=outline
# OIDC_CLIENT_SECRET=your-oidc-secret
# OIDC_AUTH_URI=https://auth.yourdomain.com/realms/master/protocol/openid-connect/auth
# OIDC_TOKEN_URI=https://auth.yourdomain.com/realms/master/protocol/openid-connect/token
# OIDC_USERINFO_URI=https://auth.yourdomain.com/realms/master/protocol/openid-connect/userinfo
# OIDC_LOGOUT_URI=https://auth.yourdomain.com/realms/master/protocol/openid-connect/logout
# OIDC_DISPLAY_NAME=SSO Login

Generate secrets:

openssl rand -hex 32  # SECRET_KEY
openssl rand -hex 32  # UTILS_SECRET

Step 4: Start Outline

docker compose up -d

# Run database migrations
docker exec outline node build/server/scripts/seed.js

Step 5: Reverse Proxy (Caddy)

# /etc/caddy/Caddyfile
wiki.yourdomain.com {
    reverse_proxy localhost:3000
}
sudo systemctl restart caddy

Step 6: Organize Your Wiki

Recommended collection structure:

CollectionPurpose
📋 CompanyMission, values, org chart, policies
🚀 EngineeringArchitecture, runbooks, onboarding
📊 ProductSpecs, roadmap, user research
💼 SalesPlaybooks, pricing, case studies
👋 OnboardingNew hire guides, setup instructions
📝 Meeting NotesStandups, retros, all-hands

Tips:

  • Use templates for recurring documents (meeting notes, RFCs, postmortems)
  • Star important documents for quick access
  • Use / commands in the editor for blocks, embeds, tables
  • Drag and drop to reorder documents and collections

Step 7: Integrations

IntegrationSetup
SlackSettings → Integrations → Slack (notifications + search)
Zapier/n8nUse Outline's API with webhooks
Import from NotionSettings → Import → Notion (native importer)
Import from ConfluenceSettings → Import → Confluence

Production Hardening

Backups:

# Database backup (daily cron)
docker exec outline-db pg_dump -U outline outline > /backups/outline-$(date +%Y%m%d).sql

# MinIO data backup
docker run --rm -v minio_data:/data -v /backups:/backup alpine \
  tar czf /backup/outline-files-$(date +%Y%m%d).tar.gz /data

Updates:

docker compose pull
docker compose up -d

Performance:

  • Increase DATABASE_CONNECTION_POOL_MAX for larger teams
  • Add PostgreSQL connection pooling (PgBouncer) for 100+ users
  • Consider CDN for MinIO assets

Resource Usage

UsersRAMCPUDisk
1-202 GB2 cores10 GB
20-504 GB2 cores20 GB
50-2008 GB4 cores50 GB

VPS Recommendations

ProviderSpec (30 users)Price
Hetzner4 vCPU, 8 GB RAM€8/month
DigitalOcean2 vCPU, 4 GB RAM$24/month
Linode2 vCPU, 4 GB RAM$24/month

Why Self-Host Outline

Outline Cloud's pricing scales with seats: the Team plan is $10/user/month, which means a 15-person company pays $150/month or $1,800/year. Notion charges $15/user/month for the Business plan. At 15 users, that's $2,700/year. Confluence Cloud is similarly priced at $8.15/user/month, and the costs compound as teams grow. Self-hosted Outline, by contrast, costs only your server bill — typically $8–20/month on a Hetzner or DigitalOcean instance regardless of how many users you add.

The math is stark for growing teams. A 30-person company self-hosting Outline pays approximately $100/year in infrastructure versus $3,600/year on Outline Cloud. Within the first year, the investment in setting up self-hosting pays back many times over.

Data ownership and compliance: Confluence and Notion route your company's internal knowledge — architecture docs, HR policies, customer data — through third-party infrastructure. For companies in regulated industries or jurisdictions with strict data residency requirements, this creates compliance risk. Self-hosting Outline means your wiki data never touches Atlassian's or Notion's servers. Legal, healthcare, and financial services teams often require this.

Customization: Self-hosted Outline lets you configure storage backends, authentication providers, and retention policies in ways the cloud product doesn't allow. You can pair it with self-hosted Keycloak for SSO, MinIO for on-premises file storage, and your own SMTP server for complete infrastructure independence.

When NOT to self-host Outline: If your team has fewer than 5 people, the free tiers on competing products may serve you well enough. Outline's setup is more involved than most self-hosted tools — it requires MinIO (or AWS S3) for file storage and an external OIDC provider for authentication; there is no simple username/password login. If you don't have someone comfortable managing Docker services, consider whether the operational overhead is worth it. For very small teams with no DevOps capacity, Notion's free tier or GitHub Wikis may be the pragmatic choice.

Prerequisites (Expanded)

Before deploying Outline in a production environment, it helps to understand why each requirement matters rather than treating the list as a checklist to rush through.

VPS with 2 GB RAM minimum: Outline is a Node.js application that loads a sizable JavaScript bundle on startup. With only 1 GB RAM, the process risks OOM-killing under moderate load, especially during database migrations or after a fresh deployment. For teams larger than 10 people, start with 4 GB. Ubuntu 22.04 LTS is the recommended OS — it has long-term support through 2027, wide community knowledge, and predictable package versions. Avoid running on cutting-edge distros in production; stability matters more than novelty.

Docker and Docker Compose: Outline's setup expects Docker Compose v2+ (the docker compose subcommand, not the legacy docker-compose). Verify with docker compose version before starting. The Compose file orchestrates four containers — Outline, PostgreSQL, Redis, and MinIO — as a single unit.

S3-compatible storage: Outline stores all file attachments (images, PDFs, documents) in an S3-compatible bucket. This is not optional. The most common self-hosted choice is MinIO, which we've included in the Compose file above. Alternatively, you can use a real AWS S3 bucket, Cloudflare R2, or Backblaze B2 — all are S3-compatible.

OIDC provider: This is the most common stumbling block. Outline has no built-in password login; it delegates authentication entirely to an external provider. If your team uses Google Workspace, GitHub, or Microsoft 365, this is straightforward. If you want a fully self-hosted solution, pair Outline with self-hosted Keycloak or Authentik.

When choosing a VPS, providers like Hetzner (Europe) and Vultr offer good value for small teams. See our VPS comparison for self-hosters for a full breakdown of providers, pricing, and network performance that will help you make the right infrastructure choice.

Production Security Hardening

Running Outline in production means you're protecting your company's internal knowledge base. Weak security here has real consequences — a compromised wiki exposes architecture docs, credentials that got accidentally pasted, and sensitive business information.

Firewall with UFW: Lock down your server to only the ports that need to be publicly accessible.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP (for Caddy's ACME challenge)
sudo ufw allow 443/tcp   # HTTPS
sudo ufw enable

Never expose PostgreSQL (5432), Redis (6379), or MinIO (9000/9001) to the public internet. These ports should only be reachable within Docker's internal network.

Fail2ban for SSH protection: Brute-force attacks on SSH are constant background noise on any public server.

sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local to set maxretry = 3 and bantime = 3600 under [sshd]. Restart with sudo systemctl restart fail2ban.

Keep secrets out of docker-compose.yml: Never hardcode passwords or secret keys directly in the Compose file. The .env file approach used in this guide is correct — but make sure .env is never committed to version control. Add it to .gitignore. For additional security, consider using Docker secrets or a secrets manager for production deployments.

Disable SSH password authentication: Once you have SSH key-based access working, disable password auth entirely:

sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd

Automatic security updates: Enable unattended upgrades to patch the OS automatically:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

This handles kernel patches, OpenSSL updates, and other security fixes without manual intervention. Limit it to security updates only to avoid accidental application breakage.

Disable Outline signups after setup: Once your team accounts are created, set WIKI_RESTRICTED_DOMAIN in your .env file so only email addresses from your domain can register — or use OIDC authentication scoped to your identity provider, which handles this automatically.

For a complete server hardening checklist beyond what's covered here, see our self-hosting security checklist, which covers certificate pinning, log monitoring, and intrusion detection for self-hosted services.

Troubleshooting Common Issues

Outline container exits immediately on startup

This almost always means a missing or incorrectly formatted .env variable. Outline is strict about its required configuration.

docker compose logs outline

Look for lines like Error: Missing required environment variable: SECRET_KEY. The most common culprits are a SECRET_KEY that's too short (must be 32+ chars), an invalid DATABASE_URL format, or a URL that doesn't include the protocol (https://).

Files and images won't upload

Outline will log Error: connect ECONNREFUSED minio:9000 if MinIO isn't running or reachable. Check:

docker compose ps
docker compose logs minio

If MinIO is running, verify the bucket exists and the bucket policy allows the Outline service account to write. Log into the MinIO console at http://your-server:9001 and confirm the outline bucket is present and the access policy is set to allow the credentials in your .env.

OIDC authentication fails after clicking "Sign in with Google"

If you're redirected back to the login page with no error, check that your OAuth callback URL exactly matches what you registered in your identity provider. For Google, the authorized redirect URI must be https://wiki.yourdomain.com/auth/oidc.callback — the trailing path matters. Also verify that GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env match your Google Cloud Console credentials.

Real-time collaboration isn't working (changes don't sync)

Outline uses WebSockets for real-time collaboration. If edits don't appear live across multiple browser tabs, your reverse proxy may be stripping WebSocket upgrade headers. With Caddy, this is handled automatically. If you're using Nginx, add the following to your proxy configuration:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Database migration fails on first run

If docker exec outline node build/server/scripts/seed.js exits with a PostgreSQL connection error, the database container may still be initializing. Wait 10 seconds and try again. You can watch the DB startup with docker compose logs postgres. The database is ready when you see database system is ready to accept connections.

MinIO console is accessible from the internet

By default, MinIO's admin console runs on port 9001. If you've opened this port in your firewall, it's publicly accessible with only the MinIO root credentials standing between attackers and your files. Close port 9001 in UFW immediately. Access the MinIO console only by SSH tunneling: ssh -L 9001:localhost:9001 user@your-server.

For Outline deployed at team scale, monitoring the application health proactively is important. The application exposes a /api/health endpoint — add it to your Uptime Kuma instance to get alerted if the Outline service becomes unavailable. Additionally, monitor your PostgreSQL instance for slow queries as the wiki grows: Outline's full-text search relies on PostgreSQL's built-in text search capabilities, and large wikis (over 5,000 documents) can develop slow query issues if the database isn't properly vacuumed and indexed. Schedule a weekly VACUUM ANALYZE job to keep PostgreSQL's statistics current and queries fast. These maintenance steps take under an hour to set up and prevent the most common performance degradation issues that large Outline deployments encounter.

See the VPS comparison for self-hosters to choose the right server for your Outline deployment.

Set up automated server backups with restic to protect your Outline database and MinIO file storage.

Review the self-hosting security checklist before going to production.

Compare wiki and knowledge base tools on OSSAlt — features, import support, and pricing side by side.

See open source alternatives to Outline on OSSAlt.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.