开始

使用 docker-compose 完成

docker-compose 文件,需要修改postgres的密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
version: '3.8'
services:
outline:
image: docker.io/outlinewiki/outline:0.72.2
container_name: outline
env_file: ./outline-docker.env
expose:
- 3000
volumes:
- outline-data:/var/lib/outline/data
networks:
- outline_network

postgres:
image: abcfy2/zhparser:15-alpine
container_name: postgres
restart: unless-stopped
environment:
# 需要修改
POSTGRES_PASSWORD: password
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- database-data:/var/lib/postgresql/data
expose:
- 5432
networks:
- outline_network

redis:
image: redis
container_name: redis
restart: unless-stopped
expose:
- 6379
networks:
- outline_network

authelia:
image: docker.io/authelia/authelia:4.37.5
container_name: authelia
volumes:
- ./data/authelia:/config
expose:
- 9091
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
networks:
- outline_network

nginx:
image: nginx
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx/conf/conf.d:/etc/nginx/conf.d
- ./data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./data/nginx/conf/ssl:/etc/nginx/ssl
networks:
- outline_network

networks:
outline_network:
driver: bridge

volumes:
outline-data:
database-data:

完成以后,先生成一个 outline-docker.env 文件

1
touch outline-docker.env

先拉取并跑一下容器,把文件映射出来(报错不用管)

1
docker-compose up

nginx

1
2
rm -rf data/nginx/conf/nginx.conf/
nano data/nginx/conf/nginx.conf

nginx.conf配置文件,不需要修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
user  nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*;
server_tokens off;
}

需要两个域名,一个是 authelia 认证服务,一个是 outline 域名(SSL证书我直接从腾讯云下载的)

authelia

1
nano data/nginx/conf/conf.d/authelia.conf

