# Environment variables

> Complete reference of Shelve environment variables

This page documents all environment variables available in Shelve, their usage and configuration.

## Required variables

These environment variables are **mandatory** for Shelve to function:

### `DATABASE_URL`

- **Type**: String (PostgreSQL URL)
- **Required**: ✅ Yes
- **Description**: Connection URL to your PostgreSQL database
- **Format**: `postgresql://username:password@host:port/database`
- **Example**: `postgresql://user:pass@db.example.com:5432/shelve`

<callout type="info">

**Recommendation**: Use [Neon](https://neon.tech) with [Vercel integration](https://vercel.com/integrations/neon) for simplified configuration.

</callout>

### `NUXT_SESSION_PASSWORD`

- **Type**: String
- **Required**: ✅ Yes
- **Constraint**: Minimum 32 characters
- **Description**: Secret key to sign and encrypt user sessions
- **Generation**: `openssl rand -base64 48`

### `NUXT_PRIVATE_ENCRYPTION_KEY`

- **Type**: String
- **Required**: ✅ Yes
- **Constraint**: Minimum 32 characters
- **Description**: Key Encryption Key (KEK). Used to seal the per-project Data Encryption Keys (DEKs) that actually protect variable values. See [Encryption](/docs/core-features/encryption) for the full model.
- **Generation**: `openssl rand -base64 48`

<callout type="warning">

**Important**: Never modify these keys after first deployment, it would make existing data inaccessible. A safe KEK rotation flow (re-sealing all DEKs) is on the roadmap.

</callout>

## Authentication configuration

Shelve now supports multiple authentication methods. **You need to configure at least one method** for users to be able to create accounts and log in:

### Option 1: Email authentication only (Recommended)

- Configure `NUXT_PRIVATE_RESEND_API_KEY` and `NUXT_PRIVATE_SENDER_EMAIL`
- Users can sign up and log in using their email with OTP codes
- No OAuth setup required

### Option 2: OAuth only

- Configure at least one OAuth provider (GitHub or Google)
- Users authenticate via OAuth providers
- No email service required

### Option 3: Both methods (Maximum flexibility)

- Configure both email service and OAuth providers
- Users can choose their preferred authentication method
- Recommended for production environments

## Authentication variables

Shelve supports multiple authentication methods. You need **at least one authentication method** configured:

### Email authentication (OTP)

For email-based authentication using one-time passwords (OTP), you need to configure email service variables below.

### OAuth authentication (Optional)

OAuth providers offer an alternative authentication method alongside email authentication.

### GitHub OAuth

To enable GitHub authentication, configure these two variables together:

#### `NUXT_OAUTH_GITHUB_CLIENT_ID`

- **Type**: String
- **Required**: 🔶 Optional (must be paired with CLIENT_SECRET)
- **Description**: Client ID of your GitHub OAuth App
- **How to get**: [GitHub Developer Settings](https://github.com/settings/developers)

#### `NUXT_OAUTH_GITHUB_CLIENT_SECRET`

- **Type**: String
- **Required**: 🔶 Optional (must be paired with CLIENT_ID)
- **Description**: Client Secret of your GitHub OAuth App
- **How to get**: [GitHub Developer Settings](https://github.com/settings/developers)

### Google OAuth

To enable Google authentication, configure these two variables together:

#### `NUXT_OAUTH_GOOGLE_CLIENT_ID`

- **Type**: String
- **Required**: 🔶 Optional (must be paired with CLIENT_SECRET)
- **Description**: Client ID of your Google OAuth App
- **How to get**: [Google Cloud Console](https://console.cloud.google.com/)

#### `NUXT_OAUTH_GOOGLE_CLIENT_SECRET`

- **Type**: String
- **Required**: 🔶 Optional (must be paired with CLIENT_ID)
- **Description**: Client Secret of your Google OAuth App
- **How to get**: [Google Cloud Console](https://console.cloud.google.com/)

## GitHub integration variables

### `NUXT_PRIVATE_GITHUB_PRIVATE_KEY`

- **Type**: String (Base64)
- **Required**: 🔶 Optional
- **Description**: Private key of your GitHub App for advanced integration
- **Usage**: Automatic secrets synchronization with GitHub
- **Format**: PKCS#8 encoded in base64

<callout type="info">

**Required setup**: This variable requires a GitHub App configured with comprehensive permissions including Secrets, Variables, and more. See the [Vercel documentation](/docs/self-hosting/vercel#advanced-github-integration) for the complete permissions list.

</callout>

#### How to get this key

1. Create a GitHub App in your organization
2. Download the private key (.pem format)
3. Convert it to PKCS#8 format and encode in base64:

```bash
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private-key.pem | base64 -w 0
```

## Email service variables

### `NUXT_PRIVATE_RESEND_API_KEY`

- **Type**: String
- **Required**: ⚠️ Required for email authentication (OTP)
- **Format**: Must start with `re_`
- **Description**: Resend API key for sending emails including OTP codes
- **Usage**: OTP authentication, welcome emails, notifications
- **How to get**: [Resend Dashboard](https://resend.com/dashboard)

<callout type="warning">

**Important**: This variable is now required if you want to use email authentication (OTP). Without it, users can only authenticate via OAuth providers.

</callout>

<callout type="info">

**Recommendation**: Use [Resend](https://resend.com) with [Vercel integration](https://vercel.com/integrations/resend) for automated configuration.

</callout>

### `NUXT_PRIVATE_SENDER_EMAIL`

- **Type**: String (Email)
- **Required**: ⚠️ Required for email authentication (required if RESEND_API_KEY is set)
- **Description**: Sender email address for OTP codes and notifications
- **Format**: `noreply@yourdomain.com`
- **Constraint**: Must be a valid email verified in Resend

## Administration variables

### `NUXT_PRIVATE_ADMIN_EMAILS`

- **Type**: String (comma-separated list)
- **Required**: 🔶 Optional
- **Description**: List of emails with access to admin features
- **Format**: `admin@app.com,admin2@app.com`
- **Usage**: Access to statistics, user management

### `NUXT_PRIVATE_ALLOWED_ORIGINS`

- **Type**: String (comma-separated list of URLs)
- **Required**: 🔶 Optional
- **Description**: Allowed origins for CORS requests
- **Format**: `https://app.com,https://www.app.com`
- **Usage**: Security, CSRF attack prevention

## Automatic validation

Shelve uses an automatic environment variables validation system:

- **Startup validation**: The application checks all required variables
- **Format validation**: URLs, emails, minimum lengths are verified
- **Consistency validation**: OAuth pairs are validated together
- **Explicit error messages**: In case of error, logs indicate exactly what's wrong

## Configuration by environment

### Local development

Create a `.env` file at the root of your project:

```bash
# Copy from .env.example
DATABASE_URL=postgresql://localhost:5432/shelve_dev
NUXT_SESSION_PASSWORD=your-dev-session-password-32-chars-min
NUXT_PRIVATE_ENCRYPTION_KEY=your-dev-encryption-key-32-chars-min
```

### Production on Vercel

Configure all variables in your Vercel project settings:

1. Vercel Project > Settings > Environment Variables
2. Add each variable with its value
3. Select appropriate environments (Production, Preview, Development)

## Troubleshooting

### Common errors

**"Session password must be at least 32 characters long"**

- Generate a longer key: `openssl rand -base64 48`

**"Must be a valid PostgreSQL URL"**

- Check the format: `postgresql://user:pass@host:port/db`
- Test the connection to your database

**"GitHub OAuth validation failed"**

- Make sure you have defined CLIENT_ID AND CLIENT_SECRET together
- Verify that the values are correct

**"Resend API key must start with 're_'"**

- Use the Resend API key, not a test key
- Verify that you copied the complete key

### Missing environment variables

Vercel deployment logs will show:

```text
🔐 Auth configuration validated:
  GitHub OAuth: ✅/❌
  Google OAuth: ✅/❌  
  Email Service: ✅/❌
```

This allows you to quickly check which integrations are active.
