Securo:开源、自托管、隐私优先的个人财务管理器
英文标题:🔥 securo-finance/securo
Securo 是一款采用 AGPL-3.0 许可的开源个人财务管理器,支持在用户自己的基础设施上部署,主打不向第三方交出财务数据。产品覆盖多账户、交易与预算、资产估值、报表、多币种、银行同步、OIDC、Passkey 和 TOTP 等功能,并可接入巴西、欧洲、美国及国际银行服务商。其可选 AI Agents 功能支持 OpenAI、Anthropic、Ollama 及 OpenAI 兼容模型,可通过 MCP 调用用户数据工具,并为每个 Agent 提供 RAG 知识库。对开发者而言,项目基于 FastAPI、React、PostgreSQL、Redis 和 Celery 构建,既提供 Docker Compose 部署方式,也说明了裸机或 LXC 环境的配置路径。
644.3 KB
56.1 KB
中文
网站 · 演示 · 路线图 · 文档 · Discord · 联系维护者
财务应用想要你的数据,而这个不会。
我们相信,个人财务应当真正属于个人。任何企业都不应介于你与自己的财务数据之间。Securo 是一款运行在你自有基础设施上的开源财务管理器,让你完整掌握账户、支出和财务习惯,同时不向第三方交出哪怕一个字节的数据。重新夺回控制权。
Linux 与 macOS(使用 Docker 或 Podman;如两者均不存在,将安装 Docker):
curl -fsSL https://usesecuro.com/install.sh | bash
**Windows:**安装 Docker Desktop,然后:
git clone https://github.com/securo-finance/securo.git && cd securo
docker compose up --build
打开 http://localhost:3000 并创建账户,即可完成。
- 支持多账户管理及实时余额
- 交易管理,支持搜索、筛选和 CSV 导出
- 文件导入(OFX、QIF、CAMT、CSV)
- 自动分类规则引擎
- 定期交易与预算
- 目标和储蓄目标,并提供进度跟踪
- 资产管理,支持估值跟踪和增长规则
- 报表:净资产,以及按类别显示迷你趋势图的收入与支出对比
- 通过服务提供商同步银行数据(巴西银行使用 Pluggy、约 2500 家欧洲 PSD2 银行使用 Enable Banking、美国及国际银行使用 SimpleFIN,并且可扩展)
- 多币种支持与自动外汇兑换
- 多用户支持,提供管理面板和注册控制功能
- 双因素认证(TOTP)与暴力破解防护
- 支持 Authentik、Pocket ID 和其他标准服务商的 OIDC 登录
- AI Agents(可选):可通过工具使用你的数据的自托管 LLM 对话,以及按 Agent 划分的 RAG 知识库
将任一受支持服务商的凭据添加至 .env,然后使用 docker compose up 重启。可配置一个或两个服务商——只要对应凭据存在,各服务商会自动注册。
在 pluggy.ai 注册并添加:
PLUGGY_CLIENT_ID=your-client-id
PLUGGY_CLIENT_SECRET=your-client-secret
Enable Banking —— 欧洲银行(PSD2)
在 enablebanking.com 注册,创建 Production 应用,并下载其 PEM 私钥。将 PEM 保存到 ./secrets/(已被 git 忽略),然后添加:
ENABLE_BANKING_APP_ID=your-application-id
ENABLE_BANKING_PRIVATE_KEY_FILE=/app/secrets/your-key.pem
ENABLE_BANKING_OAUTH_REDIRECT_URI=https://your-host/oauth/callback
重定向 URI 必须与 EB 应用中 Allowed Redirect URLs 的其中一项完全一致。Production EB 要求 HTTPS——本地开发时,请通过隧道(ngrok、cloudflared)暴露前端,或使用 EB sandbox。
**免费套餐——受限模式。**Enable Banking 的免费计划要求你在通过 Securo 连接前,先在 EB 门户中预先关联想要导入的账户。若跳过此步骤,连接将不会返回账户,Securo 会显示一条带有门户链接的横幅提示。
SimpleFIN —— 美国及国际银行
SimpleFIN 是一个只读开放协议。无需 API key——每个连接都会通过 SimpleFIN Bridge 提供的一次性 Setup Token 携带自身凭据。只需启用该功能:
SIMPLEFIN_ENABLED=true
SIMPLEFIN_API_URL=https://beta-bridge.simplefin.org # sandbox;真实银行请使用 bridge.simplefin.org
随后在 Securo 中依次选择:账户 → 连接银行 → SimpleFIN,并粘贴 Token。如需在不连接真实银行的情况下试用,开发者页面提供免费的演示 Token。
Securo 可以将登录委托给任何标准 OIDC 服务商,包括 Authentik 和 Pocket ID。请在你的服务商中创建 confidential/web 应用,并注册以下重定向 URI:
https://your-securo-host/api/auth/oidc/callback
然后将服务商设置添加至 .env 并重启:
OIDC_ENABLED=true
OIDC_PROVIDER_NAME=Pocket ID
OIDC_DISCOVERY_URL=https://id.example.com/.well-known/openid-configuration
OIDC_CLIENT_ID=securo
OIDC_CLIENT_SECRET=your-client-secret
# 可选;默认值为 ${FRONTEND_URL}/api/auth/oidc/callback
OIDC_REDIRECT_URI=https://your-securo-host/api/auth/oidc/callback
要在配置 OIDC 后强制仅允许 SSO 访问,请设置 LOCAL_AUTH_ENABLED=false。仅当 OIDC_ENABLED=true、OIDC_CLIENT_ID 和 OIDC_DISCOVERY_URL 均已配置时,Securo 才会在此模式下启动;否则,启动会因验证错误而失败,而非让实例陷入没有可用登录方式的状态。如果服务器报告本地认证和 OIDC 均不可用,登录页面会显示明确的配置错误。若仅可选的 OIDC 配置请求失败,客户端会在显示警告的同时保留本地控制项;后端仍是最终权威,在仅 OIDC 模式下依然会拒绝这些操作。
禁用本地认证后,Securo 将拒绝密码和 Passkey 登录、公开注册、首位管理员密码设置、管理员或工作区邀请创建的密码用户、忘记/重置密码请求、密码更新、新 Passkey 注册或验证,以及新 TOTP 设置或启用。本地凭据控制项会从登录、账户、设置、注册和管理员用户管理页面中隐藏。现有用户、密码哈希、活跃会话、Passkey 和 TOTP 配置不会被删除;现有 Passkey 和 TOTP 仍可作为清理路径被移除。OIDC 用户配置和现有账户关联仍分别由 OIDC_AUTO_REGISTER 和 OIDC_EXISTING_USER_LINK_MODE 控制。
对于全新的仅 OIDC 实例,首个账户必须通过 OIDC 配置。请保持 OIDC_AUTO_REGISTER=true,启用 OIDC_SYNC_ROLES=true,并在该身份已配置的角色声明中包含 OIDC_ADMIN_ROLES 的任一值,使首次登录成为 Securo 管理员。至少存在一个匹配账户之前,请勿禁用 OIDC 自动注册。
默认情况下,新 OIDC 用户会使用已验证的电子邮箱自动配置(OIDC_AUTO_REGISTER=true)。设置 OIDC_AUTO_REGISTER=false 后,仅允许电子邮箱与服务商声明匹配的现有 Securo 用户访问。
关联现有账户
Securo 中已存在的账户(通过密码创建)绝不会自动关联至 OIDC 身份,因此,现有用户首次进行 SSO 登录时默认会被拒绝。OIDC_EXISTING_USER_LINK_MODE 控制此行为:
OIDC_EXISTING_USER_LINK_MODE=disabled
| 值 | 行为 |
|---|---|
disabled(默认) |
永不关联。现有账户必须继续使用密码登录。 |
verified_email |
当服务商针对相同电子邮箱发送 email_verified=true 时,关联现有账户。 |
email |
仅根据匹配的电子邮箱进行关联,即使没有 email_verified。 |
使用 verified_email 可在不重建账户和数据的情况下,将现有用户迁移至 SSO。只有在你信任服务商对其声明的每个地址都拥有控制权时,才应选择 email,因为任何能够在那里设置电子邮箱的人都可能认领匹配的 Securo 账户。已关联到其他账户的 OIDC 身份在任何模式下都会被拒绝。
当 OIDC_SYNC_ROLES=true 时,Securo 还可将服务商角色/群组同步到其内置权限系统。默认声明为 groups,可与 Authentik 群组映射及 Pocket ID 角色/群组分配良好配合。
OIDC_SYNC_ROLES=true
OIDC_ROLES_CLAIM=groups
OIDC_ADMIN_ROLES=securo-admins
OIDC_WORKSPACE_ROLE_MAP={"securo-owners":"owner","securo-editors":"editor","securo-viewers":"viewer"}
OIDC_ADMIN_ROLES 会在每次 OIDC 登录时授予或撤销 Securo 管理员权限(is_superuser)。OIDC_WORKSPACE_ROLE_MAP 将服务商角色/群组映射为用户个人工作区角色(owner、editor 或 viewer);如果存在多个已映射角色,Securo 会应用权限最高的角色。保持 OIDC_SYNC_ROLES=false,即可继续在本地管理所有 Securo 角色。
可通过 Touch ID、Face ID、Windows Hello 或安全密钥登录。Passkey 默认启用,无需配置:它会遵循你访问 Securo 时使用的地址。
以下两条规则源自 WebAuthn 标准本身,任何设置都无法绕过:
- IP 地址永远无效。
http://192.168.1.10:3000无法注册 Passkey。 - 除
localhost外,纯 HTTP 永远无效。
因此,请在 http://localhost:3000 上使用 Passkey,或者将 Securo 部署在 HTTPS 反向代理后的域名上。通过域名提供服务时,请将 FRONTEND_URL 指向该域名(这也会覆盖 CORS 和 OAuth 回调):
FRONTEND_URL=https://securo.example.com
如需将 Passkey 固定到一个域名,请设置 WEBAUTHN_RP_ID(若通过多个子域名访问 Securo,请使用父域名)。否则,Securo 会遵循浏览器;来自不可用地址的请求会在 UI 中收到说明,而不是静默失败。
汇率(可选)
如需自动货币兑换,请将免费的 Open Exchange Rates key 添加至 .env:
OPENEXCHANGERATES_APP_ID=your-app-id
创建外币交易时会按需获取汇率。如果没有 key,跨币种金额将默认使用 1:1 的回退汇率,并显示视觉警告。
基于你的 Securo 数据运行的自托管 AI 助手——支持多服务商(OpenAI、Anthropic、Ollama、OpenAI 兼容服务),可通过 MCP 使用工具,提供按 Agent 划分的 RAG 知识库,以及 ⌘J 全局聊天面板。
添加至 .env:
AGENTS_ENABLED=true
COMPOSE_PROFILES=agents
然后执行 docker compose up -d。前往“设置 → AI Agents”添加服务商连接。该功能默认关闭;关闭时零成本。
COMPOSE_PROFILES=agents 仅用于告知 Docker Compose 启动额外的 mcp-server 容器,因此在裸机或 LXC 安装中,只需设置 AGENTS_ENABLED=true。内置 MCP server 是同一 virtualenv 中的普通 uvicorn 应用;请让它与 API 一同运行,并将后端指向它:
# 与 API/worker/beat 进程一同运行
uvicorn mcp_server.main:app --host 127.0.0.1 --port 8765
AGENTS_ENABLED=true
AGENTS_BUILTIN_MCP_URL=http://127.0.0.1:8765/mcp
没有该 server 时,Agents 仍可对话,但无法使用工具,也不能读取你的数据。后端日志会说明其未能连接到哪个 MCP server。
| 层级 | 技术栈 |
|---|---|
| 后端 | FastAPI、SQLAlchemy、Alembic、Celery |
| 前端 | React、TypeScript、Vite、Tailwind CSS |
| 数据库 | PostgreSQL |
| 队列 | Redis + Celery |
该代码库的部分代码在 AI 协助下构建。所有代码均经过人工审查,且不会有数据离开你的环境。
欢迎使用 AI 参与贡献。我们审查作者,而不是工具:无论是谁写出了 diff,你都要对其质量、其与 Securo 发展方向的契合度,以及合并后发生的一切负责。参见使用 AI。
# 运行后端测试(在 backend/ 目录中执行,需要 Python 3.11+;与 CI 相同)
cd backend
pip install -e ".[dev]" # 仅首次执行——安装 pytest 和开发依赖
pytest
# 重新构建
English / 原文
Website · Demo · Roadmap · Docs · Discord · Talk to the maintainer
Finance apps want your data. This one doesn't.
We believe personal finance should actually be personal. No corporation should sit between you and your financial data. Securo is an open-source finance manager that runs on your own infrastructure, giving you full visibility into your accounts, spending, and habits, without surrendering a single byte to third parties. Take back control.
Linux & macOS (uses Docker or Podman; installs Docker if neither is present):
curl -fsSL https://usesecuro.com/install.sh | bash
Windows: Install Docker Desktop, then:
git clone https://github.com/securo-finance/securo.git && cd securo
docker compose up --build
Open http://localhost:3000 and create an account. That's it.
- Multi-account management with running balances
- Transaction management with search, filters, and CSV export
- File import (OFX, QIF, CAMT, CSV)
- Auto-categorization rules engine
- Recurring transactions and budgets
- Goals and savings targets with progress tracking
- Asset management with valuation tracking and growth rules
- Reports: Net Worth and Income vs Expenses with category sparklines
- Bank sync via providers (Pluggy for Brazilian banks, Enable Banking for ~2500 European PSD2 banks, SimpleFIN for US and international banks, extensible)
- Multi-currency support with automatic FX conversion
- Multi-user support with admin panel and registration controls
- Two-factor authentication (TOTP) with brute-force protection
- OIDC login support for Authentik, Pocket ID, and other standard providers
- AI Agents (optional): self-hosted LLM chat with tool-use over your data, plus a per-agent RAG knowledge base
Add credentials for any of the supported providers to .env, then restart with docker compose up. Configure one or both — each provider auto-registers when its credentials are present.
Sign up at pluggy.ai and add:
PLUGGY_CLIENT_ID=your-client-id
PLUGGY_CLIENT_SECRET=your-client-secret
Enable Banking — European banks (PSD2)
Sign up at enablebanking.com, create a Production application, and download its PEM private key. Save the PEM to ./secrets/ (gitignored), then add:
ENABLE_BANKING_APP_ID=your-application-id
ENABLE_BANKING_PRIVATE_KEY_FILE=/app/secrets/your-key.pem
ENABLE_BANKING_OAUTH_REDIRECT_URI=https://your-host/oauth/callback
The redirect URI must match exactly one of the Allowed Redirect URLs in your EB application. Production EB requires HTTPS — for local development, expose your frontend via a tunnel (ngrok, cloudflared) or use the EB sandbox.
Free tier — restricted mode. Enable Banking's free plan requires you to pre-link the accounts you want to import inside the EB portal before connecting from Securo. If you skip that step, the connection returns no accounts and Securo will surface a banner with a link to the portal.
SimpleFIN — US and international banks
SimpleFIN is a read-only open protocol. No API key needed — each connection brings its own credentials via a single-use Setup Token from the SimpleFIN Bridge. Just enable the feature:
SIMPLEFIN_ENABLED=true
SIMPLEFIN_API_URL=https://beta-bridge.simplefin.org # sandbox; use bridge.simplefin.org for real banks
Then in Securo: Accounts → Connect Bank → SimpleFIN , and paste the token. The developer page gives out free demo tokens if you want to try it without a real bank.
Securo can delegate login to any standard OIDC provider, including Authentik and Pocket ID. Create a confidential/web application in your provider and register this redirect URI:
https://your-securo-host/api/auth/oidc/callback
Then add the provider settings to .env and restart:
OIDC_ENABLED=true
OIDC_PROVIDER_NAME=Pocket ID
OIDC_DISCOVERY_URL=https://id.example.com/.well-known/openid-configuration
OIDC_CLIENT_ID=securo
OIDC_CLIENT_SECRET=your-client-secret
# Optional; defaults to ${FRONTEND_URL}/api/auth/oidc/callback
OIDC_REDIRECT_URI=https://your-securo-host/api/auth/oidc/callback
To require SSO-only access after OIDC is configured, set LOCAL_AUTH_ENABLED=false. Securo will start in this mode only when OIDC_ENABLED=true, OIDC_CLIENT_ID, and OIDC_DISCOVERY_URL are all configured; otherwise startup fails with a validation error instead of leaving the instance with no usable login method. The login page shows an explicit configuration error if the server reports that neither local auth nor OIDC is available. If only the optional OIDC-config request fails, the client keeps local controls available with a warning; the backend remains authoritative and still rejects them in OIDC-only mode.
With local auth disabled, Securo rejects password and passkey login, public registration, first-admin password setup, admin or workspace-invite creation of password-backed users, forgot/reset-password requests, password updates, new passkey registration or verification, and new TOTP setup or enablement. Local credential controls are hidden from login, account, setup, registration, and admin user-management screens. Existing users, password hashes, active sessions, passkeys, and TOTP configuration are not deleted; existing passkeys and TOTP can still be removed as cleanup paths. OIDC user provisioning and existing-account linking remain controlled separately by OIDC_AUTO_REGISTER and OIDC_EXISTING_USER_LINK_MODE.
On a fresh OIDC-only instance, the first account must be provisioned through OIDC. Keep OIDC_AUTO_REGISTER=true, enable OIDC_SYNC_ROLES=true, and include one of the values from OIDC_ADMIN_ROLES in that identity's configured roles claim so the first login becomes a Securo administrator. Do not disable OIDC auto-registration before at least one matching account exists.
New OIDC users are auto-provisioned by default (OIDC_AUTO_REGISTER=true) using verified email addresses. Set OIDC_AUTO_REGISTER=false to allow only existing Securo users whose email matches the provider claim.
Linking existing accounts
An account that already exists in Securo (created with a password) is never linked to an OIDC identity automatically, so the first SSO login of an existing user is rejected by default. OIDC_EXISTING_USER_LINK_MODE controls that:
OIDC_EXISTING_USER_LINK_MODE=disabled
| Value | Behavior |
|---|---|
disabled (default) |
Never link. Existing accounts must keep using password login. |
verified_email |
Link the existing account when the provider sends email_verified=true for the same email. |
email |
Link on a matching email alone, even without email_verified. |
Use verified_email to move existing users to SSO without recreating their accounts and data. Only pick email if you trust your provider to own every address it asserts, since anyone able to set an email there could claim the matching Securo account. An OIDC identity already linked to another account is always rejected, in every mode.
Securo can also synchronize provider roles/groups into its built-in permissions when OIDC_SYNC_ROLES=true. The default claim is groups, which works well with Authentik group mappings and Pocket ID role/group assignments.
OIDC_SYNC_ROLES=true
OIDC_ROLES_CLAIM=groups
OIDC_ADMIN_ROLES=securo-admins
OIDC_WORKSPACE_ROLE_MAP={"securo-owners":"owner","securo-editors":"editor","securo-viewers":"viewer"}
OIDC_ADMIN_ROLES grants or revokes Securo admin (is_superuser) on each OIDC login. OIDC_WORKSPACE_ROLE_MAP maps provider roles/groups to the user's Personal workspace role (owner, editor, or viewer); if multiple mapped roles are present, Securo applies the highest permission. Leave OIDC_SYNC_ROLES=false to keep all Securo roles managed locally.
Sign in with Touch ID, Face ID, Windows Hello, or a security key. Passkeys are on by default and need no configuration: they follow whatever address you open Securo on.
Two rules come from the WebAuthn standard itself, and no setting can work around them:
- An IP address is never valid.
http://192.168.1.10:3000cannot register passkeys. - Plain HTTP is never valid, except on
localhost.
So use passkeys on http://localhost:3000, or put Securo on a domain behind an HTTPS reverse proxy. When serving from a domain, point FRONTEND_URL at it (this also covers CORS and OAuth callbacks):
FRONTEND_URL=https://securo.example.com
To pin passkeys to one domain, set WEBAUTHN_RP_ID (use the parent domain if you reach Securo on several subdomains). Otherwise Securo follows the browser, and requests from an unusable address get an explanation in the UI instead of a silent failure.
Exchange Rates (Optional)
For automatic currency conversion, add a free Open Exchange Rates key to .env:
OPENEXCHANGERATES_APP_ID=your-app-id
Rates are fetched on-demand when foreign-currency transactions are created. Without a key, cross-currency amounts default to a 1:1 fallback rate with a visual warning.
Self-hosted AI assistants over your Securo data — multi-provider (OpenAI, Anthropic, Ollama, OpenAI-compatible), tool-use via MCP, per-agent RAG knowledge base, ⌘J global chat panel.
Add to .env:
AGENTS_ENABLED=true
COMPOSE_PROFILES=agents
Then docker compose up -d. Settings → AI Agents to add a provider connection. Off by default; zero cost when off.
COMPOSE_PROFILES=agents only tells Docker Compose to start the extra mcp-server container, so on a bare-metal or LXC install set AGENTS_ENABLED=true alone. The built-in MCP server is a plain uvicorn app in the same virtualenv; run it next to the API and point the backend at it:
# alongside the API/worker/beat processes
uvicorn mcp_server.main:app --host 127.0.0.1 --port 8765
AGENTS_ENABLED=true
AGENTS_BUILTIN_MCP_URL=http://127.0.0.1:8765/mcp
Without that server the agents still chat, but they have no tools and cannot read your data. The backend log says which MCP server it failed to reach.
| Layer | Stack |
|---|---|
| Backend | FastAPI, SQLAlchemy, Alembic, Celery |
| Frontend | React, TypeScript, Vite, Tailwind CSS |
| Database | PostgreSQL |
| Queue | Redis + Celery |
Parts of this codebase were built with help of AI. All code is human-reviewed and no data leaves your environment.
Contributing with AI is welcome. We review the author, not the tool: whatever wrote the diff, you own its quality, its fit with where Securo is going, and everything that happens after it merges. See Using AI.
# Run backend tests (from backend/, needs Python 3.11+; same as CI)
cd backend
pip install -e ".[dev]" # first time only — installs pytest and dev deps
pytest
# Rebuild after dependency changes
docker compose up --build
If you've mise installed, you can install backend/frontend directly with it:
# Install the Python version specified in .python-version,
# and create a project virtual environment using that Python.
# Install all tools and dependencies (include Python with dedicated venv)
mise //...:install
# Install only backend tools/deps
mise backend:install
# Run backend tests
mise backend:test
# Install frontend dependencies
mise frontend:install
# Run frontend linting
mise frontend:lint
# Run frontend build
mise frontend:build
See CONTRIBUTING.md for guidelines.
Not sure where to start, or want to talk something through first? Book 15 minutes — no agenda needed. Something broken, an idea, or just what you think of Securo, all welcome.
This project is licensed under the GNU Affero General Public License v3.0.
This means you can freely use, modify, and distribute this software, but any modifications — including when used as a network service (SaaS) — must also be released under the AGPL-3.0.
