# Key Environment Variables in Open‑SEO: A Complete Configuration Guide

> Master Open-SEO configuration with this guide to key environment variables. Learn how to set up site URLs, database connections, APIs, and more for optimal performance.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-08-16

---

**Open‑SEO uses environment variables defined in `process.env` across more than a dozen files to configure site URLs, database connections, third‑party APIs, telemetry settings, and CI/test behavior.**

The open‑source Open‑SEO repository (every-app/open-seo on GitHub) relies heavily on environment variables to remain flexible across self‑hosted, cloud, and development deployments. This guide catalogs every significant variable, where it appears in the source code, and how to set it correctly.

---

## Core Site and Application Settings

These variables control the base identity of your Open‑SEO instance.

### SITE_URL and VITE_SITE_URL

In [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), the SEO utilities resolve the canonical site address from two possible sources:

```typescript
// web/src/lib/seo.ts (lines 6‑7)
const siteUrl = process.env.SITE_URL ?? process.env.VITE_SITE_URL;

```

- **SITE_URL** – Standard Node.js environment variable used in production.
- **VITE_SITE_URL** – Vite‑prefixed variant exposed to the client bundle during development.

If neither is set, the application falls back to `http://localhost:3000`.

### PORT

The Vite development server port is configured in [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts):

```typescript
// vite.config.ts (lines 12‑13)
export default defineConfig({
  server: {
    port: parseInt(process.env.PORT || "5173"),
  },
});

```

### NODE_ENV

In [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts), the authentication logic branches based on environment:

```typescript
// src/lib/auth.ts (line 184)
if (process.env.NODE_ENV !== "production") {
  // Development‑only auth bypasses
}

```

---

## Database and Cloudflare Infrastructure

Open‑SEO supports both Cloudflare D1 and PostgreSQL backends. Migration and ORM configuration require these credentials.

### CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN, CLOUDFLARE_DATABASE_ID

The D1‑to‑Postgres migration script in [`scripts/migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/scripts/migrate-d1-to-postgres.ts) reads:

```typescript
// scripts/migrate-d1-to-postgres.ts (line 90)
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
const apiToken = process.env.CLOUDFLARE_API_TOKEN;

```

Additionally, [`drizzle-prod.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-prod.config.ts) uses:

```typescript
// drizzle-prod.config.ts
accountId: process.env.CLOUDFLARE_ACCOUNT_ID,
databaseId: process.env.CLOUDFLARE_DATABASE_ID,
apiToken: process.env.CLOUDFLARE_API_TOKEN,

```

### POSTGRES_DATABASE_URL

PostgreSQL deployments require a connection string:

```typescript
// drizzle-pg.config.ts (line 13)
export default defineConfig({
  dbCredentials: {
    url: process.env.POSTGRES_DATABASE_URL!,
  },
});

// scripts/migrate-d1-to-postgres.ts
const pgClient = new Client(process.env.POSTGRES_DATABASE_URL);

```

### CLOUDFLARE_D1_DATABASE_ID

Optional override for the source D1 database during migrations:

```typescript
// scripts/migrate-d1-to-postgres.ts
const d1DatabaseId = process.env.CLOUDFLARE_D1_DATABASE_ID ?? defaultId;

```

---

## Third‑Party API Integrations

### DATAFORSEO_API_KEY

Multiple scripts consume this key for SEO data services:

