AFFiNE 自托管完整部署
前言
AFFiNE 是一款开源的知识管理工具,支持本地优先和云端同步。本文将详细记录在 2GB 内存 VPS 上从零开始部署 AFFiNE 的完整过程,包括所有遇到的问题和解决方案。
测试环境:
- 系统:Ubuntu 22.04
- CPU:2 核
- 内存:2GB RAM
- 存储:50GB SSD
- 面板:1Panel
第一步:环境准备
1.1 检查系统资源
# 检查内存
free -h
# 检查磁盘空间
df -h
# 检查 CPU
lscpu
1.2 安装 Docker 和 Docker Compose
如果使用 1Panel 面板,Docker 环境已自动安装。否则需要手动安装:
# 更新软件源
sudo apt update
# 安装 Docker
curl -fsSL https://get.docker.com | bash
# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker
# 安装 Docker Compose V2
sudo apt install docker-compose-plugin
# 验证安装
docker --version
docker compose version
1.3 配置 Swap(关键步骤)
重要:2GB 物理内存无法稳定运行 AFFiNE,必须添加 Swap。
# 创建 4GB Swap 文件
sudo fallocate -l 4G /swapfile
# 设置权限
sudo chmod 600 /swapfile
# 格式化为 Swap
sudo mkswap /swapfile
# 启用 Swap
sudo swapon /swapfile
# 验证 Swap 已启用
free -h
# 设置开机自动挂载
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 调整 Swap 使用策略(可选,降低对物理内存的压力)
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
第二步:部署 AFFiNE
2.1 方案选择
有两种部署方式:
方案 A:使用 1Panel 应用商店(推荐新手)
- 优点:一键安装,自动配置
- 缺点:配置文件修改不便
方案 B:手动 Docker Compose(推荐进阶用户)
- 优点:完全控制配置
- 缺点:需要手动维护
本文以方案 B 为例,方案 A 可参考 1Panel 应用商店说明。
2.2 创建项目目录
# 创建项目目录
mkdir -p /opt/affine
cd /opt/affine
# 创建数据目录
mkdir -p data/config data/storage data/postgres data/redis
2.3 创建 docker-compose.yml
nano docker-compose.yml
粘贴以下内容:
version: '3.8'
services:
affine:
image: ghcr.io/toeverything/affine-graphql:stable
container_name: affine_app
restart: always
ports:
- "3010:3010"
deploy:
resources:
limits:
cpus: '1.0'
memory: 1200M
reservations:
cpus: '0.5'
memory: 800M
environment:
- NODE_OPTIONS=--import=./scripts/register.js
- AFFINE_CONFIG_PATH=/root/.affine/config
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://affine:affine_password@postgres:5432/affine
- NODE_ENV=production
- AFFINE_SERVER_PORT=3010
- AFFINE_SERVER_HOST=0.0.0.0
volumes:
- ./data/config:/root/.affine/config
- ./data/storage:/root/.affine/storage
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- affine_network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3010/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
postgres:
image: postgres:16-alpine
container_name: affine_postgres
restart: always
volumes:
- ./data/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_USER=affine
- POSTGRES_PASSWORD=affine_password
- POSTGRES_DB=affine
- PGDATA=/var/lib/postgresql/data/pgdata
networks:
- affine_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U affine -d affine"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: affine_redis
restart: always
volumes:
- ./data/redis:/data
command: redis-server --appendonly yes
networks:
- affine_network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
affine_config:
affine_storage:
affine_postgres:
affine_redis:
networks:
affine_network:
driver: bridge
配置说明:
cpus: '1.0':限制最多使用 1 个 CPU 核心memory: 1200M:限制最多使用 1.2GB 内存POSTGRES_PASSWORD:建议修改为强密码ports: "3010:3010":映射到宿主机 3010 端口
2.4 启动服务
# 拉取镜像
docker compose pull
# 启动服务(后台运行)
docker compose up -d
# 查看日志
docker compose logs -f
# 等待 2-3 分钟,直到看到 "Server is ready" 提示
2.5 验证部署
# 检查容器状态(所有容器应为 healthy)
docker compose ps
# 测试服务响应
curl http://localhost:3010/api/health
# 应返回:{"status":"ok"}
访问 http://服务器IP:3010 应该能看到 AFFiNE 登录页面。
第三步:配置反向代理(推荐)
3.1 使用 1Panel OpenResty
如果使用 1Panel 面板,推荐使用内置的 OpenResty 反向代理:
- 进入 1Panel 面板 → 网站管理
- 创建反向代理网站
- 填写配置:
- 域名:
affine.your-domain.com - 代理地址:
http://127.0.0.1:3010 - 启用 HTTPS(推荐使用 Let's Encrypt 自动证书)
- 域名:
3.2 使用 Nginx(手动配置)
# 安装 Nginx
sudo apt install nginx
# 创建配置文件
sudo nano /etc/nginx/sites-available/affine
粘贴以下配置:
server {
listen 80;
server_name affine.your-domain.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name affine.your-domain.com;
# SSL 证书路径(需要先申请证书)
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 日志
access_log /var/log/nginx/affine_access.log;
error_log /var/log/nginx/affine_error.log;
# 反向代理配置
location / {
proxy_pass http://127.0.0.1:3010;
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;
# WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
启用配置:
# 创建软链接
sudo ln -s /etc/nginx/sites-available/affine /etc/nginx/sites-enabled/
# 测试配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
3.3 配置 AFFiNE Base URL(重要)
如果使用域名访问,必须设置 BASE_URL,否则会出现无限重定向问题。
编辑 docker-compose.yml:
nano /opt/affine/docker-compose.yml
在 affine 服务的 environment 部分添加:
environment:
- AFFINE_SERVER_BASE_URL=https://affine.your-domain.com
# ... 其他环境变量
重启服务:
cd /opt/affine
docker compose down
docker compose up -d
第四步:解决常见问题
4.1 容器反复重启
症状:
docker compose ps
# 显示容器状态为 "Restarting"
原因: 内存不足导致 OOM Killer 杀掉进程
解决方案:
- 确认 Swap 已启用:
free -h - 查看系统日志:
dmesg | grep -i oom - 增加 Swap 大小或添加资源限制(见步骤 2.3)
4.2 域名访问出现 ERR_TOO_MANY_REDIRECTS
症状: 浏览器报错"重定向次数过多"
原因: 未设置 AFFINE_SERVER_BASE_URL 导致内部生成 http 链接,反向代理强制跳转 https 形成死循环
解决方案:
- 按照步骤 3.3 设置 BASE_URL
- 清除浏览器缓存
- 如果使用 Cloudflare,清除 CDN 缓存
4.3 CPU 使用率过高
症状: CPU 长期占用 80%-100%
原因: Docker 未限制资源,Node.js 进程占满 CPU
解决方案:
在 docker-compose.yml 中添加资源限制(见步骤 2.3 的 deploy.resources 配置)
4.4 桌面客户端无法登录
症状: 客户端提示"没有权限"或"内容不存在"
原因: AFFiNE 有两种账号模式
- Local First Account:浏览器版默认使用,无密码
- Cloud Account:需要邮箱+密码,桌面客户端仅支持此模式
解决方案:
- 在浏览器版中创建云账号:
- 点击右上角头像
- 选择"设置密码"或"注册云账号"
- 输入邮箱和密码
- 使用新创建的账号密码登录桌面客户端
- 确保在浏览器版中至少创建了一个工作区,并开启云端同步
4.5 数据库初始化失败
症状: 日志显示 Migration failed 或 Database connection error
解决方案:
# 停止服务
docker compose down
# 删除 PostgreSQL 数据(会丢失所有数据!)
rm -rf ./data/postgres/*
# 重新启动
docker compose up -d
# 查看日志,等待数据库初始化完成
docker compose logs -f postgres
第五步:日常维护
5.1 查看服务状态
cd /opt/affine
# 查看容器状态
docker compose ps
# 查看资源占用
docker stats
# 查看日志
docker compose logs -f affine
5.2 备份数据
# 停止服务
docker compose down
# 备份整个数据目录
tar -czf affine_backup_$(date +%Y%m%d).tar.gz ./data
# 重启服务
docker compose up -d
恢复数据:
# 停止服务
docker compose down
# 解压备份
tar -xzf affine_backup_20241124.tar.gz
# 重启服务
docker compose up -d
5.3 更新 AFFiNE
cd /opt/affine
# 拉取最新镜像
docker compose pull
# 重启服务
docker compose down
docker compose up -d
# 查看日志确认更新成功
docker compose logs -f
5.4 清理磁盘空间
# 清理未使用的 Docker 资源
docker system prune -a --volumes
# 警告:会删除所有未使用的镜像、容器、网络和卷
第六步:性能优化建议
6.1 系统层面
# 调整文件描述符限制
echo "* soft nofile 65535" >> /etc/security/limits.conf
echo "* hard nofile 65535" >> /etc/security/limits.conf
# 优化 TCP 参数
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
EOF
sysctl -p
6.2 PostgreSQL 优化
编辑 docker-compose.yml,在 postgres 服务中添加:
postgres:
command:
- postgres
- -c
- shared_buffers=256MB
- -c
- max_connections=100
- -c
- effective_cache_size=512MB
6.3 Redis 优化
redis:
command:
- redis-server
- --appendonly yes
- --maxmemory 256mb
- --maxmemory-policy allkeys-lru
第七步:安全加固
7.1 配置防火墙
# 安装 UFW
sudo apt install ufw
# 允许 SSH
sudo ufw allow 22/tcp
# 允许 HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 如果直接暴露 AFFiNE 端口(不推荐)
sudo ufw allow 3010/tcp
# 启用防火墙
sudo ufw enable
# 查看规则
sudo ufw status
7.2 定期更新系统
# 更新软件包列表
sudo apt update
# 升级系统
sudo apt upgrade -y
# 自动清理
sudo apt autoremove -y
7.3 配置自动备份
创建备份脚本:
nano /opt/affine/backup.sh
内容:
#!/bin/bash
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
cd /opt/affine
docker compose down
tar -czf $BACKUP_DIR/affine_$DATE.tar.gz ./data
docker compose up -d
# 保留最近 7 天的备份
find $BACKUP_DIR -name "affine_*.tar.gz" -mtime +7 -delete
echo "Backup completed: affine_$DATE.tar.gz"
设置权限和定时任务:
chmod +x /opt/affine/backup.sh
# 添加到 crontab(每天凌晨 2 点备份)
crontab -e
# 添加以下行
0 2 * * * /opt/affine/backup.sh >> /var/log/affine_backup.log 2>&1
总结
本文完整记录了在 2GB 内存 VPS 上部署 AFFiNE 的全过程,包括:
- ✅ 环境准备(Swap 配置)
- ✅ Docker Compose 部署
- ✅ 反向代理配置
- ✅ 常见问题排查
- ✅ 日常维护方案
- ✅ 性能优化建议
- ✅ 安全加固措施
关键要点:
- 2GB 内存必须添加 Swap
- 必须配置资源限制防止 CPU 占满
- 使用域名必须设置 BASE_URL
- 桌面客户端需要创建云账号
资源占用情况:
- CPU:日常 5%-30%,峰值 50%
- 内存:物理内存 1.5GB,Swap 300MB
- 磁盘:约 5-10GB(取决于数据量)
如果你的服务器配置更高(如 6 核 8GB),可以移除资源限制配置,获得更好的性能表现。
相关链接:
- AFFiNE 官网:https://affine.pro
- GitHub:https://github.com/toeverything/AFFiNE
- 官方文档:https://docs.affine.pro