前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >私有化部署 Outline

私有化部署 Outline

原创
作者头像
凝神长老
发布2023-03-25 03:40:58
3.8K0
发布2023-03-25 03:40:58
举报
文章被收录于专栏:凝神长老和他的朋友们

这是一款适用于个人或团队场景使用的开源文档/Wiki软件,Outline。

我在这两篇文章(https://soulteary.com/2021/09/05/opensource-documentation-wiki-software-outline-part-1.html、https://soulteary.com/2021/09/11/opensource-documentation-wiki-software-outline-part-2.html)看到了这个工具,打算试一试,结合那篇文章中罗列的信息,加上我自己的理解,基本上可以把这款软件的特点罗列如下:

  • 能够将数据完全自托管管理,不涉及私有格式,而且可以随时导出成开源格式(例如 PDF、Markdown)
  • Markdown 语法、所见即所得,可以直接上传附件和图片,也支持代码片段、数学公式
  • 类 Notion,允许插入富文本内容、卡片式渲染
  • 个人使用和管理文档,并在需要时可以邀请用户协同编辑、分享文档
  • 层级嵌套,方便分类和整理
  • 历史版本记录,并在文档被改动/编辑后有邮件提醒

缺点也不少:

  • 不支持本地登录,只支持 OAuth 登录
  • 不支持本地存储,只能使用 AWS S3 或者兼容 S3 协议的存储,例如 Minio
  • 从文档中删除图片,未必能清理后端存储中的文件
  • 没有评论功能,权限管理的层级不够丰富
  • 很多设置项不能在网页端修改,只能重启 docker-compose
  • 极度简陋的自托管支持,只能靠社区成员的零碎的讨论来解决问题

官方提供的 docker-compose 安装教程(https://docs.getoutline.com/s/hosting/doc/docker-7pfeLP5a8t)非常简陋,有很多细节都没有解释,所以并不是开箱即用的。根据官方提供的模板,做了很多尝试,我终于搭建起来了。我把缺少的细节都记录一下。

我的 docker-compose 采用 env_file 读取环境参数,然后把环境参数都写在 .env 文件里面,这样我就也可以在 docker-compose.yml 里面用环境变量,方便些。

我把 https-portal 删掉了,我打算直接开放 outline 的 3000 端口,之后用 NGINX 转发;Redis、Postgres 都只用容器内网络通讯,不开放端口;Minio 我开放了 9000 端口,也绑定了一个控制台,因为这样也可以方便后面管理(虽然理论上它也只需要容器内通讯)。

代码语言:yaml
复制
outline:
    image: ${DOCKER_OUTLINE_IMAGE_NAME}
    container_name: outline
    env_file: ./.env
    ports:
      - "9303:3000"
    restart: always
    networks:
      - outline
    extra_hosts:
      - "${DOCKER_OUTLINE_HOSTNAME}:0.0.0.0"
    depends_on:
      - postgres
      - redis
      - storage
代码语言:yaml
复制
  image: ${DOCKER_REDIS_IMAGE_NAME}
    env_file: ./.env
    volumes:
      - ./redis.conf:/redis.conf
    container_name: ${DOCKER_REDIS_HOSTNAME}
    restart: always
    networks:
      - outline
    command: ["redis-server", "/redis.conf"]
代码语言:yaml
复制
postgres:
    image: ${DOCKER_POSTGRES_IMAGE_NAME}
    env_file: ./.env
    volumes:
      - ./database-data:/var/lib/postgresql/data
    container_name: ${DOCKER_POSTGRES_HOST}
    restart: always
    networks:
      - outline
代码语言:yaml
复制
  image: ${DOCKER_MINIO_IMAGE_NAME}
    container_name: ${OUTLINE_MINIO}
    env_file: ./.env
    ports:
      - "${DOCKER_OUTLINE_MINIO_PORT}:9000"
      - "${DOCKER_OUTLINE_MINIO_ADMIN_PORT}:9001"
    command: "minio server /data --console-address 0.0.0.0:${DOCKER_OUTLINE_MINIO_ADMIN_PORT}"
    restart: always
    extra_hosts:
      - "${DOCKER_MINIO_HOSTNAME}:0.0.0.0"
      - "${DOCKER_MINIO_ADMIN_DOMAIN}:0.0.0.0"
    volumes:
      - ./storage-data:/data
    networks:
       - outline
代码语言:yaml
复制
networks:
  outline:
    external: true

.env 文件保留了环境变量,根据自己的情况修改。

所有的 IMAGE_NAME 我都用了此刻(2023-03-23)最新的。

代码语言:txt
复制
DOCKER_OUTLINE_IMAGE_NAME=outlinewiki/outline:0.68.1
DOCKER_POSTGRES_IMAGE_NAME=postgres:15.2
DOCKER_REDIS_IMAGE_NAME=redis:7.2-rc1
DOCKER_MINIO_IMAGE_NAME=minio/minio:RELEASE.2023-03-22T06-36-24Z

Outline 相关的参数如下:

代码语言:txt
复制
DOCKER_OUTLINE_HOSTNAME=outline.example.com
OUTLINE_URL=https://${DOCKER_OUTLINE_HOSTNAME}
URL=${OUTLINE_URL}
PORT=3000

Postgres 和 Redis 的参数没有特殊的地方,只要注意容器内地址通讯即可,例如:

代码语言:txt
复制
DATABASE_URL=postgres://${DOCKER_POSTGRES_USER}:${DOCKER_POSTGRES_PASS}@${DOCKER_POSTGRES_HOST}:5432/${DOCKER_POSTGRES_DBNAME}

当然也要注意把改过名字的参数类型映射回 docker 的环境变量会用的名字,以及我 disable 了 PostgreSQL 的 SSL。

代码语言:txt
复制
POSTGRES_USER=${DOCKER_POSTGRES_USER}
代码语言:txt
复制
PGSSLMODE=disable

Outline 不支持本地存储,他只开放了 AWS S3 存储,但是也可以使用兼容 S3 协议的其他存储(比如 Minio)。

Minio 是一个兼容 S3 协议的存储,简单说就是启动了一个服务之后,它把 S3 处理请求解析后,把文件存放到本地。docker-compose 中我们启动了这个 Minio 的 docker 镜像,并把 /data 目录挂载到了本地持久存储。

初始化 Minio 的时候,我提供了 MINIO_ROOT_USERMINIO_ROOT_PASSWORD,这两个后面会当作 S3 的 Access ID 和 Secret Key 来使用。它们都只由小写 a-z 和数字组成,前者 16 位,后者 64 位,我使用 https://onlinerandomtools.com/generate-random-string 生成。

因为是自己的 Minio,所以 MINIO_REGION_NAME 就可以随便写了,这个后面会当作 S3 的 Region 来使用。

代码语言:txt
复制
DOCKER_MINIO_HOSTNAME=minio.example.com
DOCKER_MINIO_ADMIN_DOMAIN=minio-admin.example.com

为了管理方便,docker-compose 还启动了 9001 管理界面,这里我们做一下重定向。

代码语言:txt
复制
MINIO_BROWSER=on
MINIO_BROWSER_REDIRECT_URL=https://${DOCKER_MINIO_ADMIN_DOMAIN}
DOCKER_OUTLINE_MINIO_PORT=9000
DOCKER_OUTLINE_MINIO_ADMIN_PORT=9001

后面大部分参数都可以按照官方示例(https://github.com/outline/outline/blob/main/.env.sample)中的说明来操作,比如使用 openssl rand -hex 32 来生成 SECRET KEY 等等。

AWS 存储就使用 Minio。

代码语言:txt
复制
AWS_ACCESS_KEY_ID=${MINIO_ROOT_USER}
AWS_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}
AWS_REGION=${MINIO_REGION_NAME}
AWS_S3_UPLOAD_BUCKET_URL=https://${DOCKER_MINIO_HOSTNAME}
AWS_S3_UPLOAD_BUCKET_NAME=outline
AWS_S3_UPLOAD_MAX_SIZE=26214400
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private

登录是个大麻烦,Outline 不支持本地用户登录,它目前只支持 Slack、Azure、Google 以及 OIDC,所以需要去各平台生成 OAuth Token,还挺麻烦的。好在 GitLab 支持标准 OIDC 协议,而我有一个私有部署的 GitLab 实例,就直接接入了。

首先填写通用的信息,如下:

代码语言:txt
复制
OIDC_AUTH_URI=https://gitlab.example.com/oauth/authorize
OIDC_TOKEN_URI=https://gitlab.example.com/oauth/token
OIDC_USERINFO_URI=https://gitlab.example.com/oauth/userinfo
OIDC_USERNAME_CLAIM=username
OIDC_DISPLAY_NAME=GitLab
OIDC_SCOPES=openid email

接着去管理中心 - 应用 - 实例 OAuth 应用程序 (https://gitlab.example.com/admin/applications),新建一个应用。

回调 URI 写 https://outline.example.com/auth/oidc.callback,范围勾选 openidemail,视情况选择是否可信和是否私密。

image
image

点击保存应用之后,把 CLIENT_IDCLIENT_SECRET 填写到 .env 文件中。

还有剩下一些杂项,根据情况修改。

我把 FORCE_HTTPS 改成了 falseDEFAULT_LANGUAGE 改成了 zh_CN。因为我不打算使用 Slack,所以我还把 Slack 的默认数据都删掉了。我启用了 SMTP,我用的是 mailgun 的服务,所以修改了 TLS_CIPHERS 以支持 587 TLS。

代码语言:txt
复制
SMTP_TLS_CIPHERS=TLSv1.2
SMTP_SECURE=false

接下去还要修改 NGINX 配置。

首先是 Outline。

Outline 的核心是 proxy_pass 的时候要加上一些 Header。

代码语言:text
复制
location / {
    proxy_pass        http://localhost:9303;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
    proxy_set_header Access-Control-Allow-Origin "*";
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $host;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
}

如果遇到跨域的问题还要加 Allow-Origin。

代码语言:text
复制
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS,PUT;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,Content-Type,Accept,Authorization;

if ($request_method = 'OPTIONS') {
  return 204;
}

接着是 Minio。

Minio 直接转发就可以,不要带 Allow-Origin,也不要带 proxy_set_header,不然可能会出现奇怪的 CORS 错误(因为 Minio 有默认的 Allow * 的配置),或者可能出现管理界面 400 错误。

代码语言:text
复制
# minio-admin.example.com
location / {
    proxy_pass        http://localhost:9001;
}
代码语言:text
复制
# minio.example.com
location / {
    proxy_pass        http://localhost:9000;
}

接下来要新建一个 Minio 存储桶。

这一步也可以使用命令行完成,例如运行一个 minio/mc 的客户端,使用 /usr/bin/mc mb 来创建一个桶,并设置访问权限。

我访问了 minio.example.com,这会被自动重定向到 minio-admin.example.com,我使用刚才上面的 Access ID 和 Secret Key 作为用户名和密码登录,然后选择左侧 Buckets,新建一个存储桶,名称就用 docker-compose 或者 .env 文件中设置的。上例是 outline。

image
image
image
image

回到 docker-compose 和 .env 的目录,启动 docker-compose up -d

首次运行还需要创建数据库以及执行迁移。

代码语言:txt
复制
docker-compose run --rm outline yarn db:create --env=production-ssl-disabled
docker-compose run --rm outline yarn db:migrate --env=production-ssl-disabled

运行之后可能还要根据自己的情况执行下面这个命令。这个命令是解决在内存不足的情况下后台保存可能会失败的问题。这个值是在主机级别,而不是容器级别。Redis 推荐 1 的原因是他们的后台保存机制(https://redis.io/topics/faq#background-saving-fails-with-a-fork-error-under-linux-even-if-i-have-a-lot-of-free-ram)。

代码语言:shell
复制
sysctl vm.overcommit_memory=1

此时回到 outline.example.com 应该一切正常了。

image
image

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档