lang: zh slug: outline-wiki-knowledge-base title: ‘Outline: The Open-Source Wiki & Knowledge Base Built for’ description: ‘Deploy Outline with Docker in 10 minutes. Build a real-time collaborative wiki for your engineering team with Markdown editor, Slack integration, full-text search, and granular permissions.’ tags: [“guide”, “open-source”, “opensource”, “reference”, “self-hosted”, “tutorial”] date: 2026-05-19 00:00:00+08:00 lastmod: 2026-05-19 00:00:00+08:00 tech_stack: [] application_domain: Dev Utils source_version: ’' licensing_model: Open Source license_type: BSL-1.1 file_size: ’' file_md5: ’' download_url: ’' backup_url: ’' github_repo: ‘outline/outline’ last_maintained: ‘2026-05-19’ draft: false categories: [‘dev-utils’] aliases:- /posts/outline-wiki-knowledge-base/ faqs:
- q: ‘What database and services does Outline require to self-host?’ a: ‘Outline requires three core services: the Node.js app itself, PostgreSQL (for documents, accounts, permissions, and metadata), and Redis (for caching, session storage, and real-time collaboration state). It also needs S3-compatible storage such as MinIO or AWS S3 for file attachments, and an external authentication provider.’
- q: ‘Does Outline support a local username and password login?’ a: ‘No. Outline has no built-in username/password system and requires an external authentication provider such as Google Workspace, Azure AD, Slack, or a generic OIDC/SAML provider. Self-hosters must configure SSO before the instance will work.’
- q: ‘What open-source license does Outline use, and is commercial use restricted?’ a: ‘Outline uses the Business Source License 1.1 (BSL-1.1), not a traditional open-source license. Internal use is free, but offering Outline as a competing hosted cloud service requires a commercial license.’
- q: ‘How does Outline resolve concurrent editing conflicts?’ a: ‘Outline uses Operational Transforms (OT) over a WebSocket connection, the same approach Google Docs uses. When two users edit the same document, both users’’ changes are merged in real time with conflict resolution typically completing within about 50ms, avoiding last-write-wins data loss.’
- q: ‘How can I make an Outline document publicly accessible?’ a: ‘Open the document, go to Share and select Publish to Internet to generate a read-only public URL that requires no authentication. Public documents are indexed by search engines unless you add a noindex tag, making this useful for API docs, user guides, or open-source wikis.’
- React Frontend — Client-side rendered SPA with a ProseMirror-based rich text editor
- PostgreSQL — Stores documents, user accounts, permissions, and metadata
- Redis — Caching, session store, and real-time collaboration state via WebSocket
- S3-Compatible Storage — File attachments (MinIO for self-hosted, AWS S3 for cloud)
- ElasticSearch or Postgres FTS — Full-text document searchReal-time collaboration uses Operational Transforms (OT) through a WebSocket connection. When two users edit the same document, changes propagate in milliseconds with conflict resolution that actually works — no last-write-wins headaches.The permission system is the standout feature. Collections can be:
- Public to team — anyone with an account can read
- Private — only invited users can access
- Read-only — team can view but not edit
- Editor access — specific users or groups can modifyDocuments inherit collection permissions but can override them individually. This maps cleanly to how engineering teams work: runbooks are public, architecture docs are team-accessible, and incident post-mortems are restricted.## Installation & Setup: Production Docker DeployOutline requires three services: the app, PostgreSQL, and Redis. A production-ready Docker Compose setup:``` yam l
version: “3.8”
services: outline: image: outlinewiki/outline:0.83.0 ports: - “3000:3000” environment: - DATABASE_URL=postgres://outline:outline_password@postgres:5432/outline - DATABASE_URL_TEST=postgres://outline:outline_password@postgres:5432/outline-test - REDIS_URL=redis://redis:6379 - SECRET_KEY=${SECRET_KEY} - UTILS_SECRET=${UTILS_SECRET} - URL=https://wiki.yourcompany.com - PORT=3000 - AWS_ACCESS_KEY_ID=minio - AWS_SECRET_ACCESS_KEY=minio123 - 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 - FILE_STORAGE=local - OIDC_CLIENT_ID=${OIDC_CLIENT_ID} - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET} - OIDC_AUTH_URI=${OIDC_AUTH_URI} - OIDC_TOKEN_URI=${OIDC_TOKEN_URI} - OIDC_USERINFO_URI=${OIDC_USERINFO_URI} - OIDC_LOGOUT_URI=${OIDC_LOGOUT_URI} - OIDC_DISPLAY_NAME=Google Workspace - SLACK_CLIENT_ID=${SLACK_CLIENT_ID} - SLACK_CLIENT_SECRET=${SLACK_CLIENT_SECRET} - SLACK_VERIFICATION_TOKEN=${SLACK_VERIFICATION_TOKEN} depends_on: - postgres - redis - minio restart: unless-stopped
postgres: image: postgres:16-alpine environment: - POSTGRES_USER=outline - POSTGRES_PASSWORD=outline_password - POSTGRES_DB=outline volumes: - postgres-data:/var/lib/postgresql/data restart: unless-stopped
redis: image: redis:7-alpine volumes: - redis-data:/data restart: unless-stopped
minio: image: minio/minio:RELEASE.2026-04-01T00-00-00Z command: server /data –console-address “:9001” environment: - MINIO_ROOT_USER=minio - MINIO_ROOT_PASSWORD=minio123 volumes: - minio-data:/data restart: unless-stopped
Create buckets on first run #
minio-createbucket: image: minio/mc:latest depends_on: - minio entrypoint: > /bin/sh -c " sleep 10; mc alias set local http://minio:9000 minio minio123; mc mb local/outline || true; mc anonymous set private local/outline; exit 0; "
volumes:
postgres-data:
redis-data:
minio-data:
### Generating SecretsBefore starting, generate the required secrets:
bas
h
Generate a 256-bit secret key #
export SECRET_KEY=$(openssl rand -hex 32)# Generate utils secret export UTILS_SECRET=$(openssl rand -hex 16)echo “SECRET_KEY=$SECRET_KEY” echo “UTILS_SECRET=$UTILS_SECRET”
d
d
these to a `.env` file:```
bas
h
cat << 'EOF' > .env
SECRET_KEY=REPLACE_WITH_GENERATED_SECRET
UTILS_SECRET=REPLACE_WITH_GENERATED_SECRET
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_VERIFICATION_TOKEN=
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
EOF
chmod 600 .env
```### Start the Stack```
bas
h
docker-compose up -d# Check all services are healthy
docker-compose ps# View logs
docker-compose logs -f outline
```Af
t
e
r
~30 seconds, Outline is available at `http://localhost:3000`.### Setting Up AuthenticationOutline requires an external authentication provider. The easiest production setup is Google Workspace OIDC:1. Go to [Google Cloud Console](https://console.cloud.google.com/) → APIs & Services → Credentials
2. Create **OAuth 2.0 Client ID** (Web application)
3. Add authorized redirect URI: `https://wiki.yourcompany.com/auth/oidc.callback`
4. Add the client ID and secret to your `.env` file:```
bas
h
OIDC_CLIENT_ID=xxx.apps.googleusercontent.com
OIDC_CLIENT_SECRET=GOCSPX-xxx
OIDC_AUTH_URI=https://accounts.google.com/o/oauth2/v2/auth
OIDC_TOKEN_URI=https://oauth2.googleapis.com/token
OIDC_USERINFO_URI=https://openidconnect.googleapis.com/v1/userinfo
OIDC_LOGOUT_URI=https://accounts.google.com/logout
```Rest
a
r
t
Outline:```
bas
h
docker-compose restart outline
```### Quick Deploy on DigitalOceanFor teams without an existing Docker setup, deploy on DigitalOcean
:```
bas
h
# On a fresh Ubuntu 24.04 Droplet ($6/month)
sudo apt update && sudo apt install -y docker.io docker-compose-plugin# Clone and start
git clone https://github.com/outline/outline.git
cd outline
# Copy the docker-compose.yml above, configure .env, then:
docker compose up -d
```Alternative
l
y
, use HTStack
for a managed Outline deployment with built-in SSL and backups.## Integration with Your Engineering Stack### Slack Integration (Deep Link)Outline's Slack integration is one of its strongest features:1. Go to [Slack API Apps]```
bas
h
# Generate a 256-bit secret key
export SECRET_KEY=$(openssl rand -hex 32)
# Generate utils secret
export UTILS_SECRET=$(openssl rand -hex 16)
echo "SECRET_KEY=$SECRET_KEY"
echo "UTILS_SECRET=$UTILS_SECRET"
```comma
n
d
: /outline
url: https://wiki.yourcompany.com/api/hooks.slack
description: Search your knowledge base
usage_hint: "[search query]"
should_escape: false
oauth_config:
redirect_urls:
- https://wiki.yourcompany```
bas
h
cat << 'EOF' > .env
SECRET_KEY=REPLACE_WITH_GENERATED_SECRET
UTILS_SECRET=REPLACE_WITH_GENERATED_SECRET
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_VERIFICATION_TOKEN=
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
EOF
chmod 600 .env
```r
g
_deploy_enabled: true
socket_mode_enabled: false
```3. Install the app to your workspace
4. Copy the Bot User OAuth Token and Verification Token to your `.env`
5. Restart OutlineOnce connected, type `/outline deploy rollback` in Slack to inst```
bas
h
docker-compose up -d
# Check all services are healthy
docker-compose ps
# View logs
docker-compose logs -f outline
```owle
d
g
e
base:```
bas
h
# List all collections
curl -X GET "https://wiki.yourcompany.com/api/collections" \
-H "Authorization: Bearer YOUR_API_TOKEN"# Create a new document
curl -X POST "https://wiki.yourcompany.com/api/documents.create" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Incident Response Runbook",
"text": "## Overview\n\nThis document covers...",
"collectionId": "123e4567-e89b-12d3-a456-426614174000",
"publish": true
}'# Search documents
curl -X POST "https://wiki.yourcompany.com/api/documents.search" \
-H "Authoriza```
bas
h
OIDC_CLIENT_ID=xxx.apps.googleusercontent.com
OIDC_CLIENT_SECRET=GOCSPX-xxx
OIDC_AUTH_URI=https://accounts.google.com/o/oauth2/v2/auth
OIDC_TOKEN_URI=https://oauth2.googleapis.com/token
OIDC_USERINFO_URI=https://openidconnect.googleapis.com/v1/userinfo
OIDC_LOGOUT_URI=https://accounts.google.com/logout
```o
c
s
.yml
name: Publish API Docs to Outlineon:
push:
branches: [main]
paths:
- 'docs/**'jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 - name: Publish to Outline
run: |
DOCS=$(cat docs/api-reference.md)
curl -X POST "https://wiki.you```
bas
h
docker-compose restart outline
``` -H "Authorization: Bearer ${{ secrets.OUTLINE_API_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{
\"id\": \"DOC_ID_HERE\",
\"text\": $(echo "$DOCS" |```
bas
h
# On a fresh Ubuntu 24.04 Droplet ($6/month)
sudo apt update && sudo apt install -y docker.io docker-compose-plugin
# Clone and start
git clone https://github.com/outline/outline.git
cd outline
# Copy the docker-compose.yml above, configure .env, then:
docker compose up -d
```o
l
s
→ Content Tools → Export → XML format# Import into Outline:
# Collection → Import → Upload Markdown/ZIP file
# Outline preserves heading structure and converts Notion databases to tables
```## Benchmarks & Real-World Use Cases### Performance BenchmarksTested on a $6/month DigitalOcean Droplet (1 vCPU, 1GB RAM):| Metric | Result |
|---|
featureImage: /images/articles/outline-the-open-source-wiki-knowledge-b.jpg
---|
| Time to first document load | **~180ms** |
| Real-time sync latency (2 editors) | **~45ms** |
| Full-text search (10,000 docs) | **~80ms** average |
| Document import (100 Markdown files) | **~12 seconds** |
| Concurrent users (comfortable) | **~50** |
| Startup time (Docker Compose) | **~25 seconds** |### Real-World Deployments- **30```
yam
l
_display_name: Outline Wiki
features:
bot_user:
display_name: Outline
always_online: true
slash_commands:
- command: /outline
url: https://wiki.yourcompany.com/api/hooks.slack
description: Search your knowledge base
usage_hint: "[search query]"
should_escape: false
oauth_config:
redirect_urls:
- https://wiki.yourcompany.com/auth/slack.callback
scopes:
bot:
- commands
- links:read
- links:write
settings:
event_subscriptions:
request_url: https://wiki.yourcompany.com/api/hooks.slack
bot_events:
- link_shared
org_deploy_enabled: true
socket_mode_enabled: false
``` **Active releases**: Monthly cadence## Advanced Usage: Production Hardening### 1. HTTPS with Let's Encrypt```
ngin
x
# /etc/nginx/sites-available/outline
server {
listen 80;
server_name wiki.yourcompany.com;
return 301 https://$server_name$request_uri;
}server {
listen 443 ssl http2;
server_name wiki.yourcompany.com; ssl_certificate /etc/letsencrypt/live/yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourcompany.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on; location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
bas h
List all collections #
curl -X GET “https://wiki.yourcompany.com/api/collections"
-H “Authorization: Bearer YOUR_API_TOKEN”
Create a new document #
curl -X POST “https://wiki.yourcompany.com/api/documents.create"
-H “Authorization: Bearer YOUR_API_TOKEN”
-H “Content-Type: application/json”
-d ‘{
“title”: “Incident Response Runbook”,
“text”: “## Overview\n\nThis document covers…”,
“collectionId”: “123e4567-e89b-12d3-a456-426614174000”,
“publish”: true
}’
Search documents #
curl -X POST “https://wiki.yourcompany.com/api/documents.search"
-H “Authorization: Bearer YOUR_API_TOKEN”
-H “Content-Type: application/json”
-d ‘{“query”: “rollback procedure”}’
e
s
s
zip -r "$BACKUP_DIR/outline_full_$TIMESTAMP.zip" \
"$BACKUP_DIR/outline_db_$TIMESTAMP.sql" \
"/var/lib/docker/volumes/outline_minio-data/_data"# Upload to S3
aws s3 cp "$BACKUP_DIR/outline_full_$TIMESTAMP.zip" \
s3://yourcompany-backups/outline/# Keep only last 14 backups
ls -t "$BACKUP_DIR"/outline_full_*.zip | tail -n +15 | xargs -r rmecho "Backup completed: outline_full_$TIMESTAMP.zip"
bas h
Run daily at 3 AM #
0 3 * * * /opt/backup/outline-backup.sh » /var/log/outline-backup.log 2>&1
### 3. Monitoring Stack
yam
l
docker-compose.monitoring.yml #
services: prometheus: image: prom/prometheus:v2.51.0 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus ports: - “9090:9090” restart: unless-stopped grafana: image: grafana/grafana:10.4.0 ``` bas h #!/bin/bash
.github/workflows/publish-docs.yml #
name: Publish API Docs to Outline
on: push: branches: [main] paths: - ‘docs/**’
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Publish to Outline
run: |
DOCS=$(cat docs/api-reference.md)
curl -X POST "https://wiki.yourcompany.com/api/documents.update" \
-H "Authorization: Bearer ${{ secrets.OUTLINE_API_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{
\"id\": \"DOC_ID_HERE\",
\"text\": $(echo "$DOCS" | jq -R -s .),
\"append\": false
}"
_ID
AWS_SECRET_ACCESS_KEY=YOUR_B2_APPLICATION_KEY
AWS_REGION=us-west-002
AWS_S3_UPLOAD_BUCKET_URL=https://s3.us-west-002.backblazeb2.com
AWS_S3_UPLOAD_BUCKET_NAME=your-outline-bucket
AWS_S3_FORCE_PATH_STYLE=false
```### 5. Multi-Environment Setup```
yam
l
# docker-compose.prod.yml — extends base with production config
services:
outline:
image: outlinewiki/outline:0.83.0
environment:
- NODE_ENV=production
- FORCE_HTTPS=true
- RATE_LIMITER_ENABLED=true
- DEFAULT_LANGUAGE=en_US
- WEB_CONCURRENCY=2
deploy:
replicas: 2
resources:
limits:
memory: 1G
reservations:
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/utils.health"```
bas
h
# Export from Notion:
# Settings & Members → Settings → Export All Workspace Content → Export as Markdown
# Export from Confluence:
# Space Tools → Content Tools → Export → XML format
# Import into Outline:
# Collection → Import → Upload Markdown/ZIP file
# Outline preserves heading structure and converts Notion databases to tables
```* | Yes | Yes | Yes (paid) | No | No |
| **Slack integration** | **Native, deep** | Basic | Yes | No | No |
| **Markdown editor** | **ProseMirror** | Partial | No | WYSIWYG | Yes |
| **Full-text search** | **Yes** (Postgres/ES) | Yes | Yes | Basic | Yes |
| **API access** | **Full REST** | Limited | Yes | Limited | GraphQL |
| **Permissions** | **Granular** | Basic | Enterprise | Simple | Simple |
| **Mobile app** | No (responsive web) | Yes | Yes | No | No |
| **Git sync** | No | No | No | No | **Yes** |
| **Price (20 users)** | **$0 (self-host)** | $192/mo | $525/mo | $0 | $0 |
| **GitHub stars** | **32,000** | N/A | N/A | 8,100 | 24,500 |**When to choose Outline over each:**- **vs. Notion**: You need self-hosting for compliance/data sovereignty, want faster search, or need native Slack integration. Notion has better templates and mobile apps.
- **vs. Confluence**: You want a modern editor, faster performance, and lower cost. Confluence has better Jira integration and enterprise compliance certifications.
- **vs. BookStack**: You need real-time collaboration and Slack integration. BookStack is simpler to set up but lacks collaborative editing.
- **vs. Wiki.js**: You want a polished, Notion-like editor. Wiki.js has Git sync and more authentication options, but v3.0 has been in alpha for years.## Limitations: Honest Assessment**Outline is not without its downsides.** Before migrating your entire team's documentation:1. **BSL-1.1 License**: Outline uses the Business Source License, not a traditional open-source license. Internal use is free. Offering Outline as a competing cloud serv```
ngin
x
# /etc/nginx/sites-available/outline
server {
listen 80;
server_name wiki.yourcompany.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name wiki.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourcompany.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}
# WebSocket support for real-time collaboration
location /realtime {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
```l
i
n
e
without Google Workspace or external SSO?Not practically. Outline requires an external authentication provider and has no built-in username/password system. The simplest alternative is configuring a generic OIDC provider like Keycloak or using the Slack authentication option. For small teams, Google Workspace's free tier works well.### How does Outline handle concurrent editing conflicts?Outline uses Operational Transforms (OT) — the same algorithm Google Docs uses. When two users edit the same document simultaneously, changes are merged in real-time with proper conflict resolution. Unlike simple last-write-wins systems, OT preserves both users' edits. In practice, conflicts are resolved within 50ms and are invisible to users.### What is the backup strategy for a self-hosted Outline instance?Back up three components: (1) the PostgreSQL database using `pg_dump`, (2) the uploaded files from your S3-compatible store (MinIO or AWS S3), and (3) the Redis data (optional, can be rebuilt). A daily cron job dumping the database and syncing files to external storage covers most recovery scenarios. Test your restores quarterly.### Can I import docume```
bas
h
#!/bin/bash
# /opt/backup/outline-backup.sh
set -euo pipefail
BACKUP_DIR="/backups/outline"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# Backup PostgreSQL
docker exec outline-postgres-1 pg_dump -U outline outline > \
"$BACKUP_DIR/outline_db_$TIMESTAMP.sql"
# Backup uploaded files (MinIO S3)
docker exec outline-minio-1 mc mirror local/outline \
"local/backup-outline-files-$TIMESTAMP"
# Compress
zip -r "$BACKUP_DIR/outline_full_$TIMESTAMP.zip" \
"$BACKUP_DIR/outline_db_$TIMESTAMP.sql" \
"/var/lib/docker/volumes/outline_minio-data/_data"
# Upload to S3
aws s3 cp "$BACKUP_DIR/outline_full_$TIMESTAMP.zip" \
s3://yourcompany-backups/outline/
# Keep only last 14 backups
ls -t "$BACKUP_DIR"/outline_full_*.zip | tail -n +15 | xargs -r rm
echo "Backup completed: outline_full_$TIMESTAMP.zip"
```ib
l
e
?Yes. Any document can be shared via a public link with read-only access. Go to **Share** → **Publish to Internet** to generate a public URL. This is useful for API documentation, user guides, or open-source project wikis. Public documents do not require authentication and are indexed by search engines unless you add a `noindex` tag.### Can I integrate Outline with my CI/CD pipeline?Yes, via the REST API. Generate an API token from **Settings** → **API**, then use it in GitHub Actions, GitLab CI, or any CI tool to publish documentation updates automatically. A common pattern is committing Markdown files to a `docs/` directory in your Git repo, then having CI push them to Outline on every merge to main.## Conclusion: Own Your Team's KnowledgeDocumentation is not a side project. It is infrastructure. Eve```
bas
h
# Run daily at 3 AM
0 3 * * * /opt/backup/outline-backup.sh >> /var/log/outline-backup.log 2>&1
```a
t
is outdated is a new hire who cannot contribute for an extra week.Outline gives engineering teams a **self-hosted, real-t```
yam
l
# docker-compose.monitoring.yml
services:
prometheus:
image: prom/prometheus:v2.51.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
restart: unless-stopped
grafana:
image: grafana/grafana:10.4.0
volumes:
- grafana-data:/var/lib/grafana
- ./grafana-dashboards:/etc/grafana/provisioning/dashboards
ports:
- "3001:3000"
restart: unless-stopped
node-exporter:
image: prom/node-exporter:v1.7.0
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.rootfs=/rootfs'
- '--path.sysfs=/host/sys'
restart: unless-stopped
volumes:
prometheus-data:
grafana-data:
```*Join the community**: [Outline GitHub](https://github.com/outline/outline) | [Outline Discussions](https://github.com/outline/outline/discussions)**Related tools**: Keycloak SSO Setup | MinIO S3 Setup Guide---
## Recommended Hosting & InfrastructureBefore you deploy any of the tools above into production, you'll need solid infrastructure. Two options dibi8 actually uses and recommends:- **DigitalOcean
** — $200 free credit for 60 days across 14+ global regions. The default option for indie devs running open-source AI tools.
- **HTStack
** — Hong Kong VPS with low-latency access from mainland China. This is the same IDC that hosts dibi8.com — battle-tested in production.*Affiliate links — they don't cost you extra and they help keep dibi8.com running.*## Sources & Further Reading- [Outline Official Documentation](h```
bas
h
# .env additions for Backblaze B2
AWS_ACCESS_KEY_ID=YOUR_B2_KEY_ID
AWS_SECRET_ACCESS_KEY=YOUR_B2_APPLICATION_KEY
AWS_REGION=us-west-002
AWS_S3_UPLOAD_BUCKET_URL=https://s3.us-west-002.backblazeb2.com
AWS_S3_UPLOAD_BUCKET_NAME=your-outline-bucket
AWS_S3_FORCE_PATH_STYLE=false
```s
://www.postgresql.org/docs/16/)
- [Redis Official Documentation](https://redis.io/docs/)
- [MinIO Documentation](https://min.io/docs/)
- [Google OIDC Setup Guide](https://developers.google.com/identity/protocols/oauth2/openid-connect)---*This article may contain affiliate links. If you sign up for DigitalOc```
yam
l
# docker-compose.prod.yml — extends base with production config
services:
outline:
image: outlinewiki/outline:0.83.0
environment:
- NODE_ENV=production
- FORCE_HTTPS=true
- RATE_LIMITER_ENABLED=true
- DEFAULT_LANGUAGE=en_US
- WEB_CONCURRENCY=2
deploy:
replicas: 2
resources:
limits:
memory: 1G
reservations:
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/utils.health"]
interval: 30s
timeout: 10s
retries: 3
```he
u
s
)
- [Grafana](https://github.com/grafana/grafana)
💬 留言讨论