Open-SEO Environment Variables: Complete Configuration Guide for Every Deployment Mode

Open-SEO requires DATAFORSEO_API_KEY as the sole mandatory variable for core functionality, with additional environment variables needed only for specific authentication modes, cloud deployments, or optional third-party integrations like Google Search Console and PostHog.

The every-app/open-seo repository uses a comprehensive environment variable system to configure authentication strategies, API credentials, and deployment targets. All supported variables are documented in the .env.example file at the repository root, while the application accesses them through a centralized runtime helper in src/server/lib/runtime-env.ts.

Core Required Variables

At minimum, Open-SEO needs access to the DataforSEO API to fetch ranking and backlink data.

Authentication Configuration

Open-SEO supports multiple authentication strategies controlled by the AUTH_MODE variable. The codebase reads these values in src/lib/auth.ts and cli-auth.ts.

Cloudflare Access Mode

When AUTH_MODE=cloudflare_access, the application expects Cloudflare zero-trust headers for user validation:

  • TEAM_DOMAIN – Your Cloudflare Access team domain.
  • POLICY_AUD – The Cloudflare Access policy audience identifier.

Both variables are validated at runtime in src/lib/auth.ts.

Hosted Mode

When AUTH_MODE=hosted, Open-SEO uses Better Auth for credential management:

  • BETTER_AUTH_SECRET – Random hex string for token encryption (generate with openssl rand -hex 32).
  • BETTER_AUTH_URL – The canonical URL where your auth server runs (e.g., http://localhost:3001 for local development).

This mode also enables Google Search Console integration when OAuth credentials are provided.

Optional Third-Party Integrations

The application conditionally enables features based on the presence of specific variables.

Google Search Console

Required when enabling Google OAuth for search analytics:

  • GOOGLE_CLIENT_ID – OAuth 2.0 client ID from Google Cloud Console.
  • GOOGLE_CLIENT_SECRET – Corresponding client secret.

These credentials are documented in docs/SELF_HOSTING_GOOGLE_SEARCH_CONSOLE.md and consumed during the OAuth flow initialization.

Analytics and Monitoring

  • POSTHOG_PUBLIC_KEY and POSTHOG_HOST – Enables PostHog product analytics when both are present, consumed in src/lib/analytics.ts.
  • LOOPS_API_KEY, LOOPS_TRANSACTIONAL_VERIFY_EMAIL_ID, and LOOPS_TRANSACTIONAL_RESET_PASSWORD_ID – Configures Loops.email for transactional messaging, referenced in src/lib/email.ts.

Testing Configuration

Deployment-Specific Variables

Docker Self-Hosting

When deploying via Docker Compose:

  • ALLOWED_HOST – Whitelist entry for reverse-proxy validation in docker-compose.yml.
  • OPEN_SEO_IMAGE – Docker image tag specification in compose.yaml.

Cloudflare Workers Production

Deploying to Cloudflare Workers requires three specific credentials used in drizzle-prod.config.ts:

  • CLOUDFLARE_ACCOUNT_ID – Your Cloudflare account identifier.
  • CLOUDFLARE_DATABASE_ID – The D1 database ID for SQL storage.
  • CLOUDFLARE_API_TOKEN – API token with Workers and D1 permissions.

These variables are marked as non-nullable in the Drizzle configuration using the ! operator, causing the build to fail if missing.

SEO and Site Configuration

How Environment Variables Are Loaded

The application uses a generic accessor function defined in src/server/lib/runtime-env.ts to safely read process.env values:

// src/server/lib/runtime-env.ts
export const runtimeEnv = (name: string) =>
  typeof process !== "undefined" ? process.env?.[name] : undefined;

This helper prevents undefined errors in edge environments and provides a single injection point for environment reads.

Configuration Quick Start

Copy the example file and configure for your deployment mode:


# Copy template

cp .env.example .env

# Example configuration for hosted mode with Google Search Console

cat <<EOF >> .env
DATAFORSEO_API_KEY=sk_test_XXXXXXXXXXXXXXXX
AUTH_MODE=hosted
BETTER_AUTH_SECRET=$(openssl rand -hex 32)
BETTER_AUTH_URL=http://localhost:3001
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
EOF

The drizzle-prod.config.ts file demonstrates strict validation for production credentials:

// drizzle-prod.config.ts
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  driver: "cloudflare",
  accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
  databaseId: process.env.CLOUDFLARE_DATABASE_ID!,
  token: process.env.CLOUDFLARE_API_TOKEN!,
});

For client-side SEO metadata, the application checks multiple variable names:

// web/src/lib/seo.ts
import { runtimeEnv } from "~/server/lib/runtime-env";

const siteUrl = runtimeEnv("SITE_URL") ?? runtimeEnv("VITE_SITE_URL") ?? "http://localhost:3000";
export const getFullUrl = (path: string) => 
  `${siteUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;

Summary

  • Minimum requirement: Only DATAFORSEO_API_KEY is mandatory for core functionality.
  • Auth modes: Cloudflare Access requires TEAM_DOMAIN and POLICY_AUD; Hosted mode requires BETTER_AUTH_SECRET and BETTER_AUTH_URL.
  • Production deployment: Cloudflare Workers needs CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_DATABASE_ID, and CLOUDFLARE_API_TOKEN.
  • Variable access: All environment reads flow through src/server/lib/runtime-env.ts using process.env.
  • Template reference: The .env.example file contains the authoritative list of all supported variables.

Frequently Asked Questions

What is the minimum setup required to run Open-SEO locally?

You only need DATAFORSEO_API_KEY set in your .env file to fetch SEO data. The application will default to cloudflare_access authentication mode (with AUTH_MODE unset) and bind to port 3000, though you will not be able to authenticate users without configuring either Cloudflare Access headers or switching to hosted mode with Better Auth credentials.

How do I configure Open-SEO for production deployment on Cloudflare Workers?

Set the three Cloudflare-specific variables in your deployment environment: CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_DATABASE_ID, and CLOUDFLARE_API_TOKEN. These are consumed in drizzle-prod.config.ts to configure the D1 database driver. Missing any of these will cause the deployment to fail immediately due to the non-nullable assertions in the configuration file.

What authentication options are available and what do they require?

Open-SEO supports three authentication strategies controlled by AUTH_MODE. The default cloudflare_access mode requires TEAM_DOMAIN and POLICY_AUD for Cloudflare zero-trust validation. Setting AUTH_MODE=hosted switches to Better Auth, requiring BETTER_AUTH_SECRET for encryption and BETTER_AUTH_URL for callback routing. When AUTH_MODE is undefined, the system defaults to Cloudflare Access mode but may lack valid credentials for user identification.

Are Google Search Console integrations mandatory?

No. Google OAuth is optional and only active when both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are provided. These variables are unnecessary unless you specifically want to pull search analytics data from Google's API. Without them, the application continues to function using DataforSEO data exclusively.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →