# How to Configure Environment Variables for Kaneo Production Deployment: Complete Variable Reference

> Configure Kaneo production deployment environment variables by creating a .env file with KANEO_CLIENT_URL, KANEO_API_URL, AUTH_SECRET, and DATABASE_URL.

- Repository: [kaneo.app/kaneo](https://github.com/usekaneo/kaneo)
- Tags: how-to-guide
- Published: 2026-08-06

---

**To configure environment variables for Kaneo production deployment, create a `.env` file at the repository root and define the required variables including `KANEO_CLIENT_URL`, `KANEO_API_URL`, `AUTH_SECRET`, and `DATABASE_URL` before starting the API and web services.**

Kaneo is an open-source project managed under the `usekaneo/kaneo` repository. When you configure environment variables for Kaneo production deployment, both the API and the web front-end read them directly from `process.env` at startup, and missing required values will cause the server to log an error and abort. This guide covers every variable referenced in the source code, grouped by purpose, with exact file paths and validation behavior, and the repository includes [`ENVIRONMENT_SETUP.md`](https://github.com/usekaneo/kaneo/blob/main/ENVIRONMENT_SETUP.md) as the canonical reference for all supported variables.

## Required Environment Variables for Kaneo Production

### Core Application URLs

You must define three URL variables so the API and web clients can communicate across origins.

- **`KANEO_CLIENT_URL`** — The public URL of the web application (for example, `https://kanéo.example.com`). The API uses this to build absolute links for emails, webhooks, and redirects. It is read in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at line 71 and [`apps/api/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/index.ts) at line 170, and referenced in plugin files such as [`apps/api/src/plugins/slack/events.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/slack/events.ts) at line 91.
- **`KANEO_API_URL`** — The base URL of the API (for example, `https://api.example.com`). This value is injected into the front-end build when `VITE_API_URL` is not set.
- **`VITE_API_URL`** — The URL that Vite injects into the web bundle via `import.meta.env.VITE_API_URL`. If omitted, the web app falls back to `KANEO_API_URL`. You can see this mapping in [`apps/web/vite.config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/web/vite.config.ts) at line 12.

### Database Connection

Kaneo expects a PostgreSQL database and reads the connection details at runtime.

- **`DATABASE_URL`** — A full PostgreSQL connection string (for example, `postgresql://user:pass@host:5432/db`). Drizzle uses this string to initialize the database in [`apps/api/src/database/prepare-database-startup.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/database/prepare-database-startup.ts) at line 23.
- **`POSTGRES_DB`**, **`POSTGRES_USER`**, **`POSTGRES_PASSWORD`** — These variables support migration scripts and test helpers. They are referenced in [`tests/api-integration/helpers/database.ts`](https://github.com/usekaneo/kaneo/blob/main/tests/api-integration/helpers/database.ts) at lines 9 through 11.

### Authentication and Security

- **`AUTH_SECRET`** — A minimum 32-character secret used for JWT signing. The API validates the length immediately on startup in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at lines 105 through 107. If the secret is too short, the process aborts with an explicit error message.

### CORS Policy

- **`CORS_ORIGINS`** — A comma-separated list of allowed origins for cross-origin API calls. If this variable is not set, the API refuses all CORS requests, as implemented in [`apps/api/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/index.ts) at line 181.

## Optional Environment Variables for Production Integrations

### Redis for Multi-Instance WebSockets

If you run multiple API instances behind a load balancer, configure Redis to broadcast real-time events across nodes.

- **`REDIS_URL`** — A simple connection string such as `redis://host:6379`. When present, the API switches to Redis broadcasting in [`apps/api/src/ws/broadcast-adapter.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/ws/broadcast-adapter.ts) at lines 5 through 7. If omitted, the server falls back to an in-memory broadcaster, which breaks real-time sync across instances.
- **`REDIS_SENTINELS`**, **`REDIS_CLUSTER_NODES`**, **`REDIS_PASSWORD`**, **`REDIS_SENTINEL_MASTER_NAME`**, **`REDIS_SENTINEL_PASSWORD`**, **`REDIS_SENTINEL_TLS`** — Advanced sentinel or cluster settings defined in [`apps/api/src/ws/redis-config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/ws/redis-config.ts).

### S3-Compatible Storage

Task image uploads require an S3-compatible object store. All variables are read in [`apps/api/src/storage/s3.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/storage/s3.ts):

- **`S3_ENDPOINT`** — The storage provider endpoint (line 12).
- **`S3_BUCKET`** — The target bucket name (line 14).
- **`S3_ACCESS_KEY_ID`** and **`S3_SECRET_ACCESS_KEY`** — Credentials for signing requests (lines 15 and 16).
- **`S3_REGION`** — The region identifier (line 17).
- **`S3_MAX_IMAGE_UPLOAD_BYTES`** — Maximum upload size, defaulting to 5 MiB (line 20).
- **`S3_FORCE_PATH_STYLE`** — Set to `true` for non-AWS providers such as MinIO (line 22).
- **`S3_KEY_PREFIX`** — Optional path prefix inside the bucket, such as `staging/` (line 23).

### OAuth and Single Sign-On

Kaneo supports several OAuth providers. Each requires a client ID and secret when enabled.

- **GitHub** — `GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET`, used in [`apps/api/src/plugins/github/webhooks/issue-opened.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/github/webhooks/issue-opened.ts) at line 141.
- **Google** — `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`, referenced in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at lines 173 through 176.
- **Discord** — `DISCORD_CLIENT_ID` and `DISCORD_CLIENT_SECRET`, read in [`apps/api/src/plugins/discord/events.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/plugins/discord/events.ts) at line 109.
- **Custom OAuth** — `CUSTOM_OAUTH_CLIENT_ID`, `CUSTOM_OAUTH_CLIENT_SECRET`, `CUSTOM_OAUTH_AUTHORIZE_URL`, `CUSTOM_OAUTH_TOKEN_URL`, and `CUSTOM_OAUTH_USER_INFO_URL`. These are parsed in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at lines 180 through 190.

### Billing, Captcha, Email, and Monitoring

- **`TURNSTILE_SECRET_KEY`** — Secret key for Cloudflare Turnstile verification, required during sign-up. It is read in [`apps/api/src/utils/verify-turnstile.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/utils/verify-turnstile.ts).
- **`STRIPE_SECRET_KEY`** and **`STRIPE_WEBHOOK_SECRET`** — Used for paid plans in [`apps/api/src/billing/stripe.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/billing/stripe.ts) and webhook signature verification in [`apps/api/src/billing/stripe-webhook.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/billing/stripe-webhook.ts).
- **`SMTP_HOST`**, **`SMTP_PORT`**, **`SMTP_USER`**, **`SMTP_PASSWORD`**, **`SMTP_FROM`** — SMTP settings for invitation and notification emails in [`apps/api/src/email/send-email.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/email/send-email.ts).
- **`NEXT_PUBLIC_SENTRY_DSN`** — Optional Sentry DSN for error reporting, injected into the web bundle in [`apps/web/vite.config.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/web/vite.config.ts) at line 30.

## How to Create and Secure the Production `.env` File

Follow these steps to prepare the environment file for `usekaneo/kaneo`:

1. Create the file at the repository root. If a `.env.sample` exists in the repo, copy it:

   ```bash
   cp .env.sample .env
   ```

2. Populate the variables using the sections above. For a minimal production deployment, set only the core URLs, `AUTH_SECRET`, `DATABASE_URL`, and any integrations you plan to use.

3. Add `.env` to `.gitignore` so secrets are never committed. The repository already excludes this file by default.

4. Restart both services after editing the file. The API and web front-end read the environment once at startup:

   ```bash
   pnpm --filter @kaneo/api start
   pnpm --filter @kaneo/web start
   ```

## Startup Validation and Common Failures

Kaneo validates several variables immediately on boot. Understanding these checks prevents silent misconfigurations.

- **`AUTH_SECRET` too short** — If `AUTH_SECRET` contains fewer than 32 characters, the API aborts with the error logged in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at lines 105 through 107.
- **Missing `KANEO_CLIENT_URL`** — Without this value, CORS handling in [`apps/api/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/index.ts) at line 181 may reject cross-origin requests, and absolute link generation fails.
- **Unreachable Redis** — An invalid `REDIS_URL` does not crash the server, but [`apps/api/src/ws/broadcast-adapter.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/ws/broadcast-adapter.ts) falls back to in-memory mode. This causes lost real-time events when running more than one API replica.
- **Incorrect S3 credentials** — Missing or wrong `S3_ENDPOINT`, `S3_ACCESS_KEY_ID`, or `S3_SECRET_ACCESS_KEY` results in failed image uploads, as enforced by the storage logic in [`apps/api/src/storage/s3.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/storage/s3.ts).

## Code Examples for Reading Environment Variables

The following patterns appear throughout the `usekaneo/kaneo` source code.

**Reading a variable in the API:**

```typescript
// apps/api/src/auth.ts
const clientUrl = process.env.KANEO_CLIENT_URL || "http://localhost:5173";
const secret = process.env.AUTH_SECRET || "";

```

**Using the variable in a front-end fetcher:**

```typescript
// apps/web/src/fetchers/project/get-project.ts
const base = import.meta.env.VITE_API_URL ?? process.env.KANEO_API_URL;

export async function getProject(id: string) {
  const res = await fetch(`${base}/api/project/${id}`);
  return res.json();
}

```

**Generating an invitation link with a safe fallback:**

```typescript
// apps/web/src/lib/invitation-link.ts
export function createInvitationLink(token: string) {
  const origin = typeof window !== "undefined"
    ? window.location.origin
    : process.env.KANEO_CLIENT_URL;

  return `${origin}/invitation/accept/${token}`;
}

```

## Summary

- Create a single `.env` file at the repository root to configure environment variables for Kaneo production deployment.
- Required variables are `KANEO_CLIENT_URL`, `KANEO_API_URL`, `AUTH_SECRET`, `DATABASE_URL`, and `CORS_ORIGINS`.
- Optional integrations include Redis for WebSocket broadcasting, S3-compatible storage, OAuth providers, Stripe, SMTP, and Sentry.
- The API validates `AUTH_SECRET` length and refuses to start if the value is too short.
- Both the API and the web front-end read `process.env` at startup, so you must restart services after any change.

## Frequently Asked Questions

### What are the minimum environment variables required to run Kaneo in production?

The minimum set is `KANEO_CLIENT_URL`, `KANEO_API_URL`, `AUTH_SECRET`, `DATABASE_URL`, and `CORS_ORIGINS`. These values are enforced or required by [`apps/api/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/index.ts) and [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) during startup, and without them the API will abort or reject cross-origin traffic.

### How does Kaneo validate `AUTH_SECRET` at startup?

The API checks the length of `AUTH_SECRET` in [`apps/api/src/auth.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/auth.ts) at lines 105 through 107. If the string is fewer than 32 characters, the process logs an error and exits immediately to prevent weak JWT signing.

### What happens if `REDIS_URL` is omitted in a production deployment?

If `REDIS_URL` is missing, [`apps/api/src/ws/broadcast-adapter.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/ws/broadcast-adapter.ts) at lines 5 through 7 falls back to an in-memory broadcaster. The application continues to run, but real-time events will not synchronize across multiple API instances.

### How do you configure S3-compatible storage for image uploads?

Define `S3_ENDPOINT`, `S3_BUCKET`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, and `S3_REGION` in your `.env` file. For non-AWS providers such as MinIO, also set `S3_FORCE_PATH_STYLE` to `true`. All of these variables are read in [`apps/api/src/storage/s3.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/storage/s3.ts).