AFFiNE 新版本升级
一、备份
先把当前状态记录下来(有助于回滚):
# 查看容器
docker ps -a
# 查看 affine 相关镜像、标签
docker images | grep affine
# 导出每个容器的配置(备份)
cd /root
mkdir affine_backup
docker inspect affine_server > /root/affine_backup/inspect_affine_server.json
docker inspect postgres > /root/affine_backup/inspect_postgres.json
docker inspect redis > /root/affine_backup/inspect_redis.json
# docker-compose文件位置——compose.yml
cd /home/affine
(用当前日期替换下面示例中的 2025-09-08)
1、备份 Postgres(推荐用 pg_dumpall 或 pg_dump)
先查看 Postgres 容器名(现有的是 postgres),然后:
# 在宿主机生成 SQL 转储(推荐)
docker exec -t postgres bash -lc 'pg_dumpall -U "${POSTGRES_USER:-postgres}"' > /root/affine_backup/affine_pg_dumpall_2025-09-08.sql
# 或备份单库(如果知道数据库名,例如 affine)
docker exec -t postgres pg_dump -U "${POSTGRES_USER:-postgres}" -d affine -Fc -f /tmp/affine_db_2025-09-08.dump
docker cp postgres:/tmp/affine_db_2025-09-08.dump /root/
如果
POSTGRES_USER/POSTGRES_DB不确定,可先用docker inspect postgres或docker exec -it postgres env | grep POSTGRES查看环境变量。 注意:如果将来需要升级 Postgres 的 major 版本(例如 pg16→pg17),官方特别警告:不能直接改镜像 tag,需要 dump/restore(也就是说备份是必须的)。docs.affine.pro
2、备份 Redis
# 触发 RDB 写入
docker exec redis redis-cli SAVE
# 将 rdb 拷贝到宿主机
docker cp redis:/data/dump.rdb /root/affine_backup/affine_redis_dump_2025-09-08.rdb
(如果使用 AOF 或者自定义数据目录,请根据实际 mount 点拷贝相应文件)
3、备份上传文件 / 存储(AFFiNE 的 storage)
先找出 affine 容器的挂载点(host path):
docker inspect affine_server --format '{{range .Mounts}}{{println .Source " -> " .Destination}}{{end}}'
返回 /home/affine/self-host/storage -> /root/.affine/storage,那么备份为:
tar -czf /root/affine_backup/affine_storage_backup_2025-09-08.tar.gz -C /home/affine/self-host/storage .
附:实际返回(记住此路径,后面会用到 docker-compose.yml 中)
/home/affine/self-host/config -> /root/.affine/config
/home/affine/self-host/storage -> /root/.affine/storage
如果数据是 docker volume,可以这样备份:(此处不采用)
# 列出卷
docker volume ls
# 用临时容器将卷打包到宿主机
docker run --rm -v affine_volume_name:/data -v /root:/backup alpine \
sh -c "cd /data && tar czf /backup/affine_volume_affine_volume_name_2025-09-08.tar.gz
4、备份配置(.env / docker-compose.yml / 自定义配置)
把现有 .env、compose 文件、副本全部备份到 /root/affine_backup/backup_affine_configs_2025-09-08/。如果没有 .env 文件,可从容器环境导出:
docker exec affine_server printenv > /root/affine_backup/affine_server_env_2025-09-08.txt
二、升级 AFFiNE 的生产环境操作步骤
以下基于当前环境 /home/affine/compose.yml,路径 /home/affine/self-host/{config,storage}。
1. 准备升级目录
mkdir -p /root/affine_upgrade
cd /root/affine_upgrade
# 下载最新 compose 文件(以官方 release 链接为准)
# 此文件源文件已经拉取到192.168.201.202(升级测试机)/home/yunweizu/affine_upgrade_2025_09_08/目录下备份用,如无外网环境到此处cp
wget -O docker-compose.yml https://github.com/toeverything/AFFiNE/releases/latest/download/docker-compose.yml
# 同步示例 env(可能有新增参数)
wget -O .env.example https://raw.githubusercontent.com/toeverything/AFFiNE/main/.github/deployment/self-host/.env.example || true
# 对比配置
diff -u /home/affine/compose.yml /root/affine_upgrade/docker-compose.yml | less
👉 在 docker-compose.yml 和 .env 中确认以下几点:
- Postgres 数据卷 映射到
/home/affine/self-host/config - storage 卷 映射到
/home/affine/self-host/storage - Redis 保持不变
- 端口仍然是
80:3010 - 新增的环境变量(比如
ENABLE_MERMAID=true)要补到.env
🔑 docker-compose.yml 关键变化点
- 镜像名称
- 旧:
ghcr.io/toeverything/affine-graphql - 新:
ghcr.io/toeverything/affine👉 必须改。因为官方已经弃用affine-graphql镜像,新版本统一用affine。
- 旧:
- 端口映射
- 旧:固定
80:3010 - 新:
${PORT:-3010}:3010👉 更灵活,推荐改成新写法。但如果你原本就在 Nginx 前做反代,实际没区别。
- 旧:固定
- 新增环境变量
- 新增
AFFINE_INDEXER_ENABLED=false👉 建议跟随官方模板加上。这个控制是否启用索引功能(全文检索/AI 相关)。生产环境如果暂时不用,可以保持false。
- 新增
- Redis
- 旧:
container_name: redis+ 暴露 6379 端口 - 新:
container_name: affine_redis,不再暴露宿主机端口 👉 生产环境如果没有外部应用要直连 Redis,建议用新版(不暴露 6379,更安全)。
- 旧:
- Postgres
- 旧:
image: postgres:16,container_name: postgres,端口 5432 - 新:
image: pgvector/pgvector:pg16,container_name: affine_postgres,不暴露端口 👉 升级点最重要!AFFiNE 新版推荐用带pgvector扩展的镜像(支持向量搜索 / AI 功能)。 ⚠️ 风险点:容器名变更 →.env或依赖中DATABASE_URL需要同步,否则连不上。
- 旧:
📋 升级时你要做的决策
- 镜像名称 → 必须改成新版本 ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
- 容器名
- 如果你不想修改
.env(里面写了postgres、redis),可以保持旧名字: container_name: postgres
container_name: redis - 如果你愿意完全跟随新模板,就需要:
.env和DATABASE_URL改成affine_postgres和affine_redis。- 现有数据卷要确认是否能直接迁移到新容器。
- 如果你不想修改
- Postgres 镜像
- 如果你需要用 AFFiNE 的新 AI/向量功能 → 换成
pgvector/pgvector:pg16。 - 如果你只是普通文档协作,不依赖向量搜索 → 可以先继续用
postgres:16,降低风险。
- 如果你需要用 AFFiNE 的新 AI/向量功能 → 换成
- Redis 端口
- 如果没有外部依赖,推荐取消暴露(用内部网络通信即可)。
- 如果外部还有调试或监控工具需要直连,就保留
6379:6379。
确认无误后,用更新过的新 compose 文件替换生产目录:
cp /root/affine_upgrade/docker-compose.yml /home/affine/compose.yml
修改已有用户密码(不删除数据)
原密码为空,会报错,建议修改密码为affine
进入 PostgreSQL 容器:
docker exec -it postgres psql -U affine -d affine
修改密码:
ALTER USER affine WITH PASSWORD 'affine';
退出 psql:
\q
- 确认
.env里的DB_PASSWORD与新密码一致,然后再运行迁移:
docker-compose up --no-deps --exit-code-from affine_migration affine_migration
compose.yml 参考 /home/affine/compose.yml
name: affine
services:
affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
container_name: affine_server
ports:
- '${PORT:-3010}:3010'
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
affine_migration:
condition: service_completed_successfully
volumes:
# custom configurations
- ${UPLOAD_LOCATION}:/root/.affine/storage
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE}
- AFFINE_INDEXER_ENABLED=false
restart: unless-stopped
affine_migration:
image: ghcr.io/toeverything/affine:${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
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE}
- AFFINE_INDEXER_ENABLED=false
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
redis:
image: redis
container_name: redis
healthcheck:
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
postgres:
image: pgvector/pgvector:pg16
container_name: postgres
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_DATABASE:-affine}
POSTGRES_INITDB_ARGS: '--data-checksums'
# you better set a password for you database
# or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
POSTGRES_HOST_AUTH_METHOD: trust
healthcheck:
test:
['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
.env 参考 /home/affine/.env
如果主机有迁移,IP地址有变化,AFFINE_SERVER_HOST 和 AFFINE_SERVER_EXTERNAL_URL 要对应修改
注意:把 DB_PASSWORD=安全考虑已清理 这行 DB_PASSWORD=affine 设置一个新密码
# select a revision to deploy, available values: stable, beta, canary
AFFINE_REVISION=stable
# set the port for the server container it will expose the server on
PORT=80
# set the host for the server for outgoing links
AFFINE_SERVER_HTTPS=false
AFFINE_SERVER_HOST=192.168.201.202
# or
AFFINE_SERVER_EXTERNAL_URL=http://192.168.201.202
# position of the database data to persist
DB_DATA_LOCATION=/home/affine/self-host/postgres/pgdata
# position of the upload data(images, files, etc.) to persist
UPLOAD_LOCATION=/home/affine/self-host/storage
# position of the configuration files to persist
CONFIG_LOCATION=/home/affine/self-host/config
# database credentials
DB_USERNAME=affine
DB_PASSWORD=affine
# 此处设置一个密码affine,否则升级报错,处理较麻烦
DB_DATABASE=affine
MAILER_HOST=smtp.exmail.qq.com
MAILER_PORT=465
MAILER_USER=devops@akuvox.com
MAILER_PASSWORD=knGnfce3ALz8kUm6
MAILER_SENDER=devops@akuvox.com
安装独立版 Docker Compose(推荐,兼容老系统)
# 1. 下载 docker-compose 二进制(v2.27.0 为例,官方最新稳定版)
curl -L "https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 2. 添加执行权限
chmod +x /usr/local/bin/docker-compose
# 3. 建立软链接(有些系统只认这个名字)
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 4. 验证
docker-compose version
2. 拉取最新镜像
进入生产目录,拉取新版本镜像:
cd /home/affine
docker-compose pull
3. 停止旧 affine 容器(保留数据库和 redis)
docker stop affine_server || true
docker rm affine_server || true
不要停 Postgres、Redis,因为它们是数据依赖。
4. 运行 migration job
新版本通常需要迁移数据库 schema,必须跑 migration job:
docker-compose up --no-deps --exit-code-from affine_migration affine_migration
如果没有 affine_migration 服务,可以这样跑:(已有服务,不采用)
docker run --rm \
--network=host \
-e DATABASE_URL="postgresql://<user>:<pass>@127.0.0.1:5432/<db>" \
-e REDIS_SERVER_HOST="127.0.0.1" \
-v /home/affine/self-host/storage:/root/.affine/storage \
-v /home/affine/self-host/config:/root/.affine/config \
ghcr.io/toeverything/affine-graphql:stable \
sh -c "node ./scripts/self-host-predeploy.js"
观察日志,确认返回码是 0,否则停止操作。
5. 启动新 affine 服务
docker-compose up -d affine
查看日志:
docker logs -f affine_server
6. 验证服务
- 浏览器访问 http://192.168.201.202 (或绑定域名),能正常打开。
- 登录原有账号,检查页面内容是否完整。
- 新建文档,插入一个 mermaid 代码块测试渲染。
- 上传文件、搜索功能、协作是否正常。
docker ps检查所有容器健康状态。
7. 升级完成后清理
等确认 24~48 小时无异常,再清理旧镜像:
docker image prune -a
升级后会发生的情况
- affine_server 容器会被替换(镜像更新),但数据不会丢失,因为你保留了 Postgres/Redis/storage 的 volume 映射。
- 数据库 schema 被迁移,旧版本无法再直接读取,回滚时必须用备份恢复。
- 配置文件若未合并新增变量,可能导致新功能不可用(例如 mermaid 渲染)。
- Redis 缓存可能被清空,但这不会影响持久化数据。
修改密码
方法一:
把一个用户的密码覆盖到另一个用户。 users 表里密码是 argon2id 哈希,假设将zhongping.wei密码覆盖到Kidd,可以直接把 zhongping.wei 的 password 拷贝过去。
在 psql 里执行:
UPDATE users
SET password = (
SELECT password FROM users WHERE name = 'zhongping.wei'
)
WHERE name = 'Kidd';
然后检查一下:
SELECT name, password FROM users WHERE name IN ('zhongping.wei', 'Kidd');
看到 Kidd 的 password 已经和 zhongping.wei 一样了。 此时,Kidd 就能用 zhongping.wei 的密码登录。
方法二:
Affine 的 users 表里密码字段是 bcrypt 哈希。所以需要:
- 生成 bcrypt 哈希
- 用 SQL 更新
users表
1. 本地生成 bcrypt 哈希
直接在宿主机上生成,步骤如下:
# 安装 Python 的 bcrypt 库
pip install bcrypt
新建一个脚本 gen_bcrypt.py:
import bcrypt, os
password = os.environ.get("NEWPASS", "Akuvox@2025")
hashed = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed.decode())
运行:
NEWPASS='Akuvox@2025' python3 gen_bcrypt.py
会输出类似:
$2b$12$KpYcD93S8Y/4b3G5XjNw/.rQx5rNw7DD0k5b6d0Q6C4pTQqp6SNCW
这个就是 Affine 数据库接受的哈希值。
2. 更新数据库
进入 PostgreSQL:
docker exec -it postgres psql -U affine -d affine
找到你要改的用户 ID 或邮箱(举例查邮箱):
SELECT id, email FROM users;
假设要修改 admin@example.com 这个用户:
UPDATE users
SET "password" = '$2b$12$KpYcD93S8Y/4b3G5XjNw/.rQx5rNw7DD0k5b6d0Q6C4pTQqp6SNCW'
WHERE email = 'admin@example.com';
📍 在 AFFiNE 里怎么用 Mermaid?
- 在编辑器中新建一个代码块(和写代码一样)。
- 把语言指定为
mermaid。 - 输入 Mermaid 语法。
例子(直接复制到 AFFiNE 代码块里):
graph TD
A[Start] --> B{Is AFFiNE upgraded?}
B -->|Yes| C[Enjoy Mermaid 🎉]
B -->|No| D[Upgrade first]

渲染后,你会看到一张流程图。

作者
fffff@xf.nn
