Finbase — self-hosted система личных финансов на PocketBase с интерфейсом и браузерным расширением на SolidJS. Расширение забирает счета и операции из банковских кабинетов, сохраняет их в собственный backend и открывает полный финансовый обзор в отдельной вкладке.
Проект рассчитан на личную или семейную установку: счета связаны с пользователями, но авторизованные участники одной базы пока видят общие данные.
- синхронизация Сбера, Т-Банка, Яндекс Банка, Яндекс Лавки и Жизньмарта;
- счета, пользователи, операции, категории с иерархией и Lucide-иконками, теги;
- CRUD-таблицы в стиле screener с поиском, сортировкой и фильтрами, включая «Без категории» и «Без тегов»;
- автоматический баланс счёта и исключение выбранных счетов из отчётов;
- правила категоризации, поиск повторяющихся неразмеченных операций, создание правила из найденной группы и последовательный режим интерактивной разметки;
- поиск возможных переводов между счетами в окне 30 минут с подтверждением или отклонением пары;
- обзор по периодам, счетам и пользователям: баланс, доходы, расходы, категории, таблицы, Sankey и детализация по годам, месяцам или неделям;
- единый движок графиков Apache ECharts, светлая, тёмная и системная темы;
- вход через PocketBase OIDC, в том числе через Authelia;
- идемпотентный demo-сид для локальной разработки и контейнера.
Мультивалютность пока ограничена хранением кода валюты: общий итог не выполняет FX-конвертацию. Ежемесячные PDF-отчёты также ещё не реализованы.
Банковские кабинеты и магазины
│
▼
Chrome extension / SolidJS
│ типизированный FinbaseService
▼
PocketBase API + Go hooks
│
├── accounts / users / transactions
├── categories / tags / transfers
├── transaction_rules
└── daily_flows / flow_splits / category_sums / operation_groups
backend/ PocketBase-приложение и одна Go-миграция
frontend/ SolidJS UI и Manifest V3 extension
frontend/src/components/ui/ переиспользуемые компоненты
frontend/src/pages/data/ универсальный CRUD и фильтры
frontend/src/pages/statistics/ обзор, таблицы и ECharts
frontend/src/pages/automation/ правила, группы операций и переводы
frontend/src/shared/finbase/ frontend-модели PocketBase 1:1
frontend/src/shared/finbase/models.ts повторяет записи backend без DTO и
лишнего преобразования. frontend/src/pages/data/finbase-schema.ts содержит
только UI-метаданные: подпись поля, вид контрола и доступность в таблице.
Понадобятся Docker с Compose либо Go 1.26.2, а для frontend — pnpm 11 и Node.js
24. Версия pnpm зафиксирована в frontend/package.json.
cd backend
cp .env.example .env
docker compose up --build -d- API и PocketBase Admin UI:
http://127.0.0.1:8080иhttp://127.0.0.1:8080/_/; - данные:
backend/pb_data; - опубликованный образ:
ghcr.io/maintainer64/finbase_web:latest.
Создать или обновить администратора можно отдельной командой:
docker compose exec finbase_web /pb/finbase superuser upsert \
admin@example.com 'replace-with-a-long-password' \
--dir=/pb/pb_dataВ GitHub Releases публикуются
архивы backend для Windows, Linux и macOS, отдельно для amd64 и arm64.
Windows-архив содержит finbase.exe, остальные — finbase; в каждом есть
инструкция запуска. Go и Docker для запуска не нужны, SQLite и миграции уже
включены. Это backend, а не приложение с отдельным desktop-окном: интерфейс
Finbase по-прежнему открывается через расширение.
На Windows распакуйте ZIP и выполните в PowerShell:
.\finbase.exe serve --http=127.0.0.1:8080 --dir=.\pb_dataНа Linux/macOS:
./finbase serve --http=127.0.0.1:8080 --dir=./pb_dataПроверка скачанных архивов: sha256sum --check SHA256SUMS (Linux) или
Get-FileHash .\finbase-backend-<version>-windows-amd64.zip -Algorithm SHA256
(PowerShell), с сопоставлением значения в SHA256SUMS. Сохраняйте pb_data
при обновлении бинарника и делайте резервную копию перед запуском новой версии.
Backend поддерживает HTTPS напрямую, без nginx. Укажите все три переменные:
FINBASE_HTTPS_ADDR=0.0.0.0:8443
FINBASE_TLS_CERT_FILE=/certs/fullchain.pem
FINBASE_TLS_KEY_FILE=/certs/privkey.pemfullchain.pem содержит сертификат сервера и промежуточные сертификаты,
privkey.pem — соответствующий приватный ключ в PEM без пароля. Сертификат
должен соответствовать домену и быть доверенным на устройстве с браузером.
Приложение загружает файлы при старте; после обновления сертификатов backend
нужно перезапустить. Приватный ключ не добавляйте в Git.
Для Windows (PowerShell) укажите реальные пути на компьютере:
$env:FINBASE_HTTPS_ADDR = "0.0.0.0:8443"
$env:FINBASE_TLS_CERT_FILE = "C:\Finbase\certs\fullchain.pem"
$env:FINBASE_TLS_KEY_FILE = "C:\Finbase\certs\privkey.pem"
.\finbase.exe serve --dir=.\pb_dataДля Docker положите файлы в backend/certs/ (папка исключена из Git), задайте
переменные в backend/.env и используйте HTTPS overlay (Compose >= 2.24.4):
cd backend
docker compose -f docker-compose.yaml -f docker-compose.https.yaml up --build -dOverlay монтирует ./certs:/certs read-only и публикует только 8443:8443.
Каталог с сертификатами должен существовать заранее; другой каталог можно
указать через FINBASE_TLS_CERTS_DIR. Дайте процессу контейнера (UID 65532)
право чтения файлов, не делая приватный ключ общедоступным.
Обычный HTTP-порт в HTTPS-режиме не
запускается: даже имеющийся --http игнорируется. Не совмещайте этот режим
с аргументами доменов для автоматического TLS или флагом --https.
Для нативного бинарника .env сам по себе не загружается: задайте переменные
через окружение shell/службы. Без всех трёх переменных (все пустые) сохраняется
обычный HTTP/автоматический TLS PocketBase. Если указана только часть настроек
или файлы не читаются/не соответствуют друг другу, запуск сервера завершается
ошибкой вместо перехода на HTTP.
В расширении укажите https://ваш-домен:8443. Для OIDC разрешённый callback:
https://ваш-домен:8443/api/oauth2-redirect.
Однократное заполнение всех рабочих коллекций:
cd backend
docker compose run --rm finbase_web demo --dir=/pb/pb_data --days=180Или включите сид при каждом старте контейнера в backend/.env:
FINBASE_DEMO=true
FINBASE_DEMO_DAYS=180Сид создаёт дерево категорий, теги, двух пользователей, четыре счёта, правила, операции за выбранный период и связанные переводы. Он идемпотентный: повторный запуск обновляет записи по стабильным ключам и не создаёт дубли.
Локальный запуск без Docker:
cd backend
go run . serve --http=127.0.0.1:8080 --dir=./pb_data
# В другом терминале:
go run . demo --dir=./pb_data --days=180cd frontend
pnpm install --frozen-lockfile
pnpm startПосле первого открытия задайте адрес PocketBase в «Настройки → Finbase и авторизация». Кнопка Finbase в шапке открывает полноэкранное приложение в новой вкладке. Разделы «Обзор», «Данные» и «Автоматика» намеренно не выводятся в маленьком popup расширения.
Полный архив Chrome extension:
cd frontend
pnpm buildРезультат находится в frontend/build.zip.
PocketBase конфигурирует OIDC-провайдер из окружения:
FINBASE_OIDC_ISSUER=https://auth.example.com
FINBASE_OIDC_CLIENT_ID=finbase
FINBASE_OIDC_CLIENT_SECRET=replace-me
FINBASE_OIDC_DISPLAY_NAME=AutheliaВ Authelia нужен confidential client с authorization_code, scopes
openid email profile и точным callback PocketBase:
identity_providers:
oidc:
clients:
- client_id: finbase
client_name: Finbase
client_secret: '$pbkdf2-sha512$...'
authorization_policy: two_factor
redirect_uris:
- https://finbase.example.com/api/oauth2-redirect
- http://127.0.0.1:8080/api/oauth2-redirect
scopes: [openid, email, profile]
response_types: [code]
grant_types: [authorization_code]Authelia хранит хеш, а FINBASE_OIDC_CLIENT_SECRET должен содержать исходный
секрет того же клиента. Для production оставьте только точный HTTPS callback.
Frontend использует PocketBase OAuth2 с PKCE; OIDC-заголовки не формируются
вручную, поэтому кириллица в имени пользователя не попадает в HTTP headers.
Основные writable-коллекции:
| Коллекция | Назначение |
|---|---|
users |
пользователи PocketBase/OIDC |
accounts |
счета, владелец, вычисляемый баланс и даты состояния |
transactions |
операции со счётом, категорией и тегами |
categories |
дерево категорий, цвет и ключ lucide_icon |
tags |
произвольные метки операций |
transaction_rules |
JSON-условия и действия автоматической разметки |
transfers |
уникальная пара входящей и исходящей операции |
Первое подходящее активное правило категоризирует новую операцию. При сохранении
правила backend также размечает подходящую историю без категории. Ссылку на
категорию можно переносить между базами: если id из value_ref неизвестен,
категория ищется по имени.
operation_groups показывает повторяющиеся неразмеченные операции. Из группы
можно создать готовое правило. Автодетектор переводов сопоставляет только
неразмеченные равные по модулю in/out в разных счетах одной валюты. Только однозначная пара в окне
FINBASE_TRANSFER_WINDOW_MINUTES получает pending; затем её можно принять как
transfer или отклонить.
accounts.balance пересчитывается backend после создания, изменения и удаления
операции. accounts.owner для синхронизированного счёта берётся из текущего JWT.
disabled_at означает отключённый источник, но сохраняет историю в аналитике.
Только excluded_report_at убирает счёт из баланса, категорий, потоков,
группировки и поиска переводов; в разделе «Данные» счёт остаётся видимым.
Календарный день отчётов рассчитывается с FINBASE_TIMEZONE_OFFSET (например,
+05:00 для Екатеринбурга), поэтому ночные операции первого числа не переходят
в предыдущий UTC-месяц.
Операции можно загрузить в «Данные → Операции → Импорт CSV». Обязательны дата,
сумма и полное наименование существующего счёта. Категория сопоставляется по
названию и может быть пустой; теги также необязательны и перечисляются через
запятую. Поддерживаются CSV с ; и , (в последнем случае список тегов нужно
взять в кавычки). Перед записью показываются предпросмотр и ошибки по строкам.
Готовый шаблон: examples/finbase-transactions-import.csv.
cd frontend
pnpm lint
pnpm exec tsc --noEmit
pnpm test
pnpm build
cd ../backend
test -z "$(gofmt -l .)"
go vet ./...
go test ./...
go build ./...Интеграционные тесты запускаются против живого PocketBase. Переменные и ручной
сценарий описаны в frontend/test/README.md.
При изменении модели:
- Обновите единственную миграцию в
backend/migrations. - С теми же именами обновите
frontend/src/shared/finbase/models.ts. - Для редактируемого поля добавьте UI-метаданные в
finbase-schema.ts. - Запустите frontend type-check/build и Go tests.
| Workflow | Когда запускается | Результат |
|---|---|---|
integration.yml |
push/PR в main или master, вручную |
Go format/vet/test/build, demo smoke, frontend lint/type-check/test/build и интеграция с PocketBase |
docker-backend.yml |
изменения backend, version tag, вручную | multi-arch linux/amd64 + linux/arm64 image в GHCR; PR только собирается |
release.yml |
tag v* или вручную для существующего тега |
проверенный ZIP расширения, 6 архивов backend (Windows/Linux/macOS × amd64/arm64), SHA256SUMS и GitHub Release |
Workflow используют совместимые stable majors: actions/checkout@v4,
actions/setup-go@v5, pnpm/action-setup@v4, actions/setup-node@v4,
actions/upload-artifact@v4, Docker Setup/Login actions @v4,
docker/metadata-action@v6 и docker/build-push-action@v7.
Обычный релиз не изменяет репозиторий сам. Сначала обновите версию
frontend/package.json, затем создайте совпадающий тег:
git tag -a v1.2.0 -m 'Finbase v1.2.0'
git push origin v1.2.0release.yml завершится ошибкой, если тег и версия пакета различаются. Перед
публикацией запускаются frontend lint/type-check/test/build и Go format/vet/test.
Бинарники кросс-компилируются обычным Go на Ubuntu с CGO_ENABLED=0; отдельные
Windows/macOS runners для сборки не требуются. Архивы и контрольные суммы
прикрепляются к версии, а не публикуются на обычных push/PR. Ручной запуск также
требует существующий версионный тег; теги с суффиксом публикуются как prerelease.
Version tag одновременно публикует контейнер с semver-тегами и latest.
Для локальной проверки сборки backend:
bash scripts/build-backend-release.sh v1.4.3 ./release-assets windows/amd64Без последнего аргумента скрипт собирает все шесть платформ. Скрипт не создаёт тег и не публикует релиз.