docs: README with full setup guide
Covers: Enable Banking signup, RSA key generation, running setup script, docker-compose wiring, OAuth redirect flow diagram, supported French banks, and troubleshooting. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fa3463a6e3
commit
2487d8a2f9
227
README.md
Normal file
227
README.md
Normal file
@ -0,0 +1,227 @@
|
||||
# actual-gocardless-proxy
|
||||
|
||||
A drop-in [GoCardless Bank Account Data API](https://developer.gocardless.com/bank-account-data/quick-start-guide/) proxy server that lets [Actual Budget](https://actualbudget.org/) sync with French (and other European) bank accounts via [Enable Banking](https://enablebanking.com/) — a **free** PSD2 aggregator.
|
||||
|
||||
**Zero modifications to actual-server.** The only change is setting one environment variable:
|
||||
|
||||
```
|
||||
GOCARDLESS_BASE_URL=http://gocardless-proxy:3456
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
Actual Budget (browser)
|
||||
│ GoCardless API calls
|
||||
▼
|
||||
actual-server
|
||||
│ GOCARDLESS_BASE_URL → http://gocardless-proxy:3456
|
||||
▼
|
||||
gocardless-proxy ◄── this repo
|
||||
│ Enable Banking PSD2 API
|
||||
▼
|
||||
Enable Banking → French banks (BNP, SG, CA, LCL, BP, …)
|
||||
```
|
||||
|
||||
The proxy translates GoCardless API shapes ↔ Enable Banking shapes on the fly and persists all state (tokens, requisitions, account mappings) in `./data/store.json` so Docker restarts don't break existing account links.
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Sign up for Enable Banking
|
||||
|
||||
Go to [enablebanking.com](https://enablebanking.com) and create a **free personal account**. Under your app settings, note your **Application ID**.
|
||||
|
||||
### 2. Generate an RSA key pair
|
||||
|
||||
Enable Banking uses RS256 JWT auth. You need to provide your **public key** in the Enable Banking dashboard and keep the **private key** on your server.
|
||||
|
||||
```bash
|
||||
# Generate a 2048-bit RSA private key in PKCS8 format
|
||||
openssl genpkey -algorithm RSA -pkcs8 -out private_key.pem -pkeyopt rsa_keygen_bits:2048
|
||||
|
||||
# Extract the public key (upload this to Enable Banking)
|
||||
openssl pkey -in private_key.pem -pubout -out public_key.pem
|
||||
```
|
||||
|
||||
Upload `public_key.pem` in the Enable Banking dashboard under your application's API settings.
|
||||
|
||||
Keep `private_key.pem` somewhere safe — you'll need it in the next step.
|
||||
|
||||
### 3. Run the setup script
|
||||
|
||||
Clone this repo and install dependencies:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/yourname/actual-gocardless-proxy
|
||||
cd actual-gocardless-proxy
|
||||
npm install
|
||||
```
|
||||
|
||||
Run the interactive setup:
|
||||
|
||||
```bash
|
||||
npm run setup
|
||||
```
|
||||
|
||||
The script will ask for:
|
||||
- Your Enable Banking **Application ID**
|
||||
- Path to your **private key PEM** file
|
||||
- The **proxy base URL** (the URL that Enable Banking will redirect to after OAuth — must be reachable from your browser; e.g. `http://localhost:3456` for local dev or `https://yourserver.example.com` for production)
|
||||
|
||||
It will generate a random `secret_id` and `secret_key` pair and print them:
|
||||
|
||||
```
|
||||
──────────────────────────────────────────────────────────
|
||||
Enter these values in Actual Budget → Settings → GoCardless:
|
||||
|
||||
Secret ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
Secret Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
And set this environment variable on actual-server:
|
||||
|
||||
GOCARDLESS_BASE_URL=http://gocardless-proxy:3456
|
||||
──────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
All credentials are stored in `./data/store.json`.
|
||||
|
||||
### 4. Add the proxy to your docker-compose.yml
|
||||
|
||||
In your existing `actual-server` `docker-compose.yml`, add the proxy service and wire it to actual-server:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
actual-server:
|
||||
image: actualbudget/actual-server:latest
|
||||
# ... your existing config ...
|
||||
environment:
|
||||
GOCARDLESS_BASE_URL: http://gocardless-proxy:3456
|
||||
# ... your other env vars ...
|
||||
depends_on:
|
||||
- gocardless-proxy
|
||||
|
||||
gocardless-proxy:
|
||||
build: /path/to/actual-gocardless-proxy
|
||||
# or: image: ghcr.io/yourname/actual-gocardless-proxy:latest
|
||||
container_name: gocardless-proxy
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /path/to/actual-gocardless-proxy/data:/app/data
|
||||
environment:
|
||||
PORT: 3456
|
||||
```
|
||||
|
||||
> **Note on PROXY_BASE_URL:** The proxy base URL is saved in `data/store.json` during setup. If you need to change it later (e.g. you added a reverse proxy), re-run `npm run setup` or edit `data/store.json` directly and update `config.proxy_base_url`.
|
||||
|
||||
### 5. Start the services
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Verify the proxy is running:
|
||||
|
||||
```bash
|
||||
curl http://localhost:3456/health
|
||||
# → {"status":"ok","configured":true}
|
||||
```
|
||||
|
||||
### 6. Configure Actual Budget
|
||||
|
||||
In Actual Budget, go to **Settings → GoCardless** and enter the `secret_id` and `secret_key` printed in step 3.
|
||||
|
||||
You can now go to **Accounts → Link account** and search for your French bank.
|
||||
|
||||
---
|
||||
|
||||
## OAuth redirect flow
|
||||
|
||||
```
|
||||
1. actual-server POST /api/v2/requisitions/ { redirect: "http://actual:5006/..." }
|
||||
↓
|
||||
2. proxy POST https://api.enablebanking.com/auth
|
||||
{ aspsp: { name, country }, redirect_url: "http://proxy/callback",
|
||||
state: <requisition_id> }
|
||||
← { url: "https://tilisy.enablebanking.com/..." }
|
||||
↓
|
||||
3. proxy returns requisition with link = EB auth URL
|
||||
↓
|
||||
4. User visits the link, authenticates at their bank
|
||||
↓
|
||||
5. Enable Banking redirects → http://proxy/callback?code=xxx&state=<req_id>
|
||||
↓
|
||||
6. proxy POST https://api.enablebanking.com/sessions { code }
|
||||
← { session_id, accounts: [uid, ...] }
|
||||
→ fetches account details, stores GC account IDs
|
||||
→ marks requisition status "LN" (linked)
|
||||
→ redirects → http://actual:5006/...?requisition_id=<req_id>
|
||||
↓
|
||||
7. actual-server GET /api/v2/requisitions/<req_id>/
|
||||
← { status: "LN", accounts: ["gc-acc-id-1", ...] }
|
||||
↓
|
||||
8. actual-server GET /api/v2/accounts/<id>/details/
|
||||
GET /api/v2/accounts/<id>/balances/
|
||||
GET /api/v2/accounts/<id>/transactions/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Supported banks
|
||||
|
||||
All French banks supported by Enable Banking, including:
|
||||
|
||||
| Bank | BIC |
|
||||
|------|-----|
|
||||
| BNP Paribas | BNPAFRPP |
|
||||
| Société Générale | SOGEFRPP |
|
||||
| Crédit Agricole | AGRIFRPP |
|
||||
| LCL | CRLYFRPP |
|
||||
| Banque Populaire | various |
|
||||
| Caisse d'Épargne | various |
|
||||
| La Banque Postale | PSSTFRPPPAR |
|
||||
| Crédit Mutuel | CMCIFRPP |
|
||||
| CIC | CMCIFRPP |
|
||||
| Boursorama | BOUSFRPPXXX |
|
||||
| Fortuneo | FTNOFRP1 |
|
||||
| Hello bank! | BNPAFRPP |
|
||||
|
||||
See [enablebanking.com/docs/markets/fr/](https://enablebanking.com/docs/markets/fr/) for the full list.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Proxy not configured" error
|
||||
Run `npm run setup` and restart the container.
|
||||
|
||||
### "Unknown institution_id" when creating a requisition
|
||||
actual-server caches institutions. Go to **Settings → GoCardless → Reset** and re-fetch banks.
|
||||
|
||||
### OAuth callback fails with "Enable Banking error"
|
||||
- Make sure `proxy_base_url` in `data/store.json` is reachable from your browser (not just from Docker).
|
||||
- Check that the redirect URL is whitelisted in your Enable Banking application settings.
|
||||
|
||||
### Transactions not appearing
|
||||
Enable Banking may return an empty `transactions` array for accounts with no activity in the requested date range. Try widening the date range.
|
||||
|
||||
### Private key errors
|
||||
Make sure the key is **PKCS8** format. To convert from traditional RSA format:
|
||||
```bash
|
||||
openssl pkcs8 -topk8 -nocrypt -in old_key.pem -out private_key.pem
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data & privacy
|
||||
|
||||
All bank credentials and tokens stay on your server inside `./data/store.json`. Nothing is sent to any third party except Enable Banking (which is the PSD2 provider) and your bank.
|
||||
|
||||
The `data/` directory is git-ignored and should not be committed.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Loading…
Reference in New Issue
Block a user