- [`scripts/dataforseo-account-usage.ts`](https://github.com/every-app/open-seo/blob/main/scripts/dataforseo-account-usage.ts) – monitors API quota
- [`scripts/brand-lookup-cost-profile.ts`](https://github.com/every-app/open-seo/blob/main/scripts/brand-lookup-cost-profile.ts) – calculates brand search costs
- [`scripts/backlinks-cost-profile.ts`](https://github.com/every-app/open-seo/blob/main/scripts/backlinks-cost-profile.ts) – estimates backlink analysis costs

### AUTUMN_SECRET_KEY

The data erasure utility in [`scripts/erase-user-data.ts`](https://github.com/every-app/open-seo/blob/main/scripts/erase-user-data.ts) uses:

```typescript
// scripts/erase-user-data.ts (line 411)
const autumnKey = process.env.AUTUMN_SECRET_KEY;
if (!autumnKey) throw new Error("AUTUMN_SECRET_KEY required for secure deletion");

```

---

## Telemetry and Privacy Controls

### OPENSEO_TELEMETRY_DISABLED and DO_NOT_TRACK

The self‑host preflight script respects user privacy preferences:

```typescript
// scripts/selfhost-preflight.ts (lines 23‑24)
const telemetryDisabled =
  process.env.OPENSEO_TELEMETRY_DISABLED === "true" ||
  process.env.DO_NOT_TRACK === "1" ||
  process.env.DO_NOT_TRACK === "true";

```

---

## CLI Authentication

### BETTER_AUTH_URL and BETTER_AUTH_SECRET

The CLI tool in [`cli-auth.ts`](https://github.com/every-app/open-seo/blob/main/cli-auth.ts) configures its auth provider:

```typescript
// cli-auth.ts (lines 7‑13)
const authUrl = process.env.BETTER_AUTH_URL ?? "http://localhost:4000";
const authSecret = process.env.BETTER_AUTH_SECRET ?? crypto.randomUUID();

```

---

## Testing and Performance Configuration

### PLAYWRIGHT_CHANNEL

End‑to‑end test browser selection:

```typescript
// playwright.config.ts (line 16)
channel: process.env.PLAYWRIGHT_CHANNEL ?? "chrome",

```

### DOMAIN_FILTER_* Performance Knobs

The domain overview filter performance spec in [`e2e/domain-overview-filters.perf.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/domain-overview-filters.perf.spec.ts) exposes fine‑grained controls:

- **DOMAIN_FILTER_CPU_THROTTLE** – CPU throttling rate for simulated devices
- **DOMAIN_FILTER_ACTION_MS** – Maximum acceptable interaction time
- **DOMAIN_FILTER_MAX_LONG_TASK_MS** – Per‑task duration threshold
- **DOMAIN_FILTER_MAX_RAF_GAP_MS** – RequestAnimationFrame gap limit
- **DOMAIN_FILTER_MAX_INPUT_MS** – Input delay ceiling
- **DOMAIN_FILTER_TOTAL_LONG_TASK_MS** – Cumulative long‑task budget

These allow CI pipelines to enforce strict performance budgets across different hardware.

---

## CI and Debugging Flags

### CI

When set to `"true"`, cost‑profile scripts ([`brand-lookup-cost-profile.ts`](https://github.com/every-app/open-seo/blob/main/brand-lookup-cost-profile.ts), [`backlinks-cost-profile.ts`](https://github.com/every-app/open-seo/blob/main/backlinks-cost-profile.ts)) enforce stricter validation and reporting formats suitable for automated pipelines.

### DEBUG_DEPTH

The BadSEO audit runner supports verbose logging:

```typescript
// badseo/scripts/run-audit.ts (line 248)
const debugDepth = parseInt(process.env.DEBUG_DEPTH || "0");
if (debugDepth > 2) console.log(extendedDiagnostics);

```

---

## Summary

- **Site identity**: `SITE_URL`, `VITE_SITE_URL`, `PORT` define how Open‑SEO presents itself and listens for traffic.
- **Infrastructure**: `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_DATABASE_ID`, and `POSTGRES_DATABASE_URL` enable database connectivity and migrations.
- **External data**: `DATAFORSEO_API_KEY` powers SEO analytics; `AUTUMN_SECRET_KEY` secures data deletion.
- **Privacy**: `OPENSEO_TELEMETRY_DISABLED` and `DO_NOT_TRACK` let operators opt out of usage reporting.
- **CLI and auth**: `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET` support command‑line authentication flows.
- **Testing**: `PLAYWRIGHT_CHANNEL` and the six `DOMAIN_FILTER_*` variables provide deterministic, measurable test environments.
- **Debugging**: `DEBUG_DEPTH` and `CI` control output verbosity and pipeline behavior.

---

## Frequently Asked Questions

### What is the minimum set of environment variables to run Open‑SEO locally?

For local development, you need `VITE_SITE_URL` (or `SITE_URL`), `PORT` if you want a custom port, and `NODE_ENV=development`. Database functionality requires either `POSTGRES_DATABASE_URL` for PostgreSQL or Cloudflare credentials for D1. See `.env.example` in the repository root for a complete template.

### How do I disable telemetry when self‑hosting Open‑SEO?

Set `OPENSEO_TELEMETRY_DISABLED=true` or `DO_NOT_TRACK=1` before running the preflight script in [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts). The script checks both variables and skips telemetry initialization if either is set.

### Can I use Open‑SEO without DataForSEO?

Yes, but brand lookup, backlink analysis, and cost profiling features require `DATAFORSEO_API_KEY`. Core site auditing and local SEO tools function without it.

### Why does the migration script need both Cloudflare and Postgres credentials?

[`scripts/migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/scripts/migrate-d1-to-postgres.ts) reads from Cloudflare D1 (source) and writes to PostgreSQL (target). It requires `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_TOKEN`, and `POSTGRES_DATABASE_URL` to establish both connections simultaneously.