# Open-SEO Environment Variables: Complete Configuration Reference

> Discover all open-seo environment variables to control site URLs, database connections, Cloudflare, and authentication. Get complete configuration details and optimize your setup.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: api-reference
- Published: 2026-07-30

---

**Open-SEO utilizes over 20 environment variables to configure site URLs, database connections, Cloudflare integrations, authentication, and telemetry preferences, with critical settings defined in [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts), and [`drizzle-prod.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-prod.config.ts).**

The `every-app/open-seo` repository relies on environment variables to adapt its behavior across development, self-hosted production, and CI environments. These variables control SEO generation, database migrations, performance benchmarking, and privacy-compliant telemetry. Understanding the complete surface of available environment variables ensures secure deployments and proper feature toggling.

## Core Application Configuration

### Site URL and Server Port

In [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts) lines 6-7, the application reads `SITE_URL` as the canonical base URL for sitemap generation and meta tags, with `VITE_SITE_URL` serving as a Vite-specific override for build-time replacement. The dev server port is configured in [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts) at line 12 via the `PORT` variable, defaulting to `3000` if unset.

```typescript
// From web/src/lib/seo.ts
const siteUrl = process.env.SITE_URL ?? process.env.VITE_SITE_URL ?? "https://example.com";

```

```typescript
// From vite.config.ts
const port = Number(process.env.PORT) || 3000;

```

### Node Environment

The `NODE_ENV` variable drives runtime behavior differences between development and production. In [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts) at line 182, authentication logic branches based on this value to adjust security policies and session handling.

## Database and Cloud Infrastructure

### Cloudflare D1 Configuration

Self-hosted deployments require Cloudflare credentials for edge database access. The `CLOUDFLARE_API_TOKEN` is validated in `scripts/selfhost-deploy-preflight.mjs` at line 64, while `CLOUDFLARE_ACCOUNT_ID` is consumed in [`scripts/migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/scripts/migrate-d1-to-postgres.ts) at line 90 for account-scoped operations. The database identifier is read from `CLOUDFLARE_DATABASE_ID` in [`drizzle-prod.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-prod.config.ts) at line 10, with an optional override available via `CLOUDFLARE_D1_DATABASE_ID` at line 101 of the migration script.

### PostgreSQL Connection

For Postgres-backed installations, `POSTGRES_DATABASE_URL` provides the connection string. This is consumed in [`drizzle-pg.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-pg.config.ts) at line 13 to initialize the Drizzle ORM client.

```typescript
// From drizzle-pg.config.ts
export const pg = drizzle({
  url: process.env.POSTGRES_DATABASE_URL!,
});

```

## Authentication and API Integration

### Better-Auth Integration

