Outline Wiki + Keycloak OIDC 部署文档
文档为部署后自用写的,适用于内网无HTTPS环境
注意,由于文件内容较多,这篇文章只是概述,相关文件请前往 Github 下载
环境信息
| 项目 | 值 |
|---|---|
| Outline 地址 | http://<服务器IP>:3000 |
| Keycloak 管理后台 | http://<服务器IP>:3001 |
| Keycloak 管理员 | admin / admin123 |
| Keycloak Realm | outline |
| OIDC Client ID | outline |
文件结构
<部署目录>/
├── config/
│ ├── redis.conf # Redis 配置文件
│ └── keycloak-realm.json # Keycloak realm 预配置(含中文、client secret)
├── data/ # 所有持久化数据(bind mount,方便备份迁移)
│ ├── postgres/ # PostgreSQL 数据库
│ ├── keycloak/ # Keycloak H2 数据库
│ └── outline/ # Outline 上传文件(图片、附件等)
├── docker-compose.yml # 一体化部署配置(4 个服务)
├── docker.env # Outline 环境变量(含 OIDC 预设值、中文注释)
├── install.sh # 一键部署脚本(自动检测/替换 IP)
└── README.md # 本文档
快速部署
一键部署
cd <部署目录>
# 自动检测本机 IP 并部署
bash install.sh
# 或手动指定 IP(只是使用这个ip去替换配置文件中的占位符)
bash install.sh 192.168.1.100
install.sh 启动时自动完成:
- 检测或接收服务器 IP
- 替换所有配置文件中的 IP(docker.env、docker-compose.yml、keycloak-realm.json)
- 创建数据目录并设置权限
- 启动所有服务(docker-compose up -d)
- 等待 Keycloak 就绪(最长 2 分钟)
- 应用 StateStore 补丁并重启 Outline
换机器部署
- 将整个部署目录复制到新机器
- 确认配置文件中 IP 仍为模板值
192.168.1.6(如果之前部署过,Git 回退即可) - 执行
bash install.sh,脚本自动替换为新机器 IP
重新部署(清除所有数据)
docker-compose down -v
rm -rf data
bash install.sh
停止服务(保留数据)
docker-compose down
数据持久化
全部使用 bind mount,无 docker volume,直接映射到 ./data/ 目录:
| 服务 | 容器路径 | 宿主机路径 | 内容 |
|---|---|---|---|
| PostgreSQL | /var/lib/postgresql | ./data/postgres/ | 数据库文件 |
| Keycloak | /opt/keycloak/data/h2 | ./data/keycloak/ | 用户、Realm 配置 |
| Outline | /var/lib/outline/data | ./data/outline/ | 上传的图片、附件 |
备份与迁移
# 停止服务
docker-compose down
# 直接打包整个 data 目录
tar czf backup.tar.gz data/
# 迁移到新服务器
scp backup.tar.gz user@new-server:/path/to/deploy/
tar xzf backup.tar.gz
bash install.sh
# 注意,可能需要替换 docker.env、docker-compose.yml、keycloak-realm.json 这些配置文件中的ip
首次使用 - 创建管理员账户
- 访问 Keycloak 管理后台:
http://<IP>:3001 - 使用 账户密码(compose中查看) 登录
- 左上角切换 Realm 到 outline
- 进入 Users -> Add user
- 填写 Username(必填)
- 点击 Create
- 进入用户详情 -> Credentials 标签
- 点击 Set password
- 输入密码,将 Temporary 设为 OFF
- 点击 Save
- 访问 Outline:
http://<IP>:3000 - 点击登录 -> 选择 OpenID Connect
- 使用刚创建的用户名密码登录
注意: 第一个通过 OIDC 登录的用户将自动成为 Outline 管理员。
配置文件说明
docker-compose.yml
| 服务 | 镜像 | 端口 | 数据目录 |
|---|---|---|---|
| postgres | postgres:18 | 5432(内部) | ./data/postgres/ |
| redis | redis | 6379(内部) | 无 |
| keycloak | quay.io/keycloak/keycloak:latest | 3001->8080 | ./data/keycloak/ |
| outline | outlinewiki/outline:1.8.0 | 3000:3000 | ./data/outline/ |
docker.env 关键变量
| 变量 | 说明 |
|---|---|
| NODE_ENV | 必须为 production |
| URL | Outline 访问地址(install.sh 自动替换 IP) |
| FORCE_HTTPS | 内网 HTTP 设为 false |
| OIDC_CLIENT_ID / OIDC_CLIENT_SECRET | 与 keycloak-realm.json 一致 |
config/keycloak-realm.json
Keycloak 启动时通过 --import-realm 自动导入,包含:
- Realm 基础设置(中文本地化:zh-CN / en)
- OIDC Client 配置(含预设 secret、redirect URI)
- redirect URI 中的 IP 由 install.sh 自动替换
遇到的问题及解决方案
问题 1: NODE_ENV=development 导致 Vite 脚本注入
现象: 浏览器报 CORS 错误,尝试加载 @vite/client 等开发服务器脚本。
解决: 保持 NODE_ENV=production。
问题 2: Secure Cookie 导致 OIDC 登录 500 错误
现象: /auth/oidc 返回 500,日志:
Cannot send secure cookie over unencrypted connection
原因: production 模式下 StateStore 将 OAuth CSRF cookie 设为
secure: true(代码: secure: _env.default.isProduction),
HTTP 连接不允许发送 secure cookie。
解决: install.sh 自动执行 sed 替换为 secure: false。
问题 3: bind mount 目录权限导致上传失败
现象: 粘贴图片提示上传失败,容器内 Permission denied。
原因: bind mount 目录属主为宿主机用户,容器内以 nodejs(1001) 运行, 无写入权限。
解决: install.sh 创建 data 子目录后执行 chmod 777。
问题 4: Keycloak issuer 返回 localhost
现象: well-known 端点 issuer 为 localhost。
解决: docker-compose.yml 中设置 KC_HOSTNAME、KC_HOSTNAME_PORT。
问题 5: 配置文件中 IP 硬编码
现象: docker.env、docker-compose.yml、keycloak-realm.json 中 IP 写死为 192.168.1.6,换机器需手动修改。
解决: install.sh 启动时自动检测或接收 IP,使用 sed 替换所有配置文件。
日常维护
查看日志
docker logs outline_outline_1 --tail 50
docker logs outline_keycloak_1 --tail 20
备份
docker-compose down
tar czf backup_$(date +%Y%m%d).tar.gz data/
docker-compose up -d
Keycloak 用户管理
访问 Keycloak 管理后台 -> 选 outline realm -> Users 管理用户。