> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mycryptoserver.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to Vercel

> Deploy My Crypto Server to Vercel in a few minutes

Vercel is the recommended way to host My Crypto Server. The app is a standard
Next.js 16 App Router project, so it deploys with zero config.

The flow is:

1. **Deploy the repo** to Vercel.
2. **Set a handful of env vars** you generate yourself (secrets + your URL).
3. **Connect two integrations** from the Vercel marketplace — a Postgres
   database (Supabase or Neon) and Inngest. These inject their own env vars
   automatically.
4. **Finish everything else in-app** under **Integrations** (Alchemy, payment
   providers, email). No more env vars needed.

***

## 1. Create your repo and deploy it

1. Generate your own copy of the source: on the private repo you were invited
   to ([github.com/mycserver/app](https://github.com/mycserver/app)), click
   **Use this template → Create a new repository**. Create it under your own
   account and keep it **private**.

   <Note>
     Use the template button — don't fork and don't push a manual copy. The
     template gives you a clean, independent repo owned entirely by you, which
     is what lets Vercel deploy it without committer-verification issues, and
     what lets [updates](/self-hosting/updates) arrive later as pull requests.
   </Note>

2. Import your new repo at [vercel.com/new](https://vercel.com/new).

3. Vercel detects everything automatically — leave the build settings exactly as
   they are and click **Deploy**.

Don't worry if the first deploy fails — it will, until the database and env
vars below are in place. You'll redeploy once at the end.

***

## 2. Set the main environment variables

In **Vercel → your project → Settings → Environment Variables**, add these.
These are the only ones you set by hand — everything else is injected by an
integration or configured in the dashboard later.

### Secrets — required

| Variable              | Purpose                                                                                            |
| --------------------- | -------------------------------------------------------------------------------------------------- |
| `MASTER_PASSPHRASE`   | Encrypts your wallet keys. **Back it up somewhere safe — losing it means losing access to funds.** |
| `BETTER_AUTH_SECRET`  | Signs auth sessions.                                                                               |
| `API_KEY_HASH_PEPPER` | Hashes public API keys.                                                                            |

#### How to generate them

Each of these needs to be a long, random, unguessable string (32+ characters).
**Generate a different value for each one** — never reuse the same secret across
variables.

If you have a terminal, run this once per variable and paste the output:

```bash theme={null}
openssl rand -base64 32
```

That prints a fresh 32-byte random string, e.g.
`nvtbziY8taKuQeDVxannyXGm4irTAtxzMj0k5p2Qw1c=`. Run it three times to get three
different values.

No terminal? Use a web generator instead — the easiest is the
**[1Password Password Generator](https://1password.com/password-generator)**:
set the length to 32+ characters, click the refresh icon for a new value, and
copy it. Generate one for each variable.

Another option is [generate-secret.vercel.app/32](https://generate-secret.vercel.app/32) — just reload the page for a fresh value each time.

<Warning>
  `MASTER_PASSPHRASE` is the key that encrypts your wallet. If you lose it you
  lose access to your funds — store a copy in a password manager before you
  deploy. Changing it later invalidates all previously encrypted keys.
</Warning>

### Your URL — required

| Variable          | Value                                                                                    |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `BETTER_AUTH_URL` | Your production URL, e.g. `https://pay.example.com` (or the `*.vercel.app` URL for now). |
| `APP_URL`         | Same value as `BETTER_AUTH_URL`.                                                         |

<Note>
  On your very first deploy you won't know the final URL yet. Deploy once with a
  placeholder, copy the URL Vercel gives you, update both vars, and redeploy.
</Note>

That's the complete list — five variables. Everything else (chains,
confirmations, session timing) has a sensible built-in default, and services
like the database, Inngest, Alchemy, and email are configured through
integrations, not env vars.

***

## 3. Connect the integrations

Both of these live in **Vercel → your project → Integrations → Browse
Marketplace**. Connecting them provisions the service and injects the env vars
automatically — you don't copy any connection strings by hand.

### Database: Supabase or Neon

Either works — both are just Postgres. There's nothing to copy by hand: add the
integration, connect it to your project, and the app auto-detects the env vars
it injects.

<Tabs>
  <Tab title="Supabase (great free tier)">
    Add the **Supabase** integration from the marketplace, create a database,
    and connect it to your project. It injects `POSTGRES_URL`,
    `POSTGRES_PRISMA_URL`, and `POSTGRES_URL_NON_POOLING`, which the app maps to
    its pooled and direct connections automatically. The free tier is generous
    enough to run a real store.
  </Tab>

  <Tab title="Neon">
    Add the **Neon** integration, create a database, and connect it to your
    project. It injects `DATABASE_URL` and `DATABASE_URL_UNPOOLED` directly.
  </Tab>
</Tabs>

Either way you never touch a connection string — the integration provides both
the pooled connection (for request handlers) and the direct one (for
migrations). See [Database Setup](/self-hosting/database) for details.

### Workflows: Inngest

Add the **Inngest** integration from the marketplace. It injects
`INNGEST_EVENT_KEY` and `INNGEST_SIGNING_KEY`. Inngest runs the durable
workflows behind payments — session lifecycle, confirmation waiting, sweeps, and
webhook delivery. Its free tier covers roughly 50k steps/month (\~4 steps per
payment).

After your first successful deploy, point Inngest at your app so it discovers
your functions: in the Inngest dashboard, sync the app URL
`https://your-app.vercel.app/api/inngest`. You should see 5 functions appear
(`sessionLifecycle`, `paymentVerify`, `webhookDeliver`, `reconcileAlchemy`,
`cleanupIdempotency`).

***

## 4. Redeploy

With the env vars and integrations in place, trigger a fresh deploy
(**Deployments → ⋯ → Redeploy**). Everything else is set up automatically —
this deploy should go green.

***

## 5. Finish setup in the dashboard

Everything else is configured inside the running app — no more env vars.

1. Visit `/setup` and create your **owner account** (email + password).
2. Complete the **onboarding wizard**: seed phrase, networks, payout addresses,
   and the **Security** step (enable email-OTP 2FA).
3. Go to **Integrations → Alchemy**, enter your API key + auth token, and enable
   it. Payment-detection webhooks are created automatically per chain the first
   time a session needs one — there's no provisioning step.
4. (Optional) Add any **payment providers** (MoonPay, Mercuryo, NOWPayments,
   CoinGate, Banxa…) under **Integrations → \<provider>**. Credentials are
   per-merchant and live in the dashboard, not in env vars.
5. (Optional) Enable email under **Integrations → Resend**: paste your
   [Resend](https://resend.com) API key and a from-address. This powers 2FA
   codes, team invites, password resets, and checkout receipts. The key is
   stored encrypted in the database — there's no email env var.

See [Authentication](/self-hosting/authentication) for 2FA, team invites, and
API keys.

***

## Troubleshooting

**First deploy fails**
Expected — the app needs a database first. Connect the Supabase or Neon
integration to your project, then redeploy.

**Deploy still fails after connecting the database**
Make sure the integration is connected to *this* project (not just installed on
your account), then redeploy so it picks up the connection.

**Inngest functions not appearing**
Open `https://your-app.vercel.app/api/inngest` in a browser. If you see a page of
data (not an error), it's working — then sync the app URL in the Inngest
dashboard.
