ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Actual sync-server 自托管部署与 CLI 实战:从 npm 安装到密码重置的完整指南

Actual sync-server 自托管部署与 CLI 实战:从 npm 安装到密码重置的完整指南 Actual sync-server 自托管部署与 CLI 实战从 npm 安装到密码重置的完整指南【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual导读本文围绕 Actual 开源仓库中的 packages/sync-server/README.md 展开系统讲解 Actual 官方同步服务器actual-app/sync-server的定位、CLI 工具的安装与使用、配置体系、Docker 部署方式及底层实现。读完本文你将掌握如何在自己的服务器上运行 Actual 同步服务、通过--config定制运行参数、使用--reset-password重置密码并能从源码层面理解端口、数据目录、HTTPS、登录方式等关键配置的真实生效机制。Actual 同步服务器local-first 理念的落地载体Actual 是一款本地优先local-first的个人财务管理应用完全免费开源使用 Node.js 编写。所谓本地优先意味着你的账本数据默认保存在本地应用无需依赖云端即可完成记账、预算等核心操作而sync-server包对应 packages/sync-server/package.json 中名为actual-app/sync-server的发布包则在此基础上增加了一个同步服务器组件用于持久化变更并把数据同步到所有设备让手机、平板、电脑之间的数据保持一致不需要任何繁重操作即可在设备间移动变更。从仓库结构看sync-server 不是独立于 Actual 的旁支模块而是整个 monorepo 的组成部分它的依赖列表中包含了actual-app/crdt同步所需的 CRDT 实现见 packages/crdt/src/crdt与actual-app/webActual 的前端构建产物用于服务器直接托管 Web 客户端。因此运行 sync-server 就等于同时获得了最新版的 Actual Web 应用与跨设备同步能力。环境要求与 CLI 安装官方 README 明确要求使用actual-app/sync-servernpm 包需要 Node.js v22 或更高版本。这一约束在 packages/sync-server/package.json 的engines字段中同样有声明node: 22属于硬性前提。安装方式为全局安装npm install --locationglobal actual-app/sync-server安装完成后npm 会根据 packages/sync-server/package.json 中bin字段的映射actual-server: ./build/bin/actual-server.js在 PATH 中注册actual-server可执行命令之后便可以在终端中直接调用。如果想从源码自行构建运行也可以使用仓库提供的 npm 脚本见 packages/sync-server/package.json 的scriptsyarn build node build/app.js提示从源码启动时入口 packages/sync-server/app.ts 会先执行数据库迁移再启动应用——它先调用runMigrations()成功后才动态import(./src/app.js)并运行避免因迁移未完成导致应用在缺表状态下启动。actual-server 命令行四个核心选项actual-server的命令行用法非常简洁actual-server [options]官方 README 提供的选项如下表命令说明-h或--help打印帮助列表并退出-v或--version打印版本号并退出--config指定配置文件路径--reset-password重置你的密码场景一默认配置直接运行actual-server不传任何参数时服务器以默认配置启动端口5006、监听地址::IPv6 通配通常同时覆盖 IPv4、数据目录优先使用/data若存在否则使用项目根目录。这些默认值来自 packages/sync-server/src/load-config.js 的 convict schemaport默认 5006、hostname默认::、dataDir默认取ACTUAL_DATA_DIR或/data。场景二自定义配置文件actual-server --config ./config.json通过--config传入配置文件路径。从 packages/sync-server/src/load-config.js 的加载逻辑可以看到完整的配置来源优先级若设置了环境变量ACTUAL_CONFIG_PATH直接使用其指向的路径否则尝试项目根目录/config.json若该文件不存在回退到数据目录/config.json配置加载后VAR_FILE形式的环境变量见下文挂载式密钥会覆盖 config.json 与普通环境变量最后通过configSchema.validate({ allowed: strict })做严格校验未知字段会直接报错。因此--config本质上是在默认路径之外显式指定 config.json 的位置便于把配置放在与数据分离的目录或在一个机器上跑多份实例。场景三重置密码actual-server --reset-password密码重置的底层逻辑在 packages/sync-server/src/scripts/reset-password.js 中若服务器尚未设置密码needsBootstrap()为真交互式提示你输入新密码并执行bootstrap({ password })完成初始化输出Password set!若已存在密码则调用changePassword(password)完成重置并输出提示你需要在所有当前已登录的浏览器或设备上使用新密码重新登录。该脚本对应的 npm 命令为yarn reset-password见 packages/sync-server/package.json。README 中关于 CLI 的全部命令与示例均由此脚本支撑属于开箱即用的运维入口。配置体系config.json 与环境变量sync-server 的配置采用 convict 库管理convict出现在 packages/sync-server/package.json 的 dependencies 中所有配置项均可在 config.json 与同名环境变量之间二选一。下面列出 packages/sync-server/src/load-config.js 中 schema 的核心配置项及其默认值配置项环境变量默认值说明portACTUAL_PORT5006服务监听端口hostnameACTUAL_HOSTNAME::监听地址默认 IPv6 通配dataDirACTUAL_DATA_DIR/data不存在则用项目根目录数据目录serverFilesACTUAL_SERVER_FILESdataDir/server-files服务器端文件含同步数据userFilesACTUAL_USER_FILESdataDir/user-files用户文件webRootACTUAL_WEB_ROOTactual-app/web构建目录Web 前端静态资源位置loginMethodACTUAL_LOGIN_METHODpassword登录方式password/header/openidtrustedProxiesACTUAL_TRUSTED_PROXIES内网网段列表10.0.0.0/8等可信反向代理 IP 网段https.keyACTUAL_HTTPS_KEY空HTTPS 私钥证书内容或路径https.certACTUAL_HTTPS_CERT空HTTPS 证书证书内容或路径upload.fileSizeLimitMBACTUAL_UPLOAD_FILE_SIZE_LIMIT_MB20JSON 请求体大小上限MBupload.fileSizeSyncLimitMBACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB20同步请求体上限MBupload.syncEncryptedFileSizeLimitMBACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB50加密文件同步上限MBtoken_expirationACTUAL_TOKEN_EXPIRATIONnever登录令牌过期时间支持never、openid-provider或毫秒数userCreationModeACTUAL_USER_CREATION_MODEmanual用户创建模式manual/logincorsProxy.enabledACTUAL_CORS_PROXY_ENABLEDfalse是否开启 CORS 代理端点供前端插件使用github.tokenACTUAL_GITHUB_TOKEN空GitHub API 令牌这些环境变量的命名与取值直接对应 README 之外、config.json的字段例如在 config.json 中可写作{ port: 5006, hostname: ::, https: { key: /data/selfhost.key, cert: /data/selfhost.crt }, upload: { fileSizeLimitMB: 20, fileSizeSyncLimitMB: 20, syncEncryptedFileSizeLimitMB: 50 } }上传限制与请求体的关联三个上传限制并非摆设在 packages/sync-server/src/app.ts 中Express 分别针对三种 body 类型设置了对应上限——express.json({ limit: ...fileSizeLimitMB })处理普通 JSON、application/actual-sync类型使用fileSizeSyncLimitMB、application/encrypted-file类型使用syncEncryptedFileSizeLimitMB。也就是说配置项直接决定了同步大数据量账本时服务器能否接受请求。挂载式密钥_FILE环境变量对于ACTUAL_OPENID_CLIENT_SECRET与ACTUAL_GITHUB_TOKEN这类敏感配置packages/sync-server/src/config-file-env.ts 提供了_FILE变体如ACTUAL_OPENID_CLIENT_SECRET_FILE、ACTUAL_GITHUB_TOKEN_FILE值指向一个文件路径运行时读取文件内容自动trim()去除首尾空白作为配置值。文件不可读时直接抛错避免静默失败。这一机制非常适合 Docker 中通过挂载 secret 文件注入凭据仓库的 upcoming-release-notes/support-file-mounted-secrets.md 也印证了该能力是近期重点演进方向。Docker 一键部署除了 npm 全局安装仓库提供了官方 Docker Compose 编排文件 packages/sync-server/docker-compose.yml适合生产环境或不想污染本机 Node 环境的用户services: actual_server: image: docker.io/actualbudget/actual-server:latest ports: - 5006:5006 # 前面数字可改后面 5006 是容器内端口 environment: # - ACTUAL_HTTPS_KEY/data/selfhost.key # - ACTUAL_HTTPS_CERT/data/selfhost.crt # - ACTUAL_PORT5006 # - ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB20 # - ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB50 # - ACTUAL_UPLOAD_FILE_SIZE_LIMIT_MB20 volumes: - ./actual-data:/data # 宿主机目录挂载到容器内 /data healthcheck: test: [CMD-SHELL, node scripts/health-check.js] interval: 60s timeout: 10s retries: 3 start_period: 20s restart: unless-stopped几个关键点端口映射宿主机端口第一个数字可随意修改容器内固定为5006数据持久化容器内的/data目录是 Actual 默认的数据存放位置务必挂载到宿主机目录如./actual-data防止容器重建导致数据丢失这也与load-config.js中dataDir默认取/data的逻辑完全对应HTTPS若使用自签证书healthcheck 需要额外注入NODE_EXTRA_CA_CERTS/data/selfhost.crtCompose 文件中有对应注释行健康检查通过node scripts/health-check.js验证实例存活对应 packages/sync-server/package.json 中的health-check脚本。启动方式docker compose up -d随后浏览器访问http://localhost:5006即可进入 Actual Web 客户端。服务器内部路由、限流与安全头理解 sync-server 的行为有助于判断自托管时的网络与安全配置。packages/sync-server/src/app.ts 展示了完整的 Express 应用骨架核心路由挂载app.use(/sync, syncApp.handlers); // 数据同步 app.use(/account, accountApp.handlers); // 账户/登录 app.use(/gocardless, goCardlessApp.handlers); // GoCardless 银行同步 app.use(/simplefin, simpleFinApp.handlers); // SimpleFIN app.use(/pluggyai, pluggai.handlers); // Pluggy.ai app.use(/akahu, akahuApp.handlers); // Akahu app.use(/enablebanking, enableBankingApp.handlers); // Enable Banking app.use(/secret, secretApp.handlers); // 密钥管理 app.use(/admin, adminApp.handlers); // 管理端 app.use(/openid, openidApp.handlers); // OpenID从路径结构可以推断sync-server 不仅承担同步职责还集成了多家银行数据源提供商的接入端点GoCardless、SimpleFIN、Pluggy、Akahu、Enable Banking这也是 Actual 自动对账/拉取交易功能的服务器侧基础。限流与安全非development环境下启用express-rate-limit每分钟窗口最多 500 次请求见 packages/sync-server/src/app.ts禁用x-powered-by头设置trust proxy为trustedProxies配置方便在反向代理Nginx/Caddy后正确识别客户端 IP统一附加Cross-Origin-Opener-Policy: same-origin、Cross-Origin-Embedder-Policy: require-corp与 CSP 响应头。运维端点GET /health返回{ status: UP }供负载均衡器或 Docker healthcheck 使用GET /metrics返回内存使用与进程运行时长GET /info返回构建包名、描述与版本号从最近的actual-app/sync-serverpackage.json 向上查找GET /mode返回当前运行模式development/test。生产/开发双模式development模式将前端请求代理到本地 Vite 开发服务器http://localhost:3001含 HMR WebSocket生产模式则直接以静态文件方式托管webRoot下的 React 构建产物并对任意未匹配路径回退到index.html即单页应用路由。HTTPS 支持当同时配置了https.key与https.cert时run()使用node:https创建 HTTPS 服务器parseHTTPSConfig支持直接传入 PEM 内容以-----BEGIN开头或证书文件路径两种写法。密码机制与首次引导第一次使用自托管实例时需要设置管理员密码这是所有后续登录的基础。密码引导/重置的完整流程在 packages/sync-server/src/scripts/reset-password.js 中运行actual-server --reset-password脚本调用needsBootstrap()判断是否已初始化未初始化 → 提示还没有设置密码现在来设置一个吧交互输入密码后调用bootstrap({ password })已初始化 → 提示已经有密码了现在来重置它输入新密码后调用changePassword(password)成功后会明确提醒所有已登录的浏览器和设备都需要使用新密码重新登录。密码通过 argon2/bcrypt 等库进行哈希存储二者均出现在 packages/sync-server/package.json 的 dependencies 中不会以明文落盘。忘记密码时这是官方提供的唯一自助恢复途径。数据目录与数据库迁移服务器运行会产生两类关键数据默认都位于dataDir下server-files/同步的账本文件数据user-files/用户文件。首次启动含升级后启动会自动执行数据库迁移。迁移逻辑位于 packages/sync-server/src/migrations.ts通过 Vite 的import.meta.glob在构建期静态收集migrations/目录下全部迁移脚本见 packages/sync-server/migrations每个迁移独立成 chunk运行时按文件名排序后逐个执行迁移状态记录在dataDir/.migrate测试模式下为.migrate-test支持up/down双向操作对应的运维命令为yarn db:migrate与yarn db:downgrade见 packages/sync-server/package.json。由于入口 packages/sync-server/app.ts 保证先迁移、后启动升级版本时无需手工干预只有显式回滚时才需要执行db:downgrade。自托管实践建议结合上述实现给出几条可直接落地的运维建议数据安全第一无论采用 npm 还是 Docker 部署务必把server-files、user-files即整个数据目录纳入定期备份同时保护好.migrate迁移状态文件公网访问务必上 HTTPS通过https.key/https.cert配置或前置反向代理终结 TLStrustedProxies默认已覆盖常见内网网段若反向代理位于其他网段需追加按需调整上传限制账本文件较大或多设备高频同步时可将ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB从默认 20 调大Docker Compose 文件中已预留注释示例健康检查接入编排使用/health端点或官方 health-check 脚本纳入监控告警开放 OpenID 时先看 enforceACTUAL_OPENID_ENFORCE对应enforceOpenId默认false决定是否强制所有用户走 OpenID开启前需确认discoveryURL或各 endpoint 均已配置openId配置完整时run()会在启动阶段调用bootstrap({ openId })预配置提供方。小结actual-app/sync-server用极简的 CLI 面四个选项封装了完整的自托管同步方案npm 全局安装后一条actual-server即可运行--config对接 convict 驱动的丰富配置体系--reset-password提供密码恢复通道Docker Compose 文件则给出生产级的一键部署参考。底层上load-config.js 定义了全部可调参数与优先级app.ts 承载了同步、银行对接、健康检查与 HTTPS 等全部路由migrations.ts 保障了版本升级的平滑性——这正是本地优先 跨设备同步这一设计在服务器端的完整实现。【免费下载链接】actualA local-first personal finance app项目地址: https://gitcode.com/GitHub_Trending/ac/actual创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表