# Environment Setup

> Configure production environment variables and secrets.

*Canonical: https://makerkit.dev/docs/tanstack-drizzle/going-to-production/environment-setup*

---

Before deploying to production, you need to configure all required environment variables. This guide covers the essential variables and how to set them up for the [Drizzle](/drizzle) kit.

## How to Configure

Set production variables directly in your hosting provider's environment settings (Railway, Docker, etc.). Public values (`VITE_*`) are inlined by Vite at build time, while server secrets are read from `process.env` at runtime — set both in your provider.

Use the committed `apps/web/.env` as the reference list of public variables, and add any required secrets (database URL, auth secret, billing keys, SMTP credentials) that are not committed.

## Required Environment Variables

### Database

```bash
DATABASE_URL=postgresql://user:password@host:5432/database
```

Your PostgreSQL connection string. Get this from your database provider (Neon, Supabase, Railway, etc.).

### Site URL

```bash
VITE_SITE_URL=https://your-domain.com
```

Your production domain. Must match exactly - used for authentication callbacks, emails, and absolute URLs.

### Authentication Secret

```bash
BETTER_AUTH_SECRET=your-random-secret-string
```

A random secret string used to sign authentication tokens and cookies. Generate a secure random string (at least 32 characters). You can generate one using:

```bash
openssl rand -base64 32
```

{% alert type="warning" title="Security Critical" %}
Use a unique, randomly generated secret for production. Never reuse your development secret or share it publicly.
{% /alert %}

### Billing Provider

```bash
VITE_BILLING_PROVIDER=stripe
```

Set to `stripe` or `polar` depending on your billing provider.

**For Stripe:**
```bash
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
```

**For Polar:**
```bash
POLAR_ACCESS_TOKEN=...
```

### Storage (S3-Compatible)

```bash
STORAGE_BASE_URL=https://your-bucket-endpoint.com
STORAGE_S3_ACCESS_KEY_ID=...
STORAGE_S3_SECRET_ACCESS_KEY=...
STORAGE_S3_BUCKET=your-bucket-name
STORAGE_S3_REGION=us-east-1
```

Required for file uploads. Works with AWS S3, Cloudflare R2, Railway Storage, or any S3-compatible provider.

### Email

```bash
EMAIL_SENDER=noreply@your-domain.com
```

Plus your email provider credentials (Resend, Postmark, SendGrid, etc.).

## Optional Environment Variables

### OAuth Providers

If you enabled social login during development:

**Google:**
```bash
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
```

**GitHub:**
```bash
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
```

{% alert type="warning" title="OAuth Redirect URLs" %}
Remember to add your production domain to the OAuth provider's allowed redirect URLs.
{% /alert %}

### Feature Flags

```bash
VITE_ACCOUNT_MODE=hybrid
VITE_ENABLE_PERSONAL_ACCOUNT_BILLING=true
VITE_ALLOW_USER_TO_CREATE_ORGANIZATION=true
```

Match these to your development configuration. Team/organization behavior is controlled by `VITE_ACCOUNT_MODE`; see [Account Modes](../configuration/account-modes).

## Environment Variables Reference

| Variable | Required | Description |
|----------|----------|-------------|
| `DATABASE_URL` | Yes | PostgreSQL connection string |
| `VITE_SITE_URL` | Yes | Production domain URL |
| `BETTER_AUTH_SECRET` | Yes | Authentication token signing secret |
| `VITE_BILLING_PROVIDER` | Yes | `stripe` or `polar` |
| `STRIPE_SECRET_KEY` | If Stripe | Stripe secret key |
| `STRIPE_WEBHOOK_SECRET` | If Stripe | Stripe webhook signing secret |
| `POLAR_ACCESS_TOKEN` | If Polar | Polar API token |
| `STORAGE_BASE_URL` | Yes | S3 endpoint URL |
| `STORAGE_S3_ACCESS_KEY_ID` | Yes | S3 access key |
| `STORAGE_S3_SECRET_ACCESS_KEY` | Yes | S3 secret key |
| `STORAGE_S3_BUCKET` | Yes | S3 bucket name |
| `STORAGE_S3_REGION` | Yes | S3 region |
| `EMAIL_SENDER` | Yes | From email address |

For the complete list, see the [Environment Variables Reference](../configuration/environment-variables).

## Best Practices

1. **Never commit secrets** - Use `.env.local` for local development, never commit to git
2. **Use different values per environment** - Don't reuse development keys in production
3. **Validate before deploying** - Double-check that all required variables (see the table above) are set in your provider
4. **Rotate secrets regularly** - Especially after team member changes
5. **Use your provider's secret management** - Most hosting platforms encrypt environment variables

## Common Mistakes

- **Wrong site URL** - Must match your actual domain exactly, including `https://`
- **Missing webhook secrets** - Billing won't work without webhook configuration
- **Development keys in production** - Stripe test keys won't process real payments
- **Typos in variable names** - Double-check spelling, especially for the `VITE_` prefix
