Upgrading¶
Use this page as an upgrade runbook. The safe path is:
- Back up
/data. - Read the release notes for the version you are installing.
- Pull or change the image tag.
- Start the container and let migrations run.
- Verify login, Tracker, Admin status, backups, and bank sync.
- Keep the previous image tag and backup until the upgrade is confirmed.
The v0.36 → v0.37 notes are included below because that upgrade changes sessions, security settings, SimpleFIN matching, and React runtime behavior.
Before you upgrade¶
Do these before touching the running container:
- Open Admin → Backups and create a manual backup.
- Confirm the backup file appears in
/data/backups. - If this is production, copy the newest backup somewhere outside the app host.
- Confirm the host mount that contains
/data/db/bills.dbis persistent. - Save the current image tag from
docker ps. - Review Current Release and any version notes between your current version and the target version.
Useful checks:
docker ps --filter name=bill-tracker
docker inspect bill-tracker-main --format '{{.Config.Image}}'
ls -lh /portainer/hosting/bill-tracker/data/db/bills.db
ls -lh /portainer/hosting/bill-tracker/data/backups
Upgrade a Docker install¶
If your Compose file tracks a tag such as latest, pull and restart:
If your Compose file pins a version, edit the image tag first:
Then start the new container:
The Docker entrypoint runs migrations before the app starts. Leave
RUN_DB_MIGRATIONS enabled for normal upgrades.
Upgrade a source install¶
For a direct source deployment:
Restart your process manager after rebuilding. Migrations run when the server
opens the database, so a manual node scripts/migrate-db.js is usually not
required after a clean checkout.
Verify the upgrade¶
After restart:
- Open the app and log in.
- Open Admin → Status and check for database, migration, backup, and worker errors.
- Open Tracker as a regular user and confirm bills render.
- Open Bills and confirm a bill can be viewed/edited.
- If SimpleFIN is enabled, run or wait for a sync and confirm transactions appear.
- Run a manual backup after the upgrade.
- Keep the pre-upgrade backup until you are comfortable with the new version.
Rollback plan¶
The preferred rollback path is a known-good backup plus the previous image tag.
- Stop the container.
- Restore the pre-upgrade
/databackup or use Admin → Backups if the app is still reachable. - Change the Compose image tag back to the previous version.
- Start the container.
- Verify login and Admin → Status.
Migrations are versioned and recorded in schema_migrations. Some migrations
have explicit rollback definitions in the Admin panel, but a full data backup
is the recovery path to trust.
v0.36 → v0.37 Migration Notes¶
The following are operator-relevant changes that may affect deployed installations:
One-time re-login required
v0.37 hashes session tokens at rest (see Security below). Migration v0.94
deletes all existing plaintext sessions from the sessions table on first
startup after this version. Every user — including the bootstrap admin —
must log in again once.
Database migrations applied¶
| Migration | Adds | Notes |
|---|---|---|
| v0.92 | users.webauthn_enabled, users.webauthn_user_id, webauthn_credentials, webauthn_challenges |
WebAuthn / FIDO2 hardware security key support. Optional per user. |
| v0.93 | bills.interest_accrued_month, payments.interest_delta, rewritten transactions.provider_transaction_id |
Interest now charged once per calendar month per debt bill. SimpleFIN transaction dedupe is now stable across disconnect/reconnect. Existing keys are rewritten; duplicates are deduped in-place. |
| v0.94 | sessions.id switched to SHA-256(token), geolocation_enabled setting seeded false |
Session tokens hashed at rest; existing plaintext sessions are deleted. Geolocation becomes opt-in (off by default). |
| v0.95 | subscription_catalog.subcategory, subscription_catalog.starting_monthly_usd, subscription_catalog.starting_annual_usd, subscription_catalog.price_notes, subscription_catalog_descriptors |
1,501 rows (1,069 bank descriptors + 432 slang terms) seeded into descriptors. lookupCatalog now checks bank descriptors first. |
| v0.96 | bills.catalog_id (FK → subscription_catalog.id), user_catalog_descriptors |
Catalog id backfilled for existing subscription bills via name matching. Per-user custom bank descriptors enabled. |
| v0.97 | subscription_recommendation_feedback |
Captures accepts, declines, existing-bill links, and catalog relinks/unlinks as future learning signals. |
| v0.99 | bills.autopay_verified_at, bills.inactive_reason, bills.inactivated_at, payments.autopay_failure |
Autopay trust indicator, cancellation reasons, retroactive autopay-failure flagging. |
Security¶
- Session token hashing (
sessions.id→SHA-256(token)) — see warning above. - IP geolocation is now a per-user opt-in via Profile → Privacy
(
geolocation_enabled, defaultfalse). No outboundip-api.comcalls are made for a user unless that user's toggle is on. TOKEN_ENCRYPTION_KEYis honoured again. If the env var is set, all DB-key-encrypted secrets (SMTP password, OIDC client secret, SimpleFIN tokens, TOTP secrets, push notification tokens, login history IP/UA/location columns) are transparently re-encrypted with the env key in a single transaction on first startup. Migration is idempotent: already-e2:values are skipped. The Admin → Bank Sync card now shows which key source is active.- Rate limiting on sync/backfill endpoints (
POST /:id/sync,POST /sync-all,POST /:id/backfill): 10 requests per 15 minutes per authenticated user. GET routes on the same router are unaffected.
Configuration changes¶
- New env var:
WEBAUTHN_RP_ID(defaultlocalhost) andWEBAUTHN_ORIGIN(defaultlocalhost) for WebAuthn / FIDO2 hardware key 2FA. Set these to your production domain in HTTPS deployments. CSRF_HTTP_ONLYnow defaults totrue(wasfalsein v0.34 and earlier). The SPA fetches the token fromGET /api/auth/csrf-tokenand stores it in-memory; the server-side double-submit validation (header == cookie) is unchanged. If you pinnedCSRF_HTTP_ONLY=falsein your.env, leave it — the explicit override is still respected. Update Security Settings and Reverse Proxy and HTTPS to reflect the new default.
Behavioural changes¶
- SimpleFIN lookback window: The Data page and admin Bank Sync card now
show the actual backend values: a 44-day initial seed/backfill window
and a 45-day hard limit (SimpleFIN Bridge's own cap). The previous
inconsistent
90/89/6/60UI numbers are gone. - Manual and auto-sync now produce identical match results:
bankSyncService.runSynccallsautoMatchForUserdirectly. The redundant call inbankSyncWorkerwas removed. - Subscription recommendations are now bank-backed known services only:
Unknown recurring merchant patterns no longer mix into primary
recommendations; high-confidence (
90%+) bank transaction matches resolve to a known catalog entry. Recommendation confidence now separates identity, amount, and cadence evidence. - Subscription page actions simplified: Recommendation cards now show one
clear primary action (
Track SubscriptionorLink Existing Bill), a Details icon, and a compact More menu for secondary actions. - Subscription cadence sort: Tracked Subscriptions panel has a Custom/Cadence segmented control. Cadence groups by Weekly, Biweekly, Monthly, Quarterly, Yearly, and Other. Reordering is disabled while Cadence sort is active.
- Manual sync and auto-sync: 30 s timeout (
AbortSignal.timeout(30000)) on bothclaimSetupTokenandfetchAccountsAndTransactions. Network errors and 5xx responses retry up to 3 times with 1 s / 2 s backoff; 4xx fail immediately.
React 19¶
The frontend was upgraded from React 18.3.1 to React 19. All 15
shadcn/ui primitive files had React.forwardRef(...) replaced with plain
function components accepting ref as a named prop. BillModal was
refactored to useActionState with a form action prop. Custom
useOptimistic polyfill was removed in favour of the native React 19 hook.
If you maintain a fork or downstream extension, audit any
React.forwardRef usage you re-applied to primitives.
What to read next¶
Each section above links to the user guide or admin page that documents the change. The most important starting points are:
- Plan a Month in the Tracker — the sparkline, Changed badge, autopay trust, sortable columns, and bank-payment override all show up there.
- Tracker Features — keyboard navigation, animations, and the overdue command center.
- Browse the Service Catalog — the new matching workspace and custom bank descriptors.
- Subscribe to the Calendar Feed — the Apple / Google / Outlook subscription flow.
- Profile and Login Privacy — per-user login geolocation, login history, and WebAuthn.
- Tune Security Settings — encryption key separation and deployment security knobs.
- Back Up and Restore — restore planning and backup handling.
See also¶
Next steps¶
- Roll back an upgrade with Back Up and Restore.
- Review the breaking changes in the Current Release.
- See the deploy-side configuration in Docker Compose.