Docker 安装 AFFiNE

Docker 安装 AFFiNE

目前开源的笔记大致有几个选择:

  1. 思源笔记, 必须登录官方账号并付费才可以开启多端同步;
  2. 为知笔记 docker 镜像, 好久没更新了,但客户端齐全;
  3. AppFlowy, 依赖 openai 搜索,搜索功能基本是残废;
  4. AFFiNE, 没有手机 APP, 基本能平替思源笔记;
  5. outline, 私有化部署非常繁琐复杂,和 AppFlowy 几乎一样困难;
  6. vnote, 无需部署,可通过 git 同步,仅桌面 client;

思源笔记及其风险

在这几个笔记软件中,说实话,思源最突出,功能强大,体验舒适,但是,作者曾经的恶作剧也很恶心,另外,使用 s3 同步功能居然收费,收费也就罢了,毕竟开发不易,觉得收费不合理可以不用,但还需要登录他们社区的账号才可以,假设他们社区挂了,我的笔记是不是就没法同步下来了?一些背景:

  1. 使用 Github 账号登录 黑客派 之后, Github 自动 follow、star
  2. 关于我们犯过的错和道歉

总结下,思源笔记的作者,自己也承认,曾经,只要你使用 github 登录他们的社区,就会自动 follow 和 star 他的项目,并因此搞的 github 规范其开放接口并清零了他们的 star,但凡你找份正经工作,你都没心思搞这种蝇头小利,另外,开源的项目中,内置挖矿脚本,群发推广邮件给自己的用户。

思源笔记的作者并不是喜欢开源而开源,TA 有非常强烈的商业诉求,但是否成功不确定,所以思源笔记不值得信赖!
社区有思源笔记的二开版本,去除了需要登录且付费才能使用 s3 同步的限制,项目名字叫:siyuan-unlock
怎么说呢,社区的这种行为虽然不应该被推广,毕竟断人财路,但很抱歉,这是合法的,思源笔记基于 GPL 协议开源,除非获得商业授权,否则修改后使用必须要开源。如果一定要使用思源笔记,建议用 siyuan-unlock, 且不要追新版本,选用半年前的版本就行,除非必须,否则不要升级,鬼知道会不会继续挖矿,或者有其他问题,比如隐私泄露,数据丢失等等。

抛开作者曾经做的恶,思源笔记本身还不错,功能强大(有 database, 做 todo 很完美), 插件完善,主题丰富(虽然质量堪忧), 有移动端,不过不是标准 markdown, 未来如果数据迁移,可能不丝滑。

AFFiNE - 功能更强大

比起思源笔记,AFFiNE 功能更强大,除了支持 database 外还支持 kanban, 思维导图,画板,但暂无手机 app

outline 和 Appflowy

outline 颜值不错,我使用了很长一段时间,只是部署很麻烦,仅有 web 端,只有基础功能。 AppFlowy 功能上和思源差别不大,但搜索依赖 openai, 私有化部署后,搜索基本是残废,不建议用。部署难度比 outline 还高;

为知笔记 docker 镜像,功能上和为知笔记没差别,也可以直接用为知笔记的 client, 但很久没更新了,且不开源。
vnote 我曾经使用了数年,体验不错,作为笔记软件,它几乎是完美的,唯一的缺点就是不方便,需要安装 client, 同步依赖 git 仓库。

我对笔记软件的诉求

我希望笔记软件可以做到:

  1. 按工作区或笔记本分割,比如工作笔记那就是工作笔记,和私有笔记不应该只是一个目录或 tag 的区别,假设你写了一个雄心勃勃的学习或健身计划在私有笔记中,但工作笔记和私有笔记只是目录不同,在目录展开的情况下,你的个人隐私就一览无余。
  2. 支持待办,如果支持看板更好;
  3. 多端同步或有 web 版本;
  4. 搜索功能不能垃圾,如果我知道啥是啥,我用笔记软件干嘛?
  5. 数据可控,我可以自己备份或导出;
  6. 不受制于人,这和数据可控一样的,思源由于要登录账号,所以不敢用,而不是付费;

综合这些诉求,其实真的只有 AFFiNE 能满足我,第一条就过滤了不少。或许某天,我退休了,或者有空了,我会开发下笔记软件,我的理念是 all in one, 笔记 + 待办 + 博客 + wiki, 是否有 ai 其实远没那么重要。

AFFiNE 私有化部署

AFFiNE 私有化部署算是简单的了,主要分:

  1. .env 文件;
  2. docker-compose.yml 文件;
  3. nginx 配置;

AFFiNE - env 文件

.env
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
AFFINE_REVISION=stable
PORT=3010
UPLOAD_LOCATION=/data/soft/affine/storage
CONFIG_LOCATION=/data/soft/affine/config
AFFINE_SERVER_HOST=affine.kpromise.top
AFFINE_SERVER_PORT=3010
AFFINE_SERVER_HTTPS=true
MAILER_HOST=smtp.kpromise.top
MAILER_PORT=465
MAILER_USER=xxx@kpromise.top
MAILER_SENDER=xxx@kpromise.top
MAILER_PASSWORD=your-email-password
DATABASE_URL=postgres://affine:affine-password@your-postgres-db-host:5432/affine-db
REDIS_SERVER_HOST=your-redis-host
REDIS_SERVER_PORT=6379
REDIS_SERVER_USER=
REDIS_SERVER_PASSWORD=
REDIS_SERVER_DATABASE=1
TELEMETRY_ENABLE=false
NODE_ENV=production

env 文件里,主要是 postgres、redis、email 相关的配置;

AFFiNE - docker-compose.yml

docker-compose.yml
 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
name: affine
services:
  affine:
    image: ghcr.io/toeverything/affine-graphql:${AFFINE_REVISION:-stable}
    container_name: affine
    ports:
      - '${PORT:-3010}:3010'
    depends_on:
      affine_migration:
        condition: service_completed_successfully
    volumes:
      # custom configurations
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    env_file:
      - .env
    networks:
      - dockerNetwork

  affine_migration:
    image: ghcr.io/toeverything/affine-graphql:${AFFINE_REVISION:-stable}
    container_name: affine_migration_job
    volumes:
      # custom configurations
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
    env_file:
      - .env
    networks:
      - dockerNetwork

networks:
  dockerNetwork:
    external: true

AFFiNE - nginx 配置

affine.conf
 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
server {
    listen 443 ssl http2;
    server_name affine.kpromise.top;
    charset uft-8;

    location / {
        proxy_pass https://pi-server;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|zip|map)$ {
        set $custom_root /data/soft/affine/static;
        if ($http_referer ~* "note.kpromise.top/admin") {
            set $custom_root /data/soft/affine/static/admin;
        }
        root $custom_root;
        expires 7d;
        access_log off;
        try_files $uri $uri/ =404;
    }
    ssl_certificate_key /xxx/note.key;
    ssl_certificate /xxx/fullchain.cer;
    ssl_session_timeout 10m;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256::!MD5;
}

nginx 里面我做了动静分离,将 docker 里面的 static 目录 pull 出来,然后动静分离,主要是我采用内网穿透,如果静态资源也需要回源到内网,那么速度会非常慢,动静分离后,动态资源才回源到本地,速度更快。

这里的 postgres 需要支持向量,可以参考:Docker 运行 postgresql
如需自行构建 affine,请参考:自行构建 affine

最后更新于