介绍

  • Excalidraw是一个手写体风格的流程图项目,通过浏览器进行访问,可以导入各种图形库,非常方便,而且好看
  • 该项目可以本地作图,也可以多人同时在线协作作图,也可以AI交互使用,官方体验:Excalidraw
  • 官方项目部署简单excalidraw
  • 官方项目默认数据保存在浏览器缓存中或者官方数据库中(尤其是协作模式),本文介绍一个二开项目,主要是将数据进行本地化存储,确保所有数据可控
  • 二开项目地址:BetterAndBetterII/excalidraw-full

简单本地docker环境部署

项目文档中文简介写的很清晰

当前(2025年12月1日)该项目配置文件存在一点小问题,如果使用的是github认证,不会有问题
如果使用dex认证,但是用的其默认配置的端口号,也不会有问题
但是如果要修改服务地址或者端口号,则需要在.env配置文件中添加一条配置OIDC_ISSUER环境变量,其内容和OIDC_ISSUER_URL指定相同即可

局限性

默认配置适用于本地使用,不能跨设备使用

搭建流程

首先说明:

  • 这里的搭建流程实现的是将服务可以通过域名在其他设备上或者外网进行访问,对外实现的基本内容不在介绍范围,比如内网穿透之类的
  • 整个项目是在Ubuntu24.04环境上通过docker进行搭建的
  • 作者的二开项目中存在两种认证方式,一种是通过github认证,另一种是自建dex服务进行认证
  • 由于github访问在国内不是很友好,所以使用自建dex服务的方式
  • 二开项目中默认的dex是通过docker compose创建.
    而我个人觉得,从网络的访问来讲,这应该是两个独立的项目,两者不需要依赖同一个网络环境,所以两个服务拆开搭建

搭建dex服务

配置文件准备

这里需要一个yaml配置文件和一个数据库文件dex.db

这里使用的dex服务是通过数据库进行保存用户名和密码的
如果不想用数据库保存,则可以配置为项目中config/dex.config.yaml的静态方式

创建配置文件

配置文件dex.config.yaml内容:

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
issuer: https://your_dex_address

storage:
type: sqlite3
config:
file: /data/dex.db

web:
http: 0.0.0.0:5556
allowedOrigins: ["*"]

logger:
level: debug
format: text

enablePasswordDB: true

oauth2:
skipApprovalScreen: true

staticClients:
- id: excalidraw
redirectURIs:
- https://your_excalidraw_address/auth/callback
name: Excalidraw
public: true
secret: this_is_secret

issuer: 这里配置的是dex的地址
storage: 数据存储方式
oauth2.skipApprovalScreen: 设置为true后就不会有二次同意的界面了
staticClients: dex是服务端,这里是静态配置客户端的内容,其中idsecret需要和excalidraw那边对应相同

创建数据库文件

注意数据库的属主必须是1001,不然docker内部无权限访问

1
2
touch dex.db
chown 1001:1001 dex.db

拉起服务

通过docker命令拉起使用

1
2
3
4
5
6
7
8
docker run -d \
--name dex \
--restart unless-stopped \
-p 5556:5556/tcp \
-v ./dex.config.yaml:/etc/dex/config.yaml:ro \
-v ./dex.db:/data/dex.db \
dexidp/dex \
dex serve /etc/dex/config.yaml

服务拉起后需要添加用户数据到数据库中

1
2
3
4
5
6
7
# apt install sqlite3
# 进入数据库
sqlite3 dex.db
# 插入一条用户数据
insert into password values('admin@example.com', '$2a$10$2lsidfjaGIGrs1HsldifjasdiyhLIHlakssdlfijIZck7Mc8T4W', 'admin', 'f2538a29-f57b-4a8f-8c8f-e0ed420bdf44');
# 退出
.quit

其中values中的四个部分:

  1. 邮箱,不需要认证,之后登陆时使用的内容
  2. 密码,生成方式:echo password | htpasswd -BinC 10 admin | cut -d: -f2,需要安装apache2-utils工具包,其中password是你自己的密码
  3. 用户名
  4. UUID,随便一个字符串就行,也可以通过cat /proc/sys/kernel/random/uuid生成一个

nginx代理配置

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
server {
listen 80;
listen [::]:80;
server_name your_dex_address;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 443 ssl;
listen [::]:443 ssl;

server_name your_dex_domain;
charset utf-8;

ssl_certificate your_pem_path;
ssl_certificate_key your_key_path;

location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
proxy_redirect off;
proxy_pass http://localhost:5556;
}
}

搭建excalidraw-ful服务

配置

这里需要两个,一个配置文件,另一个是数据库,该数据库用来保存画板数据
创建数据库文件:
touch excalidraw.db
这里没有权限要求!
配置文件env.conf内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
OIDC_ISSUER_URL=https://your_dex_address
OIDC_CLIENT_ID=excalidraw
OIDC_CLIENT_SECRET=this_is_secret
OIDC_REDIRECT_URL=https://your_excalidraw_address/auth/callback

JWT_SECRET=xxxxx

STORAGE_TYPE=sqlite
DATA_SOURCE_NAME=excalidraw.db
LOCAL_STORAGE_PATH=./data

OPENAI_API_KEY=sk-your_openai_api_key
OPENAI_BASE_URL=https://api.openai.com

说明:

  • OIDC相关参数: 和dex服务中配置对应即可
  • JWT_SECRET: 用于签署会话令牌的强随机字符串,可以使用openssl rand -base64 32生成一个
  • OPENAI相关参数: 是OpenAI的密钥

拉起服务

1
2
3
4
5
6
7
docker run -d \
--name excalidraw-full \
--restart unless-stopped \
-p 3002:3002/tcp \
-v ./excalidraw.db:/root/excalidraw.db \
-v ./env.conf:/root/.env \
ghcr.io/betterandbetterii/excalidraw-full:latest

nginx代理配置

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
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name your_excalidraw_domain;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 443 ssl;
listen [::]:443 ssl;

server_name your_excalidraw_domain;
charset utf-8;

ssl_certificate your_pem_path;
ssl_certificate_key your_key_path;
ssl_session_timeout 20m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_verify_client off;

location / {
proxy_http_version 1.1;
proxy_pass http://localhost:3002;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600s;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

遇到的问题

登陆时报错

1
2
3
Authentication not configured
# 或者
OIDC not configured

原因就是dex的配置文件和excalidraw的配置文件中相关配置不对,或者地址写错导致一个找不到另一个

协作模式无法使用

打开浏览器的开发者模式(F12)可以看到控制台报错

1
WebSocket connection to 'wss://your_excalidraw_address/socket.io/?EIO=4&transport=websocket' failed:

原因是websocket的https无法访问导致,如果是通过nginx代理的,需要配置wws才可以,直接使用我上面的配置就可以解决

参考