# Maybe — User Guide

Maybe is a self-hosted personal finance application — "the OS for your personal
finances." It brings every account you own (bank accounts, credit cards,
investments, crypto, loans, real estate, vehicles) into one place, tracks every
transaction, categorizes your spending, plans budgets, charts your net worth
over time, and includes an optional AI assistant that can answer questions about
your own financial data. You run it on your own machine or server with Docker, so
your data stays with you.

> [!NOTE]
> The Maybe project reached its final public release (`v0.6.0`) and is no longer
> actively maintained by the original team. The application is fully functional
> and free to self-host under the AGPLv3 license. This guide documents the app as
> it exists at that release so you can run and use it confidently.

This guide is for people who want to **use** Maybe: install it, connect or enter
accounts, and manage their money day to day. For architecture, the full
environment-variable reference, deployment, and security hardening, see the
companion **Maybe — Administrator & Developer Guide**.

---

## 1. Quick Start

Maybe is a web application you host yourself. The fastest path is Docker Compose:
one command pulls the official image and starts the web app, a background worker,
PostgreSQL, and Redis. You then open `http://localhost:3000` in a browser and
create your account.

### What Maybe does

- **One dashboard for everything** — net worth, assets vs. liabilities, and a
  cash-flow Sankey diagram across all your accounts.
- **Every account type** — checking/savings, credit cards, investments, crypto,
  loans, properties, vehicles, and custom "other" assets and liabilities.
- **Transactions** — add manually, import from CSV, or sync automatically from
  banks via Plaid. Categorize, tag, split income vs. expense, and match transfers.
- **Budgets** — set monthly budgeted spending and expected income per category.
- **Rules** — automatically categorize, tag, or rename transactions as they arrive.
- **Investments** — track holdings, record trades (buys/sells), and value assets.
- **AI Assistant** — chat with an assistant that can read your accounts and
  transactions to answer questions (optional, requires an OpenAI key).
- **Multi-currency** — over 160 currencies including major fiat, crypto, and
  precious metals, with historical exchange-rate conversion.
- **Multi-user "family"** — invite household members; data is shared at the family
  level with role-based access.

### Prerequisites

- A machine with **Docker Engine** installed and running (Linux, macOS, or Windows).

### Start the app in two commands

```bash
# Download the sample Compose file from the Maybe repository
curl -o compose.yml https://raw.githubusercontent.com/maybe-finance/maybe/main/compose.example.yml

# Pull the image and start the app
docker compose up
```

```text
[+] Running 4/4
 ✔ Container maybe-db-1      Healthy
 ✔ Container maybe-redis-1   Healthy
 ✔ Container maybe-web-1     Started
 ✔ Container maybe-worker-1  Started
```

Open `http://localhost:3000`, click **create your account**, enter your email and
a password, and you are in.

> [!TIP]
> Out of the box the sample Compose file works with zero configuration — it ships
> with a default `SECRET_KEY_BASE` and database password baked in. That is fine
> for a local trial. If you expose Maybe beyond your own machine, set your own
> secrets first — see Section 2 and the Admin Guide's Configuration Reference.

### What to try next

- Add your first account (Section 4.1).
- Import a CSV of past transactions (Section 4.7).
- Create a monthly budget (Section 4.5).
- Turn on the AI assistant (Section 4.8).

---

## 2. Installation

Maybe is distributed as a single Docker image,
`ghcr.io/maybe-finance/maybe`, published to the GitHub Container Registry. The
recommended and supported way to run it is Docker Compose.

### System requirements