authelia.conf 配置文件,自行修改SSL证书位置和域名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
server {
listen 80;
listen 443 ssl;
resolver 127.0.0.11;

# 需要修改的部分
server_name sso.example.com;
ssl_certificate ssl/sso.example.com_bundle.crt;
ssl_certificate_key ssl/sso.example.com.key;

location / {
proxy_pass http://authelia:9091;

client_body_buffer_size 128k;

#Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;

# Advanced Proxy Config
send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;

# Basic Proxy Config
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_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

# If behind reverse proxy, forwards the correct IP
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.0.0.0/8;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from fc00::/7;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
}

outline

1
nano data/nginx/conf/conf.d/outline.conf

outline.conf 配置文件,自行修改SSL证书位置和域名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
server {
listen 80;
listen 443 ssl;
charset utf-8;

# 需要修改的部分
server_name outline.example.com;
ssl_certificate ssl/outline.example.com_bundle.crt;
ssl_certificate_key ssl/outline.example.com.key;

resolver 127.0.0.11;
ssl_session_timeout 5m;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://outline:3000/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
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;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

postgres

再次运行docker

1
docker-compose up -d

进入 PostgreSQL 数据库命令行

1
docker exec -it --user postgres postgres psql -U postgres

自行修改密码字段,执行SQL

1
2
3
4
5
6
7
8
# 创建用户,自行修改密码
CREATE USER outline WITH PASSWORD 'password_of_outline_user';

# 创建数据库
CREATE DATABASE outline OWNER outline;

# 退出命令行
\q

停止docker

1
docker-compose stop

authelia

authelia主要的两个配置文件:configuration.ymlusers_database.yml

主要配置文件

configuration.yml 是主要的配置文件

所有可以定义的 环境变量

需要手动修改的参数有6个

  • jwt_secret
  • session.secret
  • storage.encryption_key
  • identity_providers.oidc.hmac_secret
  • identity_providers.oidc.issuer_private_key
  • identity_providers.oidc.clients.secret

可以用命令生成

1
openssl rand -hex 64

identity_providers.oidc.issuer_private_key的生成,把在当前目录下生成的 private.pem 内容复制出来

1
docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:4.37.5 authelia crypto pair rsa generate --bits 4096 --directory /keys

完整的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# 开始配置:https://www.authelia.com/integration/prologue/get-started/

jwt_secret: xxx
# 默认重定向到的 URL
default_redirection_url: https://sso.example.com

server:
host: 0.0.0.0
port: 9091

log:
level: debug

# 身份验证后端,支持LDAP和文件两种方式
authentication_backend:
# 禁止用户从 Web 前端重置密码
password_reset:
disable: false
# 文件路径
file:
path: /config/users_database.yml

# 二次验证
totp:
disable: false
issuer: example.com
algorithm: sha256
period: 30
skew: 1
secret_size: 32

# 访问控制:https://www.authelia.com/configuration/security/access-control/
access_control:
# 没有定制rules的部分默认拒绝策略
default_policy: deny
rules:
- domain: outline.example.com
policy: one_factor
subject:
- ['group:admins']


# 会话配置,Authelia依靠会话 cookie 来验证用户身份:https://www.authelia.com/configuration/session/introduction/
session:
name: authelia_session
domain: sso.example.com
secret: xxx
expiration: 3600 # 1 hour
inactivity: 300 # 5 minutes
# 提供会话存储
redis:
# 这里的host是在docker-compose中定义的
host: redis
port: 6379

# 存储
storage:
encryption_key: xxx
local:
path: /config/db.sqlite3


# 防止暴力攻击
regulation:
max_retries: 3
find_time: 2m
ban_time: 120m


# 邮件通知
notifier:
smtp:
username: 12345@qq.com
password: 4Rcec6pUA
host: smtp.exmail.qq.com
port: 465
sender: 12345@qq.com


# 身份提供商:https://www.authelia.com/configuration/identity-providers/open-id-connect/
identity_providers:
oidc:
hmac_secret: xxx
issuer_private_key: |
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
access_token_lifespan: 1h
authorize_code_lifespan: 1m
id_token_lifespan: 1h
refresh_token_lifespan: 90m
enable_client_debug_messages: false
enforce_pkce: public_clients_only
cors:
endpoints:
- authorization
- token
- revocation
- introspection
allowed_origins:
- https://outline.example.com
allowed_origins_from_client_redirect_uris: false
# 客户端列表
clients:
- id: outline
description: outline团队知识库
secret: 'TBbCctA3uCpeUn1U04th1UV6dwrKVaAccME4LIrhKSZ_P3R8an4VK6IqO5qnzNSuhEIdSR7l'
public: false
scopes:
- openid
- offline_access
- profile
- email
# 单因素认证,这里改为双因素的话登录需要二次验证
authorization_policy: one_factor
# 回调URL
redirect_uris:
- https://outline.example.com/auth/oidc.callback
userinfo_signing_algorithm: none

后端验证文件

users_database.yml 是身份后端验证方式之一,使用文件来做验证,当然也可以选择LDAP。

用户密码文件的参考文档:user–password-file

1
2
3
4
5
6
7
8
9
10
11
users:
# outline就是登录用户名
outline:
disabled: false
# 登陆后在authelia页面显示的名称
displayname: "Outline"
password: "$argon2id$v=19$m=65536,t=3,p=4$9BTjyrRh5FNYjvpO4wIa9A$oLqRqvjjb9twHBI0ELA6AP/NXsJcrMwv9vACo2+J/A0"
# 邮箱,可以在configuration.yml中的authentication_backend启用是否支持邮箱登录,默认没有启用邮箱登录
email: 123@example.com
groups:
- admins

password 的生成,复制生成的Digest:后面的参数

1
docker run --rm authelia/authelia:4.37.5 authelia crypto hash generate argon2 --password 'password'

outline

编辑 outline-docker.env 文件,完整的官方配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# ================ Outline ================
NODE_ENV=production
# 一个十六进制编码的 32 字节随机密钥。官方推荐使用 `openssl rand -hex 32` 在你的终端生成
SECRET_KEY=xxx
# 一个唯一的随机密钥。格式并不重要,官方推荐使用 `openssl rand -hex 32` 在你的终端生成
UTILS_SECRET=xxx

# 表示外部浏览器将会以什么域名访问 Outline 及其资源文件
# 1. outline.example.com: 修改为你自己的域名
URL=https://outline.example.com

# Outline 使用的端口
PORT=3000

# 使用本地存储,没有使用S3
FILE_STORAGE=local
# =========================================


# ================ PostgreSQL ================
# 用于连接 PostgreSQL 的 URL,password是在docker-compose中定义的
DATABASE_URL=postgres://outline:password@postgres:5432/outline
# 禁止使用SSSL连接
PGSSLMODE=disable
# ============================================


# ================ Redis ================
# 用于连接 Redis 的 URL
REDIS_URL=redis://redis:6379
# =======================================



# ================ AUTHENTICATION ================
# ID要和authelia配置文件中的identity_providers.clients.id保持一致
OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=TBbCctA3uCpeUn1U04th1UV6dwrKVaAccME4LIrhKSZ_P3R8an4VK6IqO5qnzNSuhEIdSR7l

# 将sso.example.com换成自己的
OIDC_AUTH_URI=https://sso.example.com/api/oidc/authorization
OIDC_TOKEN_URI=https://sso.example.com/api/oidc/token
OIDC_USERINFO_URI=https://sso.example.com/api/oidc/userinfo

# outline登录界面显示的名称:使用{}登录
OIDC_DISPLAY_NAME=账号密码

OIDC_USERNAME_CLAIM=preferred_username
OIDC_SCOPES="openid offline_access profile email"

备份路径

需要备份的内容:

  • /var/lib/docker/volumes/outline_database-data
  • /var/lib/docker/volumes/outline_outline-data
  • docker-compose.yml 同级目录下的 data 文件