个人Wiki的搭建-手搓一个Outline

写在前面:
用过Synology Note Station,Joplin,Confluence,也私有化部署过为知笔记。简单做个对比。
Synology Note Station | Joplin | Confluence | 为知笔记 | Outline | |
|---|---|---|---|---|---|
客户端支持 | 支持全平台 | 支持全平台 | 仅web版 | 仅web版 | 仅web版 |
支持插件的全面性 | 几乎没有 | 很丰富 | 很丰富 | 几乎没有 | 够用 |
界面美观 | 简陋 | 一般 | 还不错 | 简陋 | 还不错 |
易用性 | 简单上手 | 需要自己搭server端 | 比较复杂 | 简陋 | 简单上手 |
数据库/多端同步 | 全平台自动同步 | 全平台自动同步 | web端实时更新 | web端实时更新 | web端实时更新 |
资源占用 | 群晖自带忽略不计 | pg占了一点儿内存 | 云端服务器,私有化没搞过,据说内存占用较大 | 较低 | 较低 |
总得来说Outline还是比较不错的一个选择,支持树形结构展示,美观又易上手,登录有SSO和双因素认证,也有适合多人使用的鉴权和基本的权限管理。
缺点是拖拽上传的图片上传容易,但是删除仅是在前端删除,源数据想要彻底删除,需要手动到minio里去删,前后端并没有做到完全同步。
准备事项:
一些解析好的域名
服务器一台
mkdir好文件夹并准备好下面介绍的文件
开始
1.OIDC SSO登录
有位程序员大神推荐了https://console.authing.cn/ 看起来是很牛逼,但是能力有限,按照理解自行配置完成之后无法顺利登录。
研究之后发现,有一个相对比较简单的办法:
docker run -d \
--name=sso-server \
-e CLIENT_NAME="My SSO Service" \
-e CLIENT_ID="随机生成" \ #后面要用到
-e CLIENT_SECRET="随机生成" \ #后面要用到
-e USER_PASS="随机生成" \ #这个是登录密码
-p 3009:80 \
soulteary/sso-server:1.1.6 通过nginx让这个3009端口通过SSL的域名访问,比如sso.youradmin.com,后面会用到这个二级域名。
2.docker-compose.yml
所需要的文件内容,可以根据自己环境修改端口号和相关内容
version: "3"
services:
outline:
image: outlinewiki/outline:latest
env_file: ./docker.env
command: sh -c "yarn start"
ports:
- "3000:3000"
depends_on:
- postgres
- redis
- storage
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./redis.conf:/redis.conf
command: ["redis-server", "/redis.conf"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 30s
retries: 3
postgres:
image: postgres
ports:
- "5432:5432"
volumes:
- ./database-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready -U user"]
interval: 30s
timeout: 20s
retries: 3
environment:
POSTGRES_USER: 'wiki'
POSTGRES_PASSWORD: 'wiki'
POSTGRES_DB: 'outline'
storage:
image: minio/minio
env_file: ./docker.env
ports:
- "9001:9001"
- "9002:9002"
entrypoint: sh
command: -c 'minio server /data --address ":9001" --console-address ":9002"'
deploy:
restart_policy:
condition: on-failure
volumes:
- ./storage-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "https://minio.youradmin.com/minio/health/live"] #域名需要自己修改
interval: 30s
timeout: 20s
retries: 3
environment:
- MINIO_ROOT_USER=随机生成一个 #minio的登录名
- MINIO_ROOT_PASSWORD=随机生成一个 #minio的登录密码注意,minio的9002端口是管理端登录界面,9001是API端口,实际上env里的域名是nginx映射9001端口的。
3.docker.env
根据自己环境修改端口号和相关内容
# –––––––––––––––– REQUIRED ––––––––––––––––
NODE_ENV=production
# Generate a hex-encoded 32-byte random key. You should use `openssl rand -hex 32`
# in your terminal to generate a random value.
SECRET_KEY=随机生成一个 #自行解决
# Generate a unique random key. The format is not important but you could still use
# `openssl rand -hex 32` in your terminal to produce this.
UTILS_SECRET=随机生成一个 #自行解决
# For production point these at your databases, in development the default
# should work out of the box.
DATABASE_URL=postgres://wiki:wiki@postgres:5432/outline
DATABASE_URL_TEST=postgres://wiki:wiki@postgres:5432/outline-test
DATABASE_CONNECTION_POOL_MIN=
DATABASE_CONNECTION_POOL_MAX=
# Uncomment this to disable SSL for connecting to Postgres
PGSSLMODE=disable
# For redis you can either specify an ioredis compatible url like this
REDIS_URL=redis://redis:6379
# or alternatively, if you would like to provide additional connection options,
# use a base64 encoded JSON connection option object. Refer to the ioredis documentation
# for a list of available options.
# Example: Use Redis Sentinel for high availability
# {"sentinels":[{"host":"sentinel-0","port":26379},{"host":"sentinel-1","port":26379}],"name":"mymaster"}
# REDIS_URL=ioredis://eyJzZW50aW5lbHMiOlt7Imhvc3QiOiJzZW50aW5lbC0wIiwicG9ydCI6MjYzNzl9LHsiaG9zdCI6InNlbnRpbmVsLTEiLCJwb3J0IjoyNjM3OX1dLCJuYW1lIjoibXltYXN0ZXIifQ==
# URL should point to the fully qualified, publicly accessible URL. If using a
# proxy the port in URL and PORT may be different.
URL=https://youradmin #你自己的域名
PORT=3000
# See [documentation](docs/SERVICES.md) on running a separate collaboration
# server, for normal operation this does not need to be set.
COLLABORATION_URL=
# To support uploading of images for avatars and document attachments an
# s3-compatible storage must be provided. AWS S3 is recommended for redundancy
# however if you want to keep all file storage local an alternative such as
# minio (https://github.com/minio/minio) can be used.
# A more detailed guide on setting up S3 is available here:
# => https://wiki.generaloutline.com/share/125de1cc-9ff6-424b-8415-0d58c809a40f
#
AWS_ACCESS_KEY_ID=MINIO_ROOT_USER #docker-compose.yml里的minio登录名
AWS_SECRET_ACCESS_KEY=MINIO_ROOT_PASSWORD #docker-compose.yml里的minio登录密码
AWS_REGION=local
# AWS_S3_ACCELERATE_URL=
AWS_S3_UPLOAD_BUCKET_URL=https://minio.youradmin.com #这个域名是minio的域名,是nginx反代的9001端口
AWS_S3_UPLOAD_BUCKET_NAME=wiki-bucket
AWS_S3_UPLOAD_MAX_SIZE=26214400
# AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=public-read
# –––––––––––––– AUTHENTICATION ––––––––––––––
# Third party signin credentials, at least ONE OF EITHER Google, Slack,
# or Microsoft is required for a working installation or you'll have no sign-in
# options.
# To configure Slack auth, you'll need to create an Application at
# => https://api.slack.com/apps
#
# When configuring the Client ID, add a redirect URL under "OAuth & Permissions":
# https://<URL>/auth/slack.callback
# SLACK_CLIENT_ID=
# SLACK_CLIENT_SECRET=
# To configure Google auth, you'll need to create an OAuth Client ID at
# => https://console.cloud.google.com/apis/credentials
#
# When configuring the Client ID, add an Authorized redirect URI:
# https://<URL>/auth/google.callback
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# To configure Microsoft/Azure auth, you'll need to create an OAuth Client. See
# the guide for details on setting up your Azure App:
# => https://wiki.generaloutline.com/share/dfa77e56-d4d2-4b51-8ff8-84ea6608faa4
# AZURE_CLIENT_ID=57ce0aec-d374-4dd7-8cc0-4be3e446208e
# AZURE_CLIENT_SECRET=o8~8Q~ZGaei49nqG2Z-WL5GBRPeMdvI3pzVvcbuZ
# AZURE_RESOURCE_APP_ID=00000003-0000-0000-c000-000000000000
# To configure generic OIDC auth, you'll need some kind of identity provider.
# See documentation for whichever IdP you use to acquire the following info:
# Redirect URI is https://<URL>/auth/oidc.callback
OIDC_CLIENT_ID=CLIENT_ID #第一步中设置的CLIENT_ID
OIDC_CLIENT_SECRET=CLIENT_SECRET #第一步中设置的CLIENT_SECRET
OIDC_AUTH_URI=https://sso.youradmin.com/dialog/authorize #第一步中反代sso的域名
OIDC_TOKEN_URI=https://sso.youradmin.com//oauth/token #第一步中反代sso的域名
OIDC_USERINFO_URI=https://sso.youradmin.com//api/outline/oidc #第一步中反代sso的域名
# Specify which claims to derive user information from
# Supports any valid JSON path with the JWT payload
OIDC_USERNAME_CLAIM=preferred_username
# Display name for OIDC authentication
OIDC_DISPLAY_NAME=My SSO
# Space separated auth scopes.
OIDC_SCOPES=openid profile email
# –––––––––––––––– OPTIONAL ––––––––––––––––
# Base64 encoded private key and certificate for HTTPS termination. This is only
# required if you do not use an external reverse proxy. See documentation:
# https://wiki.generaloutline.com/share/1c922644-40d8-41fe-98f9-df2b67239d45
# SSL_KEY=
# SSL_CERT=
# If using a Cloudfront/Cloudflare distribution or similar it can be set below.
# This will cause paths to javascript, stylesheets, and images to be updated to
# the hostname defined in CDN_URL. In your CDN configuration the origin server
# should be set to the same as URL.
# CDN_URL=
# Auto-redirect to https in production. The default is true but you may set to
# false if you can be sure that SSL is terminated at an external loadbalancer.
FORCE_HTTPS=false
# Have the installation check for updates by sending anonymized statistics to
# the maintainers
ENABLE_UPDATES=true
# How many processes should be spawned. As a reasonable rule divide your servers
# available memory by 512 for a rough estimate
WEB_CONCURRENCY=1
# Override the maximum size of document imports, could be required if you have
# especially large Word documents with embedded imagery
MAXIMUM_IMPORT_SIZE=5120000
# You can remove this line if your reverse proxy already logs incoming http
# requests and this ends up being duplicative
# DEBUG=http
# For a complete Slack integration with search and posting to channels the
# following configs are also needed, some more details
# => https://wiki.generaloutline.com/share/be25efd1-b3ef-4450-b8e5-c4a4fc11e02a
#
# SLACK_VERIFICATION_TOKEN=
# SLACK_APP_ID=
# SLACK_MESSAGE_ACTIONS=
# Optionally enable google analytics to track pageviews in the knowledge base
# GOOGLE_ANALYTICS_ID=
# Optionally enable Sentry (sentry.io) to track errors and performance,
# and optionally add a Sentry proxy tunnel for bypassing ad blockers in the UI:
# https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option)
# SENTRY_DSN=
# SENTRY_TUNNEL=
# To support sending outgoing transactional emails such as "document updated" or
# "you've been invited" you'll need to provide authentication for an SMTP server
# SMTP_HOST=<SMTP服务器>
# SMTP_PORT=<SMTP端口,比如465>
# SMTP_USERNAME=<SMTP用户名>
# SMTP_PASSWORD=<SMTP密码>
# SMTP_FROM_EMAIL=<发件人地址>
# SMTP_REPLY_EMAIL=<邮件回复地址>
# SMTP_TLS_CIPHERS=TLSv1.2
# SMTP_SECURE=true
# The default interface language. See translate.getoutline.com for a list of
# available language codes and their rough percentage translated.
DEFAULT_LANGUAGE=zh_CN
# Optionally enable rate limiter at application web server
RATE_LIMITER_ENABLED=true
# Configure default throttling parameters for rate limiter
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=604.Enjoy it
docker-compose up -d #up docker-compose down #down遇到过的坑
Q:无法上传图片
A:初始化数据库
建一个文件 docker-compose-init-minio.yml
version: "3" services: startup: image: minio/mc entrypoint: /bin/sh -c " /usr/bin/mc config host rm local; /usr/bin/mc config host add local https://minio.youradmin.com MINIO_ROOT_USER MINIO_ROOT_PASSWORD; #在docker-compose.yml中设置过 /usr/bin/mc mb local/wiki-bucket; /usr/bin/mc anonymous set public local/wiki-bucket; #和env里的保持一致 exit 0;"
后续
Q:在公网上暴露了太多端口。
A:是否有机会仅暴露一个端口,并强制通过SSL访问,其他端口只在容器内部交换数据。
目前SSO和Outline是两个yml启动的,可以合并到一个yml和一个env环境中。目前我的SSO和Outline不在一个服务器上,所以也还OK。
优化
SSO单点登录优化:
问题:通过命令行启动默认用户名和邮箱无法更改
目标:可以更改默认的用户名和邮箱
创建 docker-compose.yml
version: "3.6" services: self-hosted-sso-server: image: soulteary/sso-server:1.1.6 container_name: sso-server-linshi hostname: sso-server-linshi restart: always ports: - 3009:80 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro command: ./main environment: - TZ=Asia/Shanghai - PORT=${SERVER_LISTEN_PORT:-80} - SESSION_SECRET=${SESSION_SECRET:-} - SERVER_NAME=${SERVER_NAME:-} - CLIENT_NAME=${CLIENT_NAME:-} - CLIENT_ID=${CLIENT_ID:-} - CLIENT_SECRET=${CLIENT_SECRET:-} - CLIENT_ISTRUSTED=${CLIENT_ISTRUSTED:-} - USER_PASS=${USER_PASS:-} - LICENSE=${LICENSE:-} - LICENSE_FILE=${LICENSE_FILE:-} - OTP_OPTION=${OTP_OPTION:-} logging: driver: "json-file" options: max-size: "10m"创建 .env
# Docs @see https://github.com/soulteary/docker-sso-server CLIENT_ID=自行生成 # 和docker.env保持一致 CLIENT_SECRET=自行生成 # 和docker.env保持一致 USER_PASS=自行生成 # SSO登录密码 # Optional # CLIENT_ISTRUSTED=false # SERVER_NAME=SELF-HOSTED SSO SERVER_LISTEN_PORT=80 # SESSION_SECRET=YOUR_SESSION_SECRET_KEY CLIENT_NAME=My SSO Service # OTP_OPTION=KEY:MIZUSR2ZJZTWUSDY;PERIOD:30 LICENSE=自行获取 # https://readers-lic-gift.suyang.wiki/api/reader-benefits 通过这个网址获取 # LICENSE_FILE=
完成后记得修改docker .env中的CLIENT_ID和CLIENT_SECRET
mkdir文件夹中其实有三个文件,分别是 docker-compose-init-minio.yml docker-compose.yml docker.env
不论是未来pull升级还是遇到问题down up重启,都要执行两次docker-compose命令,可以利用startup服务来merge起来,这样一条命令就搞定了。
version: "3" services: outline: image: outlinewiki/outline:latest env_file: ./docker.env command: sh -c "yarn start" ports: - "3000:3000" depends_on: - postgres - redis - storage redis: image: redis ports: - "6379:6379" volumes: - ./redis.conf:/redis.conf command: ["redis-server", "/redis.conf"] healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 30s retries: 3 postgres: image: postgres ports: - "5432:5432" volumes: - ./database-data:/var/lib/postgresql/data healthcheck: test: ["CMD", "pg_isready -U user"] interval: 30s timeout: 20s retries: 3 environment: POSTGRES_USER: 'wiki' POSTGRES_PASSWORD: 'wiki' POSTGRES_DB: 'outline' storage: image: minio/minio env_file: ./docker.env ports: - "9001:9001" - "9002:9002" entrypoint: sh command: -c 'minio server /data --address ":9001" --console-address ":9002"' volumes: - ./storage-data:/data healthcheck: test: ["CMD", "curl", "-f", "https://minio.youradmin.com/minio/health/live"] #域名需要自己修改 interval: 30s timeout: 20s retries: 3 environment: - MINIO_ROOT_USER=随机生成一个 #minio的登录名 - MINIO_ROOT_PASSWORD=随机生成一个 #minio的登录密码 startup: image: minio/mc depends_on: storage: condition: service_healthy entrypoint: /bin/sh -c " /usr/bin/mc config host rm local; /usr/bin/mc config host add local https://minio.youradmin.com MINIO_ROOT_USER MINIO_ROOT_PASSWORD; #在docker-compose.yml中设置过 /usr/bin/mc mb local/wiki-bucket; /usr/bin/mc anonymous set public local/wiki-bucket; #和env里的保持一致 exit 0;"
微信
支付宝