| Requirement | Detail |
|---|---|
| Docker Engine | Required. Install from the [official guide](https://docs.docker.com/engine/install/). |
| PostgreSQL | Version 16 (provided automatically by the Compose file). |
| Redis | Latest (provided automatically by the Compose file). |
| Disk | A few hundred MB for the image plus your database volume. |
| Network port | `3000` on the host by default (configurable). |

> [!NOTE]
> The Compose stack runs four services: `web` (the Rails app), `worker` (the
> Sidekiq background processor), `db` (PostgreSQL), and `redis`. The worker is
> required — account syncing, imports, AI responses, and scheduled jobs all run
> there.

### Step-by-step setup

1. **Install Docker** and confirm it works:

   ```bash
   docker run hello-world
   ```

2. **Create a working directory** for the app:

   ```bash
   mkdir -p ~/docker-apps/maybe
   cd ~/docker-apps/maybe
   ```

3. **Download the sample Compose file:**

   ```bash
   curl -o compose.yml https://raw.githubusercontent.com/maybe-finance/maybe/main/compose.example.yml
   ```

4. **(Recommended for anything but a local trial) Create an `.env` file** with your
   own secrets:

   ```bash
   touch .env
   ```

   Generate a strong secret key:

   ```bash
   openssl rand -hex 64
   ```

   ```text
   3f9c1e... (128 hex characters)
   ```

   If you do not have `openssl`, this works with no external tools:

   ```bash
   head -c 64 /dev/urandom | od -An -tx1 | tr -d ' \n' && echo
   ```

   Put your values in `.env`:

   ```text
   SECRET_KEY_BASE="paste-the-generated-string-here"
   POSTGRES_PASSWORD="choose-a-database-password"
   ```

5. **Start the app:**

   ```bash
   docker compose up
   ```

6. **Open** `http://localhost:3000` and **create your account** on the login page.

7. **Run it in the background** once you are happy:

   ```bash
   # Stop the foreground process with Ctrl+C, then:
   docker compose up -d
   docker compose ls
   ```

> [!IMPORTANT]
> The very first account you register becomes a **family admin**. There is no
> separate setup wizard for the server — the first sign-up owns the instance.
> Protect those credentials and consider enabling two-factor authentication
> (Section 4.10) right away.

### Verify the install

After `docker compose up`, the database container reports healthy and the web
container serves the login screen. You can confirm the app is alive at any time:

```bash
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/up
```

```text
200
```

> [!TIP]
> The `/up` path is a built-in health check that returns `200` when the app boots
> cleanly and `500` otherwise. It is handy for uptime monitors and load balancers.

### Keeping Maybe updated

By default your instance does **not** auto-update. To pull the latest image:

```bash
cd ~/docker-apps/maybe
docker compose pull              # fetch the newest published image
docker compose build             # rebuild with updates
docker compose up --no-deps -d web worker   # restart with the new version
```

To pin to a specific channel, edit the `image:` line in `compose.yml`:

```yaml
image: ghcr.io/maybe-finance/maybe:latest   # latest commit
# or
image: ghcr.io/maybe-finance/maybe:stable   # latest tagged release
```

> [!WARNING]
> Because the project is no longer actively maintained, `latest` and `stable` may
> not change going forward. Pin to a tag you have tested rather than assuming new
> updates will arrive.

---

## 3. Configuration

Most configuration is done with environment variables at deploy time (the Admin
Guide covers every one). This section covers the settings **you** change from
inside the app, under the **Settings** menu.

### In-app settings

| Settings page | What you control |
|---|---|
| **Profile** | Your name, profile image, family members, pending invitations. |
| **Preferences** | Default time period for charts, locale, date format, theme, AI sidebar visibility. |
| **Security** | Password, two-factor authentication (MFA). |
| **Self-Hosting** | Invite-only signup, email-confirmation requirement, Synth API key, clear cached data. |
| **API Key** | Create or revoke a personal API key for the developer API. |
| **Billing** | Subscription status (disabled on self-hosted instances). |

### The Self-Hosting settings page

On a self-hosted instance, **Settings → Self-Hosting** exposes options that only
make sense when you run the server:

- **Require invite for signup** — when on, new users can only register with a valid
  invite code, so a public URL can't be used to create accounts by strangers.
- **Require email confirmation** — when on, email address changes must be confirmed
  by clicking a link (requires SMTP to be configured).
- **Synth API key** — paste a [Synth](https://synthfinance.com/) key here to enable
  historical exchange rates and security prices. You can set it here instead of via
  an environment variable.
- **Clear cache** — admins can purge cached exchange rates, security prices, and
  computed balances, then trigger a fresh sync.

> [!NOTE]
> A data provider (Synth) is only **required** if you hold investments/trades or
> use more than one currency — Maybe needs it to fetch historical security prices
> and exchange rates. A single-currency, cash-only setup works without any external
> provider.

### User-facing environment variables you might set

These are the variables most users touch; the Admin Guide lists the rest.

| Variable | Purpose | Default |
|---|---|---|
| `PORT` | Host port Puma listens on | `3000` |
| `SYNTH_API_KEY` | Exchange rates + stock prices | _(empty)_ |
| `OPENAI_ACCESS_TOKEN` | Enables the AI assistant and AI rules | _(empty)_ |
| `APP_DOMAIN` | Domain used to build links in emails | _(empty)_ |
| `SMTP_ADDRESS` / `SMTP_PORT` / `SMTP_USERNAME` / `SMTP_PASSWORD` | Outgoing email (password resets, reports) | _(empty)_ / `465` |

> [!IMPORTANT]
> Enabling `OPENAI_ACCESS_TOKEN` means AI features (chat and AI-assisted rules)
> call OpenAI and will **incur costs on your OpenAI account**. Set spending limits
> on your OpenAI account before turning it on.

See the Admin Guide for the complete configuration reference, including database,
storage (S3/Cloudflare R2), Plaid, encryption keys, and monitoring variables.

---

## 4. Core Usage

Maybe organizes your finances around a few simple concepts:

- An **Account** is one thing you own or owe (a checking account, a credit card,
  a house). Every account has a type and a running balance.
- An **Entry** is a dated event on an account. The three kinds of entry are a
  **Transaction** (money in/out), a **Trade** (buying/selling a security), and a
  **Valuation** (a stated balance on a date).
- **Categories**, **Tags**, and **Merchants** describe your transactions.
- A **Budget** sets monthly targets per category.
- A **Rule** automates how incoming transactions are categorized or tagged.
- A **Family** is your household — all data is shared among the family's users.

### 4.1 Adding accounts

From the dashboard or the **Accounts** page you can add any of these account types:

| Account type | Use it for | Tracks |
|---|---|---|
| **Depository** | Checking, savings, cash | Cash balance |
| **Credit Card** | Credit cards | Cash balance (a liability), plus APR, limit, minimum payment, annual fee |
| **Investment** | Brokerage accounts | Holdings + cash via trades |
| **Crypto** | Crypto wallets/exchanges | Holdings |
| **Loan** | Mortgages, auto/personal loans | Balance, interest rate, term, rate type |
| **Property** | Real estate | Stated value + address, year built, area |
| **Vehicle** | Cars, etc. | Stated value |
| **Other Asset** | Anything else you own | Stated value |
| **Other Liability** | Anything else you owe | Stated balance |

To add a manual account, choose the type, give it a name and currency, and set its
starting balance. For properties and vehicles you'll enter a value (and, for
properties, an address) through a short wizard.

> [!TIP]
> Accounts have three live states: **active**, **draft** (still being set up, e.g.
> a property mid-wizard), and **disabled** (hidden from totals but kept for
> history). Use **Toggle active** on an account to disable it instead of deleting,
> so your past data stays intact.

#### Connecting a bank automatically (Plaid)

If your administrator has configured Plaid (US and/or EU credentials), you can
link a real bank: choose **Connect account**, pick your institution, and complete
the secure Plaid flow. Maybe then syncs balances and transactions automatically in
the background.

> [!NOTE]
> Plaid is optional and requires Plaid API credentials set by whoever runs the
> server. Without Plaid, you add accounts and transactions manually or by CSV
> import — every feature still works.

#### Syncing

- **Sync one account:** open the account and choose **Sync**.
- **Sync everything:** use **Sync all** on the Accounts page.

Syncs run as background jobs; balances and charts refresh when they finish.

### 4.2 Recording transactions

A **Transaction** is income or an expense on an account. Create one with **New
transaction**: pick the account, date, amount, and a name. Choose whether it is an
**inflow** (income) or **outflow** (expense) — Maybe stores the sign for you. You
can also set a category, a merchant, tags, and notes.

Editing a transaction lets you change any of these fields. When you re-categorize a
transaction, Maybe may offer to create a **rule** so similar future transactions
are categorized the same way automatically (see Section 4.6).

> [!TIP]
> Use **Exclude** on a transaction to keep it out of budgets and reports (useful
> for internal transfers you track manually, or reimbursements).

#### Searching and filtering

The **Transactions** page supports rich filtering: by account, category, merchant,
tag, type (income/expense), date range, amount, and free-text search across the
name, notes, and merchant. Your last set of filters is remembered as you navigate.

### 4.3 Categories

Categories group your spending and income. A fresh family can **bootstrap** a
sensible default set with one click, including:

| Default category | Type |
|---|---|
| Income | income |
| Loan Payments, Fees | expense |
| Entertainment, Food & Drink, Shopping | expense |
| Home Improvement, Healthcare, Personal Care, Services | expense |
| Gifts & Donations, Transportation, Travel, Rent & Utilities | expense |

Each category has a color and an icon. You can create your own, nest
**subcategories** one level deep (a subcategory must share its parent's
income/expense classification), and delete categories — when you delete one you
choose a replacement category for its transactions.

> [!NOTE]
> Categories are limited to two levels (a parent and its subcategories). This keeps
> reports and the cash-flow diagram readable.

### 4.4 Tags and merchants

- **Tags** are free-form labels you attach to transactions (e.g. `vacation-2025`,
  `reimbursable`). Manage them under Settings; each has a color.
- **Merchants** ("family merchants") are the businesses you transact with. Maybe
  can auto-detect merchants on imported transactions, and you can create your own
  with a name and color.

### 4.5 Budgets

Budgets are monthly. Open **Budgets** and Maybe takes you to the current month,
creating ("bootstrapping") it on demand. For each month you set:

- **Expected income** for the month, and
- **Budgeted spending** per category.

The budget view then shows actual spending against your targets, with recent
transactions per category. Use the month picker to move between months or plan
ahead.

> [!TIP]
> You don't have to budget every category. Set targets on the few that matter; the
> rest roll up into your overall spending view.

### 4.6 Rules — automating categorization

A **Rule** watches your transactions and applies **actions** when **conditions**
match. Today rules operate on transactions.

- **Conditions** test things like the transaction's name, amount, or merchant.
  You can combine several conditions, including one level of compound (grouped)
  conditions.
- **Actions** change the transaction — for example set its category, set a tag, or
  rename it. Every rule needs at least one action.

Create a rule under **Rules → New**, define conditions and actions, then
**confirm**. Activating a rule with **Apply** runs it against your existing
matching transactions in the background and keeps applying to new ones.

> [!NOTE]
> When you manually change a transaction's category, Maybe may prompt you to turn
> that change into a category rule — a quick way to build up automation from your
> real edits. You can dismiss these prompts or disable them in preferences.

### 4.7 Importing data from CSV

Bring in history from another app or your bank's export. Go to **Imports → New**,
choose the import type, optionally attach it to an account, and upload your CSV.
The import runs as a guided flow:

1. **Upload** the file (a sample CSV is available to show the expected shape).
2. **Configure / map** your columns to Maybe's fields. Maybe may suggest a
   **template** you can apply with one click (including a dedicated Mint import path).
3. **Clean** and review the parsed rows.
4. **Confirm** the mappings, then **Publish** — the import processes in the
   background.

If something looks wrong after publishing, use **Revert** to undo the import.

> [!WARNING]
> Imports have a maximum row count. If your file is too large you'll see a message
> like "Your import exceeds the maximum row count" — split the file and import in
> batches.

### 4.8 The AI Assistant

Maybe includes an optional AI assistant you chat with in natural language. Because
it can call tools that read your own accounts and transactions, it can answer
questions like "How much did I spend on Food & Drink last month?" grounded in your
real data.

To use it:

1. Your administrator sets `OPENAI_ACCESS_TOKEN` on the server (required on
   self-hosted instances).
2. Enable AI for your user (the AI sidebar/features appear once AI is available).
3. Start a **New chat**, type a message, and the assistant streams its response.
   You can rename chats, retry the last response, and keep multiple conversations.

> [!CAUTION]
> The assistant sends prompts (which can include details about your finances) to
> OpenAI, and **usage bills your OpenAI account**. Only enable it if you're
> comfortable with both. Set OpenAI spend limits beforehand.

### 4.9 Investments, holdings, and trades

For **Investment** and **Crypto** accounts, Maybe tracks **holdings** (what you own)
derived from **trades** (your buys and sells).

- **Record a trade:** open the account and add a trade — choose a security
  (search by ticker), quantity, price, and date. A buy adds to your position; a
  sell reduces it. You can also record account fees or cash withdrawals from the
  same form.
- **Holdings** are computed from your trades and current prices; the account page
  shows current positions sorted by value.
- **Valuations** let you assert an account's value on a date directly (useful for
  assets you don't trade, like a property or a manually tracked portfolio).

> [!NOTE]
> Historical security prices and non-base-currency conversions require a data
> provider (Synth). Without one, you can still record trades and valuations, but
> historical price charts won't populate.

### 4.10 Securing your account (two-factor authentication)

Under **Settings → Security** you can enable **two-factor authentication (MFA)**
using any TOTP authenticator app (Google Authenticator, 1Password, Authy, etc.):

1. Choose **Enable MFA**. Maybe shows a QR code (issuer "Maybe Finance").
2. Scan it in your authenticator app and enter the 6-digit code to confirm.
3. Maybe displays **8 one-time backup codes** — save them somewhere safe. Each
   works once if you lose your device.

After enabling, you'll enter a code from your app at every login.

> [!WARNING]
> Store your backup codes before leaving the setup screen. If you lose your
> authenticator and have no backup codes, you can be locked out of your account.

### 4.11 Households: inviting family members

Your data lives under a **Family**. Admins can invite others to share it:

- **Hosted/SMTP setups:** **Settings → Profile → invite** sends an email invitation.
- **Self-hosted without email:** generate **invite codes** (Settings) and share them
  out of band; new users register with a code.

Roles are **member**, **admin**, and **super admin**. Admins can invite and remove
members and start data exports; a regular member uses the shared data without
managing the family.

> [!NOTE]
> You cannot remove yourself, and the last admin in a family with other users
> cannot be deactivated — this prevents a family from being left without an owner.

### 4.12 Exporting your data

Admins can produce a full export under **Settings → Profile → Export**. Maybe builds
a downloadable ZIP of your family's data in the background; when it's ready you'll
be able to download it from the same page. This is the clean way to take your data
elsewhere or keep an off-app backup.

### 4.13 The dashboard and reports

The home dashboard gives you the whole picture:

- **Net worth** and a **balance sheet** (assets vs. liabilities) across all visible
  accounts.
- A **cash-flow Sankey diagram** showing income flowing into spending categories
  and surplus, for a selectable period (default: last 30 days).
- Per-account **sparklines** and balance charts.
- A **changelog** view that pulls the latest release notes.

### 4.14 Multi-currency

Pick your family's base currency; all totals are reported in it. Maybe supports
over 160 currencies — every major fiat currency plus crypto (BTC, USDC) and
precious metals (gold, silver, platinum, palladium). Amounts in other currencies are
converted using historical exchange rates (via Synth) so past balances stay
accurate.

---

## 5. Common Tasks

Short, goal-oriented recipes. Each assumes you're signed in.

### Add your first checking account

1. Go to **Accounts → New** and choose **Depository**.
2. Name it, pick your currency, and enter the current balance.
3. Save. The account appears on your dashboard and starts contributing to net worth.

**If it fails:** make sure name, balance, and currency are all filled — all three
are required.

### Import a year of transactions from a CSV

1. **Imports → New**, choose the transaction import type and the target account.
2. Upload your CSV; download the sample first if you're unsure of the format.
3. Map your columns (or apply a suggested template), review the cleaned rows, and
   **Confirm**.
4. **Publish** and wait for the background import to finish.

**If it fails:** if you see a max-row-count error, split the CSV and import in
parts; use **Revert** to undo a bad import.

### Build a monthly food budget

1. Open **Budgets** (it lands on the current month).
2. Set **Expected income** for the month.
3. Set **Budgeted spending** on **Food & Drink** (and any other categories).
4. Track actuals vs. target as the month progresses.

### Auto-categorize a recurring charge

1. Find one example transaction and set its category.
2. When prompted, choose to **create a rule** (or go to **Rules → New**).
3. Add a condition on the merchant or name, add a **set category** action, and
   **Confirm**, then **Apply**.

### Turn on the AI assistant

1. Ask your admin to set `OPENAI_ACCESS_TOKEN` on the server (and set OpenAI spend
   limits).
2. Enable AI for your user, open **New chat**, and ask a question about your data.

### Enable two-factor authentication

1. **Settings → Security → Enable MFA**.
2. Scan the QR code in your authenticator app and confirm with the 6-digit code.
3. Save the 8 backup codes.

### Invite a partner to share finances (no email server)

1. **Settings**, generate an **invite code** (self-hosted only).
2. Share the code with them.
3. They register at your instance using the code and immediately see the shared
   family data.

### Connect a real bank (if Plaid is configured)

1. **Accounts → Connect account**.
2. Select your institution and complete the Plaid login.
3. Maybe imports balances and transactions and keeps them in sync.

### Reset just the financial data (keep your login)

Admins can clear cached market data and trigger a fresh sync from **Settings →
Self-Hosting → Clear cache**. For a deeper reset of accounts/categories/budgets,
see your admin — that is a destructive operation handled server-side.

### Export everything for backup

1. **Settings → Profile → Export** (admin only).
2. Wait for the ZIP to build, then download it.

### Update your instance to the latest image

```bash
cd ~/docker-apps/maybe
docker compose pull && docker compose build
docker compose up --no-deps -d web worker
```

---

## 6. Troubleshooting

### Error: `ActiveRecord::DatabaseConnectionError`

**Cause:** Docker initialized the PostgreSQL volume earlier with a different
database role/password than your current configuration — common after a failed
first start.

**Solution (first-time users only — this deletes the database):**

```bash
docker compose down
docker volume rm maybe_postgres-data
docker compose up
docker exec -it maybe-postgres-1 psql -U maybe -d maybe_production -c "SELECT 1;"
```

**Prevention:** decide on your `POSTGRES_PASSWORD` before the first `up`, and don't
change it after the volume is created without also resetting the volume.

> [!CAUTION]
> Removing the `maybe_postgres-data` volume permanently deletes all your Maybe
> data. Only do this on a fresh install you don't mind wiping.

### The app won't load and mentions a Redis configuration error

**Cause:** the web app can't reach Redis, which the background worker and live
updates depend on.

**Solution:** ensure the `redis` service is running (`docker compose ps`) and that
`REDIS_URL` points at it (the sample Compose file sets `redis://redis:6379/1`).
Restart with `docker compose up -d`.

**Prevention:** keep the `redis` service in your Compose file; don't remove it.

### Page loads but balances and imports never update

**Cause:** the `worker` (Sidekiq) service isn't running. Syncs, imports, AI
responses, and scheduled jobs all run there.

**Solution:** confirm the worker is up (`docker compose ps`) and restart it:
`docker compose up -d worker`.

**Prevention:** always run both `web` and `worker` — the app is incomplete without
the worker.

### Error: `Your import exceeds the maximum row count`

**Cause:** the CSV you uploaded has more rows than a single import allows.

**Solution:** split the file into smaller CSVs and import them one at a time.

**Prevention:** export in yearly or monthly chunks from your source app.

### Error: `Cannot delete a linked account`

**Cause:** the account is connected through Plaid and can't be deleted directly.

**Solution:** remove the Plaid connection for that institution (delete the linked
item from the Accounts page), or **disable** the account instead of deleting it.

**Prevention:** use **Toggle active / disable** to hide accounts you no longer
use; reserve deletion for manual accounts.

### "You cannot delete this holding"

**Cause:** the holding belongs to a Plaid-synced account and is managed by the
sync, not by you.

**Solution:** holdings on linked accounts update through Plaid; remove the trade or
the connection rather than the holding.

**Prevention:** manage positions manually only on manual investment/crypto accounts.

### AI chat says AI features are not enabled

**Cause:** either AI isn't enabled for your user, or (on self-hosted) no
`OPENAI_ACCESS_TOKEN` is set on the server.

**Solution:** ask your admin to set `OPENAI_ACCESS_TOKEN`, then enable AI for your
user.

**Prevention:** confirm both the server key and your user's AI setting before
relying on the assistant.

### Password rejected when registering

**Cause:** Maybe enforces password strength on signup.

**Solution:** use a password that is at least **8 characters** and includes an
uppercase letter, a lowercase letter, a number, and a special character.

**Prevention:** pick a strong passphrase up front; a password manager helps.

### Investment charts are empty / exchange rates missing

**Cause:** no data provider is configured, so Maybe can't fetch historical prices
or exchange rates.

**Solution:** add a **Synth API key** under **Settings → Self-Hosting** (or via
`SYNTH_API_KEY`).

**Prevention:** if you hold investments or use multiple currencies, set up Synth
when you install.

### Email features (password reset, reports) don't send

**Cause:** SMTP isn't configured.

**Solution:** set `SMTP_ADDRESS`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`,
`SMTP_TLS_ENABLED`, and `EMAIL_SENDER`. A free Resend tier works well.

**Prevention:** configure SMTP at install time if you want email confirmation,
password resets, or emailed reports.

### Diagnostic checklist

- [ ] All four containers (`web`, `worker`, `db`, `redis`) are up and healthy.
- [ ] `http://localhost:3000/up` returns `200`.
- [ ] `SECRET_KEY_BASE` and `POSTGRES_PASSWORD` are set consistently.
- [ ] The `worker` container is running (or background tasks stall).
- [ ] `SYNTH_API_KEY` is set if you use investments or multiple currencies.
- [ ] `OPENAI_ACCESS_TOKEN` is set if you want the AI assistant.

---

## 7. FAQ

**Q: Is Maybe free?**

Yes. It's open source under the AGPLv3 license and free to self-host. The original
hosted/managed service is separate; self-hosting has no subscription — billing is
disabled on self-hosted instances.

**Q: Is the project still maintained?**

The original team has stepped back; `v0.6.0` was the final public release. The code
is fully functional and you're free to run or fork it under the AGPLv3. (Note the
"Maybe" name and logo are trademarks and can't be used in forks.)

**Q: Do I have to connect my bank?**

No. Bank syncing via Plaid is optional and requires Plaid credentials. You can add
accounts and transactions manually or by CSV import and use every other feature.

**Q: Where is my data stored?**

In the PostgreSQL database that runs in your Docker stack, on your own machine or
server. Uploaded files (like exports and logos) are stored on disk by default, or
in S3/Cloudflare R2 if your admin configures it.

**Q: How do I back up my data?**

Two ways: use **Settings → Profile → Export** for a portable ZIP, and/or back up
the PostgreSQL volume at the server level (see the Admin Guide).

**Q: Can multiple people share one instance?**

Yes — invite members to your **family**. Everyone in the family shares the same
accounts and data, with member/admin/super-admin roles.

**Q: What currencies are supported?**

Over 160, including all major fiat currencies, crypto (BTC, USDC), and precious
metals. Set your base currency under preferences.

**Q: Do I need an OpenAI account?**

Only if you want the AI assistant or AI-assisted rules. Everything else works
without it. AI usage bills your OpenAI account, so set spend limits.

**Q: Why are my historical balances or stock prices blank?**

You likely don't have a data provider configured. Add a **Synth API key** to fetch
historical exchange rates and security prices.

**Q: How do I change the port?**

Set the `PORT` variable (and/or adjust the `ports:` mapping in `compose.yml`) if
something else already uses `3000`.

**Q: How do I update?**

`docker compose pull && docker compose build && docker compose up --no-deps -d web
worker`. Pin the `image:` tag if you want to control exactly which version you run.

**Q: I forgot my password — how do I reset it?**

Use the **Forgot password** link on the login page. This requires SMTP to be
configured so Maybe can email you the reset link.

**Q: Is there an API?**

Yes. Maybe has a developer API (`/api/v1`) with OAuth and personal API keys. Create
a key under **Settings → API Key**. See the Admin Guide for endpoints, scopes, and
rate limits.

**Q: Can I run this without Docker?**

The supported self-hosting path is Docker Compose. A from-source developer setup
exists for contributors (Ruby + PostgreSQL), but for using the app, Docker is the
way.

---

_Generated June 2026 from maybe-finance/maybe at 77b5469. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