The CLI authentication system depends on `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET`. As implemented in [`cli-auth.ts`](https://github.com/every-app/open-seo/blob/main/cli-auth.ts) lines 6 and 10, these configure the service endpoint and security token, with the secret falling back to a random UUID when unspecified.

```typescript
// From cli-auth.ts
const authUrl = process.env.BETTER_AUTH_URL;
const authSecret = process.env.BETTER_AUTH_SECRET || crypto.randomUUID();

```

### External Service Credentials

DataForSEO integration requires `DATAFORSEO_API_KEY`, accessed in [`scripts/dataforseo-account-usage.ts`](https://github.com/every-app/open-seo/blob/main/scripts/dataforseo-account-usage.ts) at line 22. The `ALCHEMY_PROFILE` variable (defaulting to `"default"` if not set) is read at line 65 of `scripts/selfhost-deploy-preflight.mjs` for deployment-specific configurations.

## Telemetry and Privacy Controls

Open-SEO respects user privacy through explicit opt-out mechanisms. The [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) file checks both `OPENSEO_TELEMETRY_DISABLED` (line 23) and `DO_NOT_TRACK` (line 24) to conditionally disable analytics collection.

```typescript
// From scripts/selfhost-preflight.ts
const telemetryDisabled = process.env.OPENSEO_TELEMETRY_DISABLED === "true"
  || process.env.DO_NOT_TRACK === "true";

```

## Testing and Performance Configuration

### Playwright and CI Settings

Test execution is controlled by `PLAYWRIGHT_CHANNEL` (configuring browser selection in [`playwright.config.ts`](https://github.com/every-app/open-seo/blob/main/playwright.config.ts) line 16) and the `CI` flag (used to gate CI-specific checks in [`scripts/brand-lookup-cost-profile.ts`](https://github.com/every-app/open-seo/blob/main/scripts/brand-lookup-cost-profile.ts) line 31).

### Performance Benchmarking

Domain-overview performance tests expose granular tuning via `DOMAIN_FILTER_*` variables in [`e2e/domain-overview-filters.perf.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/domain-overview-filters.perf.spec.ts):

- **`DOMAIN_FILTER_CPU_THROTTLE`** (line 20): Sets CPU throttling rate for simulation
- **`DOMAIN_FILTER_ACTION_MS`** (line 22): Defines action-to-measure timeout in milliseconds
- **`DOMAIN_FILTER_MAX_LONG_TASK_MS`** (line 23): Maximum allowed long-task duration
- **`DOMAIN_FILTER_MAX_RAF_GAP_MS`** (line 24): Maximum request-animation-frame gap tolerance
- **`DOMAIN_FILTER_MAX_INPUT_MS`** (line 25): Input latency ceiling threshold
- **`DOMAIN_FILTER_TOTAL_LONG_TASK_MS`** (line 27): Total long-task budget for the test run

## Debug and Audit Settings

The [`badseo/scripts/run-audit.ts`](https://github.com/every-app/open-seo/blob/main/badseo/scripts/run-audit.ts) file utilizes `DEBUG_DEPTH` at line 248 to enable verbose output during SEO audits. Setting this variable activates deeper inspection logs when troubleshooting crawl issues or audit failures.

## Summary

- **Open-SEO** exposes environment variables across four categories: core configuration, database connectivity, external APIs, and privacy controls.
- Critical infrastructure variables like `CLOUDFLARE_API_TOKEN` and `POSTGRES_DATABASE_URL` are validated at startup in preflight scripts located in `scripts/selfhost-deploy-preflight.mjs`.
- Telemetry collection can be disabled via `OPENSEO_TELEMETRY_DISABLED` or `DO_NOT_TRACK` flags checked in [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts).
- Performance testing exposes six tunable `DOMAIN_FILTER_*` parameters for CPU throttling and latency thresholds in [`e2e/domain-overview-filters.perf.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/domain-overview-filters.perf.spec.ts).
- The repository stores reference examples in `.env.example`, while actual consumption occurs throughout `web/src/`, `scripts/`, and root configuration files.

## Frequently Asked Questions

### What is the difference between SITE_URL and VITE_SITE_URL?

`SITE_URL` serves as the primary base URL for SEO meta tags and sitemap generation in [`web/src/lib/seo.ts`](https://github.com/every-app/open-seo/blob/main/web/src/lib/seo.ts), while `VITE_SITE_URL` acts as a framework-specific override for Vite-based builds. If both are present, the application typically prioritizes `SITE_URL` with `VITE_SITE_URL` as a fallback for development environments.

### How do I disable telemetry in Open-SEO?

Set either `OPENSEO_TELEMETRY_DISABLED=true` or `DO_NOT_TRACK=true` in your environment. The preflight script at [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) checks both variables at lines 23-24, treating either value as a valid opt-out signal that prevents analytics collection.

### Which variables are required for self-hosting?

Self-hosted deployments minimally require `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` for infrastructure provisioning, plus either `CLOUDFLARE_DATABASE_ID` (for D1) or `POSTGRES_DATABASE_URL` (for PostgreSQL) depending on your database backend. The deployment preflight script in `scripts/selfhost-deploy-preflight.mjs` validates these credentials before proceeding.

### Can I configure performance test thresholds?

Yes. The `DOMAIN_FILTER_*` family of variables allows fine-grained control over Playwright performance tests. You can adjust `DOMAIN_FILTER_CPU_THROTTLE` for CPU simulation, `DOMAIN_FILTER_MAX_LONG_TASK_MS` for task duration limits, and `DOMAIN_FILTER_TOTAL_LONG_TASK_MS` for overall budgets in [`e2e/domain-overview-filters.perf.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/domain-overview-filters.perf.spec.ts).