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.
DATAFORSEO_API_KEY– Required for all deployment modes. This key authenticates requests to DataforSEO endpoints consumed inscripts/brand-lookup-cost-profile.tsandscripts/backlinks-cost-profile.ts.PORT– Optional. Defaults to3000when unset. Referenced invite.config.tsto bind the development server.
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 withopenssl rand -hex 32).BETTER_AUTH_URL– The canonical URL where your auth server runs (e.g.,http://localhost:3001for 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_KEYandPOSTHOG_HOST– Enables PostHog product analytics when both are present, consumed insrc/lib/analytics.ts.LOOPS_API_KEY,LOOPS_TRANSACTIONAL_VERIFY_EMAIL_ID, andLOOPS_TRANSACTIONAL_RESET_PASSWORD_ID– Configures Loops.email for transactional messaging, referenced insrc/lib/email.ts.
Testing Configuration
PLAYWRIGHT_CHANNEL– Selects browser channels for end-to-end tests inplaywright.config.ts.DOMAIN_FILTER_CPU_THROTTLE– Controls performance throttling ine2e/domain-overview-filters.perf.spec.ts.
Deployment-Specific Variables
Docker Self-Hosting
When deploying via Docker Compose:
ALLOWED_HOST– Whitelist entry for reverse-proxy validation indocker-compose.yml.OPEN_SEO_IMAGE– Docker image tag specification incompose.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
SITE_URLorVITE_SITE_URL– Base URL for sitemap generation inweb/scripts/generate-sitemap.jsand meta tag rendering inweb/src/lib/seo.ts. Falls back tohttp://localhost:3000when undefined.
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_KEYis mandatory for core functionality. - Auth modes: Cloudflare Access requires
TEAM_DOMAINandPOLICY_AUD; Hosted mode requiresBETTER_AUTH_SECRETandBETTER_AUTH_URL. - Production deployment: Cloudflare Workers needs
CLOUDFLARE_ACCOUNT_ID,CLOUDFLARE_DATABASE_ID, andCLOUDFLARE_API_TOKEN. - Variable access: All environment reads flow through
src/server/lib/runtime-env.tsusingprocess.env. - Template reference: The
.env.examplefile 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →