Outline Wiki 自架教學(一):Docker 安裝、Gitea OIDC 與 AI 知識庫準備
本篇要解決的問題
公司開發團隊裡,想架一套內部的知識庫,又要能支援 AI,常見的痛點有幾個:
- 文件資料留在自己的機器上,不對外,以免洩露商業機密。
- 想要加上 AI?得付 $$,比如 Notion,或是也可以自架的 Docmost。
- Outline Wiki 裝起來很難,August 失敗過一次,最後是靠 Claude Opus 4.8 的輔助才成功。
本篇筆記文,會用一份 Docker Compose 檔,把 Outline,以及需要的 PostgreSQL、Redis、Caddy 全包進去,並針對上面這些坑一次閃掉。
另外也先說明本文裡的基本設定:
- 本機已裝好 Docker。
- 對內 PORT 是
3002,對外是3001。
關於 Outline + AI 的補充說明:
自架版 Outline 沒有內建的「AI Answers」功能,網路上常看到的 OPENAI_API_KEY 對自架版是無效的。想要 Outline 加上 AI,正解是用 MCP 外接,讓 Claude / Codex 透過 Outline 的 API 來操作(作法將寫在下一篇)。
步驟 1:安裝 Gitea
第一個管理員帳號要用 Gitea 登入,所以得先有一台 Gitea。
Gitea 本身也能用 Docker 自架,這部分 August 之前寫過,直接看這篇:
只要你的 Gitea 已經能正常登入,就可以往下走。
Outline 並不限定 Gitea,任何相容 OIDC 的供應商(Keycloak、Authentik、Google⋯)都行,差別只在 OIDC_* 那幾個網址。
步驟 2:從 Gitea 取得 Client ID 與 Secret
Outline 走 OIDC 登入,需要在 Gitea 建立一個「OAuth2 應用程式」,拿到 Client ID 和 Client Secret。
進入 Gitea 後,到 設定(Settings)→ 應用程式(Applications),找到「管理 OAuth2 應用程式」區塊。
在 Gitea 的「設定 → 應用程式」頁面,找到「管理 OAuth2 應用程式」的建立表單
需要填兩個欄位:
- 應用程式名稱:填一個自己記得註是做什麼的名稱,如:
Outline Wiki Login。 - 重新導向 URI:要填的 PORT 是有對外加上憑證,比如本篇用的是
3001。
https://<你的IP或網域>:3001/auth/oidc.callback
例如主機 IP 是 192.168.11.111,就填 https://192.168.11.111:3001/auth/oidc.callback。這個 IP 與埠號要跟等一下 Compose 裡的 URL= 完全一致。
Gitea OAuth2 應用程式表單,填入應用程式名稱與重新導向 URI(重點是 Redirect URI 結尾為 /auth/oidc.callback)
按下「建立應用程式」後,Gitea 會顯示 Client ID 與 Client Secret。
Gitea 建立完成後顯示的 Client ID 與 Client Secret 畫面。
要注意,Client Secret 只會完整顯示這一次,先複製存好。等一下要填進 Compose 的 OIDC_CLIENT_ID 與 OIDC_CLIENT_SECRET。
步驟 3-1:安裝 Outline Wiki:Windows 版
Windows 用 Docker Desktop,這裡用具名 volume(由 Docker 管理)存附件,啟動最單純。
先新增一個空資料夾,接著我們要放進下面的 2 個檔案。
Caddyfile
資料夾內新增一個檔案,檔名:Caddfile。
Caddyfile 負責「對外用 HTTPS、把流量轉給 Outline」。
檔案內容複製貼上以下,再把 192.168.11.111 換成我們 Windows 主機的區網 IP:
{
default_sni 192.168.11.111
}
192.168.11.111:3001 {
tls internal
reverse_proxy outline:3002
}
-
tls internal:Caddy 自己簽一張憑證。因為我們用的是區網 IP,本來就申請不到正式憑證,自簽夠用。 -
3001是對外埠、outline:3002是 Outline 容器內部埠,兩者分工,注意不能寫成一樣。
docker-compose.yml
資料夾內再新增一個檔案,檔名:docker-compose.yml。
檔案內容複製貼上以下:
# =============================================================================
# Outline Wiki — Docker Compose 教學範例
# =============================================================================
# 架構:
# outline → 主應用 (Node.js)
# caddy → 反向代理 + 自動 HTTPS
# postgres → 資料庫
# (外部) → Redis,負責快取 / WebSocket / 背景工作佇列
#
# ⚠️ 發佈前務必把所有 <...> 佔位符換成你自己的值。
# 範例裡的密鑰、密碼、IP 全是假的,不要直接拿去用。
# =============================================================================
services:
# ---------------------------------------------------------------------------
# Outline 主應用
# ---------------------------------------------------------------------------
outline:
image: outlinewiki/outline:latest
container_name: outline
restart: unless-stopped
environment:
- NODE_ENV=production
# --- 安全密鑰 (必填) ---------------------------------------------------
# 兩把都要用 32-byte 隨機 hex 字串。產生方式:
# openssl rand -hex 32
# ⚠️ 換掉後不要再改,改了會讓既有 session / 加密資料失效。
- SECRET_KEY=<openssl rand -hex 32 產生>
- UTILS_SECRET=<openssl rand -hex 32 產生>
# --- 資料庫連線 (必填) -------------------------------------------------
# 格式:postgres://帳號:密碼@主機:埠/資料庫名
# 主機名 postgres = 下面那個 service 名稱,Docker 內部 DNS 解析。
- DATABASE_URL=postgres://outline_user:<DB_密碼>@postgres:5432/outline
- PGSSLMODE=disable # 同一台 Docker 內部連線,不需 SSL
# --- Redis 連線 (必填) -------------------------------------------------
# 格式:redis://:密碼@主機:埠/DB編號
# 這裡指向下面內建的 redis service,主機名 redis = service 名。
- REDIS_URL=redis://redis:6379/1
# --- 對外網址 (必填) ---------------------------------------------------
# 使用者瀏覽器看到的完整網址,要跟 Caddy / 反代對外位置一致。
- URL=https://<你的網域或IP>:8443
- PORT=3019 # 容器內部監聽埠 (給 Caddy 反代用,不直接對外)
- FORCE_HTTPS=false # HTTPS 由 Caddy 處理,這裡關掉避免重導迴圈
# --- 檔案儲存 (必填) ---------------------------------------------------
# local = 存本機磁碟 (搭配下面 volumes)。也可改 s3 接物件儲存。
- FILE_STORAGE=local
- FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
# 上傳/匯入大小上限 (bytes)。預設約 1MB,匯入大 zip (如從
# Docmost/Notion 匯出) 會跳「file too large」。調大解決。
# 算法: MB × 1048576。下面 = 250MB。
- FILE_STORAGE_UPLOAD_MAX_SIZE=262144000 # 附件上限
- FILE_STORAGE_IMPORT_MAX_SIZE=262144000 # 單篇匯入
- FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE=262144000 # zip 整包匯入 (關鍵)
# --- 登入: Gitea OIDC (選填) -------------------------------------------
# 任何相容 OIDC 的供應商都行 (Gitea / Keycloak / Authentik / Google...)。
# client id/secret 從你的 OIDC 供應商後台拿。
- OIDC_CLIENT_ID=<OIDC_CLIENT_ID>
- OIDC_CLIENT_SECRET=<OIDC_CLIENT_SECRET>
- OIDC_AUTH_URI=http://<OIDC主機>/login/oauth/authorize
- OIDC_TOKEN_URI=http://<OIDC主機>/login/oauth/access_token
- OIDC_USERINFO_URI=http://<OIDC主機>/login/oauth/userinfo
- OIDC_USERNAME_CLAIM=preferred_username # 用哪個欄位當帳號
- OIDC_DISPLAY_NAME=Gitea # 登入按鈕顯示文字
- OIDC_SCOPES=openid profile email
# --- SMTP 寄信 (選填) --------------------------------------------------
# 用途:magic-link 登入信 + 通知信。
# Gmail 範例:密碼要用「應用程式密碼」,不是帳號密碼。
# (Google 帳號 → 安全性 → 兩步驟驗證 → 應用程式密碼)
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=587
- SMTP_SECURE=false # 587 用 STARTTLS,所以這裡 false
- SMTP_USERNAME=<你的gmail@gmail.com>
- SMTP_PASSWORD=<Gmail 應用程式密碼>
- SMTP_FROM_EMAIL=<你的gmail@gmail.com>
- SMTP_REPLY_EMAIL=<你的gmail@gmail.com>
volumes:
# 用具名 volume,由 Docker 管理。注意:這裡存的是「附件/上傳檔」
# (圖片、PDF...),不是文章本體。文章內容存在 PostgreSQL,不是 .md 檔。
- outline_data:/var/lib/outline/data
depends_on:
postgres:
condition: service_healthy # 等 DB 健康檢查通過才啟動 outline
redis:
condition: service_healthy # 等 Redis 就緒
# ---------------------------------------------------------------------------
# Redis — 快取 / WebSocket / 背景工作佇列 (內建獨立 service)
# ---------------------------------------------------------------------------
redis:
image: redis:7-alpine
container_name: outline_redis
restart: unless-stopped
volumes:
- redis_data:/data # 持久化 (選用,Outline 主要當快取,掉了也能重建)
healthcheck:
test: ["CMD", "redis-cli", "ping"] # 回 PONG 才算就緒
interval: 10s
timeout: 5s
retries: 5
# ---------------------------------------------------------------------------
# Caddy — 反向代理,自動處理 HTTPS 憑證
# ---------------------------------------------------------------------------
caddy:
image: caddy:2
container_name: outline_caddy
restart: unless-stopped
ports:
- "8443:8443" # 對外開的埠 (主機:容器)。實際反代規則寫在 Caddyfile。
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro # :ro = 唯讀掛載
- caddy_data:/data # 存 TLS 憑證,別刪,刪了要重新申請
- caddy_config:/config
depends_on:
- outline
# ---------------------------------------------------------------------------
# PostgreSQL
# ---------------------------------------------------------------------------
postgres:
image: pgvector/pgvector:pg16
container_name: outline_postgres
restart: unless-stopped
environment:
# 這三個要跟上面 DATABASE_URL 裡的帳號/密碼/DB名一致。
- POSTGRES_USER=outline_user
- POSTGRES_PASSWORD=<DB_密碼>
- POSTGRES_DB=outline
volumes:
- pg_data:/var/lib/postgresql/data # 資料庫實體資料,千萬別誤刪
ports:
# 只綁 127.0.0.1 = 僅本機可連,不對外曝露 DB。安全做法。
- "127.0.0.1:5432:5432"
healthcheck:
# 確認 DB 真的可接受連線,outline 才會啟動 (見上面 depends_on)。
test: ["CMD-SHELL", "pg_isready -U outline_user -d outline"]
interval: 10s
timeout: 5s
retries: 5
# -----------------------------------------------------------------------------
# 具名 volume — 由 Docker 管理,容器刪掉資料還在。
# -----------------------------------------------------------------------------
volumes:
outline_data:
pg_data:
redis_data:
caddy_data:
caddy_config:
接著要把所有 <...> 的部份換成自己的值,要改這幾項:
-
SECRET_KEY、UTILS_SECRET:開啟終端機,執行兩次openssl rand -hex 32產生 32-byte 隨機字串。沒有 openssl 的話,那就用 Claude、ChatGPT 等 AI,對話中讓它們生成 2 組使用。 -
DATABASE_URL與POSTGRES_PASSWORD:兩邊的密碼要一致。 -
URL:填https://<你的IP>:3001,IP 要跟 Caddyfile 一樣。 -
OIDC_CLIENT_ID、OIDC_CLIENT_SECRET:填上一段從 Gitea 拿到的值。 -
OIDC_AUTH_URI/OIDC_TOKEN_URI/OIDC_USERINFO_URI:把<OIDC主機>換成 Gitea 網址。 - (選填)SMTP:要寄邀請信 / magic-link 才需要填。
啟動
在 docker-compose.yml 所在資料夾開終端機:
docker compose up -d
第一次啟動 Outline 會自動跑資料庫遷移(migration),會需要多等個十幾秒。
看到 outline 正常起來後,瀏覽器打開 https://<你的IP>:3001。
瀏覽器會跳「您的連線不是私人連線 / 不安全」警告。
這是因為 tls internal 用的是自簽憑證,屬於正常現象。點「進階 → 繼續前往」就能進到 Outline。
進站後點 Continue with Gitea 用 Gitea 帳號登入,第一個登入的人就是管理員。
之後的成員,在 Outline 後台用 Email 邀請即可(這也是為什麼上面要設定 SMTP)。
步驟 3-2:安裝 Outline Wiki:Ubuntu 版
Ubuntu 版跟 Windows 版幾乎一樣,只有兩個差別:
-
附件改用 bind mount(
./data):附件直接落在專案資料夾,搬家 / 備份複製整個資料夾就帶走,不必像具名 volume 還要tar撈。 - OIDC 的 Gitea 可以在另一台機器,只要這台 Ubuntu 連得到即可。
檔案
一樣是兩個檔案:docker-compose.yml 和 Caddyfile。
Caddyfile 內容(把 IP 換成你的 Ubuntu 主機 IP):
{
default_sni 192.168.11.111
}
192.168.11.111:3001 {
tls internal
reverse_proxy outline:3002
}
docker-compose.yml 的內容複製貼上以下:
# =============================================================================
# Outline Wiki — Ubuntu 單主機部署版 (教學範例)
# =============================================================================
# 跟 Windows 版的差異:
# 1. 內建 Redis service — 不依賴外部 Redis 主機,一台 Ubuntu 全包。
# 2. 全部服務同一台主機,對外只露 Caddy 的 8443。
# 3. OIDC 仍可指向「另一台」Gitea/OIDC 主機,只要這台網路連得到。
#
# 架構:
# outline → 主應用 (Node.js)
# redis → 快取 / WebSocket / 背景佇列
# caddy → 反向代理 + 自動 HTTPS
# postgres → 資料庫
#
# ⚠️ 發佈前把所有 <...> 佔位符換成你自己的值。範例的密鑰/密碼/IP 全是假的。
#
# 部署步驟:
# 1. 整個資料夾複製到 Ubuntu (含 Caddyfile)。
# 2. 全域搜尋取代 <你的Ubuntu主機IP> → 實際 IP。
# 3. docker compose up -d
# =============================================================================
services:
# ---------------------------------------------------------------------------
# Outline 主應用
# ---------------------------------------------------------------------------
outline:
image: outlinewiki/outline:latest
container_name: outline
restart: unless-stopped
environment:
- NODE_ENV=production
# --- 安全密鑰 (必填) ---------------------------------------------------
# 兩把都用 32-byte 隨機 hex。產生: openssl rand -hex 32
# ⚠️ 換掉後別再改,改了會讓既有 session / 加密資料失效。
- SECRET_KEY=<openssl rand -hex 32 產生>
- UTILS_SECRET=<openssl rand -hex 32 產生>
# --- 資料庫連線 (必填) -------------------------------------------------
# 格式:postgres://帳號:密碼@主機:埠/資料庫名
# 主機名 postgres = 下面的 service 名,Docker 內部 DNS 解析。
- DATABASE_URL=postgres://outline_user:<DB_密碼>@postgres:5432/outline
- PGSSLMODE=disable # 同台 Docker 內部連線,不需 SSL
# --- Redis 連線 (必填) -------------------------------------------------
# ★ Ubuntu 版重點:指向「內建」redis service,主機名 redis = service 名。
# 不像基本版要填外部 Redis IP/密碼。
- REDIS_URL=redis://redis:6379/1
# --- 對外網址 (必填) ---------------------------------------------------
# 使用者瀏覽器看到的完整網址,要跟 Caddy 對外位置一致。
- URL=https://<你的Ubuntu主機IP>:8443
- PORT=3019 # 容器內部監聽埠 (給 Caddy 反向代理,不直接對外)
- FORCE_HTTPS=false # HTTPS 由 Caddy 處理,這裡關掉避免重導迴圈
# --- 檔案儲存 (必填) ---------------------------------------------------
- FILE_STORAGE=local
- FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
# 上傳/匯入大小上限 (bytes)。預設約 1MB,匯入大 zip 會跳「file too large」。
# 算法: MB × 1048576。下面 = 250MB。
- FILE_STORAGE_UPLOAD_MAX_SIZE=262144000 # 附件上限
- FILE_STORAGE_IMPORT_MAX_SIZE=262144000 # 單篇匯入
- FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE=262144000 # zip 整包匯入 (關鍵)
# --- 登入: Gitea OIDC (選填) -------------------------------------------
# 任何相容 OIDC 供應商皆可 (Gitea / Keycloak / Authentik / Google...)。
# ★ Ubuntu 版注意:OIDC 主機可在「另一台」機器,確認這台 Ubuntu 連得到。
- OIDC_CLIENT_ID=<OIDC_CLIENT_ID>
- OIDC_CLIENT_SECRET=<OIDC_CLIENT_SECRET>
- OIDC_AUTH_URI=http://<OIDC主機>/login/oauth/authorize
- OIDC_TOKEN_URI=http://<OIDC主機>/login/oauth/access_token
- OIDC_USERINFO_URI=http://<OIDC主機>/login/oauth/userinfo
- OIDC_USERNAME_CLAIM=preferred_username # 用哪個欄位當帳號
- OIDC_DISPLAY_NAME=Gitea # 登入按鈕顯示文字
- OIDC_SCOPES=openid profile email
# --- SMTP 寄信 (選填) --------------------------------------------------
# 用途:magic-link 登入信 + 通知信。
# Gmail 範例:密碼要用「應用程式密碼」,不是帳號密碼。
# (Google 帳號 → 安全性 → 兩步驟驗證 → 應用程式密碼)
- SMTP_HOST=smtp.gmail.com
- SMTP_PORT=587
- SMTP_SECURE=false # 587 用 STARTTLS,所以 false
- SMTP_USERNAME=<你的gmail@gmail.com>
- SMTP_PASSWORD=<Gmail 應用程式密碼>
- SMTP_FROM_EMAIL=<你的gmail@gmail.com>
- SMTP_REPLY_EMAIL=<你的gmail@gmail.com>
volumes:
# 存的是「附件/上傳檔」(圖片、PDF...),不是文章本體 (文章在 PostgreSQL)。
# ★ 用 bind mount: 附件直接落在專案資料夾 ./data,搬家複製即帶走。
# 對比 named volume (outline_data:) 要 tar 才能撈出,bind 好搬很多。
# 注意:DB 不要 bind,DB 檔不能直接 copy,一律用 pg_dump 備份。
- ./data:/var/lib/outline/data
depends_on:
postgres:
condition: service_healthy # 等 DB 健康檢查通過才啟動
redis:
condition: service_healthy # 等 Redis 就緒
# ---------------------------------------------------------------------------
# Redis — 內建獨立 service (★ Ubuntu 版才有,基本版用外部 Redis)
# ---------------------------------------------------------------------------
redis:
image: redis:7-alpine
container_name: outline_redis
restart: unless-stopped
volumes:
- redis_data:/data # 持久化 (選用,Outline 主要當快取,掉了也能重建)
healthcheck:
test: ["CMD", "redis-cli", "ping"] # 回 PONG 才算就緒
interval: 10s
timeout: 5s
retries: 5
# ---------------------------------------------------------------------------
# Caddy — 反向代理,自動處理 HTTPS 憑證
# ---------------------------------------------------------------------------
caddy:
image: caddy:2
container_name: outline_caddy
restart: unless-stopped
ports:
- "8443:8443" # 對外唯一開的埠 (主機:容器)。反代規則寫在 Caddyfile。
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro # :ro = 唯讀掛載
- caddy_data:/data # 存 TLS 憑證,別刪,刪了要重新申請
- caddy_config:/config
depends_on:
- outline
# ---------------------------------------------------------------------------
# PostgreSQL — pgvector 映像 (支援向量搜尋)
# ---------------------------------------------------------------------------
postgres:
image: pgvector/pgvector:pg16
container_name: outline_postgres
restart: unless-stopped
environment:
# 這三個要跟上面 DATABASE_URL 的帳號/密碼/DB名一致。
- POSTGRES_USER=outline_user
- POSTGRES_PASSWORD=<DB_密碼>
- POSTGRES_DB=outline
volumes:
- pg_data:/var/lib/postgresql/data # 資料庫實體資料,千萬別誤刪
ports:
# 只綁 127.0.0.1 = 僅本機可連,不對外曝露 DB。安全做法。
- "127.0.0.1:5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U outline_user -d outline"]
interval: 10s
timeout: 5s
retries: 5
# -----------------------------------------------------------------------------
# 具名 volume — 由 Docker 管理,容器刪掉資料還在。
# -----------------------------------------------------------------------------
volumes:
# outline_data 改用 bind mount (./data),不在這裡宣告。
pg_data:
redis_data:
caddy_data:
caddy_config:
要修改的部份,如:密鑰、DB、OIDC、SMTP,都與 Windows 版填法完全相同。
啟動
在 docker-compose.yml 所在資料夾開終端機:
docker compose up -d
確認與登入流程跟 Windows 版一樣:瀏覽器打開 https://<你的IP>:3001,遇到憑證警告點「繼續前往」,再用 Gitea 登入。
結語
照著上面的步驟做,我們就會有一套 完全自架 + 免費 + 可以用 MCP 接上 AI 的 Outline Wiki。
怎麼用 MCP 接上 Claude、Codex,下一篇會說明。



Top comments (0)