Technical Requirements for Self-Hosting OpenSEO on Cloudflare Workers
To self-host OpenSEO on Cloudflare Workers, you need Node.js 22.6 or newer, pnpm, a Cloudflare account with R2 enabled, a DataForSEO API key, and a configured .env.selfhost file containing allowed user emails and external service credentials.
The every-app/open-seo repository deploys as a Cloudflare Worker using a serverless edge architecture that relies on Cloudflare-native storage and external SEO data providers. Successfully self-hosting requires specific runtime versions, API accounts, and environment variables that are validated during the deployment process. This guide details the exact technical prerequisites, resource bindings, and configuration steps defined in the source documentation and wrangler.jsonc.
Prerequisites and Runtime Dependencies
Before deploying, your local environment must meet the following specifications:
- Node.js 22.6 or newer — The
package.jsonexplicitly declares"engines": { "node": ">=22.6" }for build-time compatibility. - pnpm package manager — Install via
corepack enable. The deployment scripts inpackage.json(such aspnpm deploy:selfhost) depend on pnpm. - Cloudflare account with R2 enabled — You must have a Cloudflare account with R2 object storage activated. According to
docs/SELF_HOSTING_CLOUDFLARE.md, a payment method is required on file even for the free tier to enable R2.
External Service Accounts
Self-hosting OpenSEO requires active accounts with the following third-party providers:
- DataForSEO account — Required for SEO data APIs. You must generate an API key and reference it as
DATAFORSEO_API_KEYin your environment file, as documented indocs/DATAFORSEO_API_KEY.md. - Alchemy CLI — Used for bootstrapping the state-store Worker and managing infrastructure. You will run
pnpm alchemy loginto authenticate with theaccess:writeOAuth scope before deploying.
Environment Configuration and Required Variables
Create a .env.selfhost file by copying .env.selfhost.example. At minimum, the file must define:
ACCESS_ALLOWED_EMAILS— A comma-separated list of email addresses permitted to access the application through Cloudflare Access.DATAFORSEO_API_KEY— Your DataForSEO API credentials.
Optional variables include:
TEAM_DOMAINandPOLICY_AUD— For customizing Cloudflare Access policies.OPENSEO_TELEMETRY_DISABLED=1— Set this to disable anonymized usage telemetry, as noted indocs/SELF_HOSTING_CLOUDFLARE_OPERATIONS.md.
Cloudflare Resources and Architecture
The OpenSEO Worker binds to several Cloudflare resources defined in wrangler.jsonc. During deployment via pnpm deploy:selfhost, the Alchemy CLI automatically provisions:
- D1 database — A SQLite-compatible database (binding
d1_databases) for application state. - KV namespaces — Two separate namespaces:
KVfor general caching andOAUTH_KVfor OAuth state management. - R2 bucket — An
open-seobucket for static assets and file storage.
The Worker entry point is src/server.ts, configured as the main handler in wrangler.jsonc. Database migrations located in drizzle.config.ts and the drizzle/ directory target the D1 instance.
Deployment Workflow
Execute the following commands in sequence to provision resources and deploy the Worker:
# Clone and prepare the repository
git clone https://github.com/every-app/open-seo.git
cd open-seo
corepack enable
pnpm install
# Authenticate with Cloudflare (required once)
pnpm alchemy login
pnpm alchemy cloudflare bootstrap
# Configure environment variables
cp .env.selfhost.example .env.selfhost
# Edit .env.selfhost to set:
# ACCESS_ALLOWED_EMAILS="admin@example.com"
# DATAFORSEO_API_KEY="your-api-key"
# Deploy the self-host stage
pnpm deploy:selfhost --yes
The deploy:selfhost command creates D1 tables, provisions KV and R2 bindings, runs database migrations, and configures a Cloudflare Access application to gate entry.
To update an existing deployment after pulling new code:
git pull
pnpm install
pnpm deploy:selfhost --yes
To completely remove the deployment and clean up resources:
pnpm alchemy destroy --env-file .env.selfhost --stage selfhost
Post-Deployment Operations
After initial deployment, you may need to configure additional access controls and monitoring.
Telemetry Management
By default, OpenSEO transmits anonymized usage telemetry. To opt out, set OPENSEO_TELEMETRY_DISABLED=1 in .env.selfhost and redeploy.
MCP Client Access
To enable Managed Client Protocol (MCP) clients, you must turn on Managed OAuth within the Cloudflare Access application settings. Details are provided in docs/SELF_HOSTING_CLOUDFLARE_OPERATIONS.md.
Summary
- Node.js 22.6+ and pnpm are required local dependencies.
- A Cloudflare account with R2 enabled and a DataForSEO API key are mandatory external requirements.
- The
.env.selfhostfile must defineACCESS_ALLOWED_EMAILSandDATAFORSEO_API_KEYat minimum. - Cloudflare resources (D1, KV, R2) are automatically provisioned by the Alchemy CLI during
pnpm deploy:selfhost. - The Worker entry point is
src/server.ts, with database migrations managed viadrizzle.config.ts. - Telemetry can be disabled via environment variable, and MCP access requires additional Cloudflare Access configuration.
Frequently Asked Questions
Can I self-host OpenSEO without a DataForSEO account?
No. The application depends on DataForSEO for search engine ranking and keyword data. Without a valid DATAFORSEO_API_KEY defined in .env.selfhost, the Worker cannot fetch SEO metrics, causing functionality to fail.
What Cloudflare plan is required for self-hosting OpenSEO?
The free tier is sufficient, but you must add a payment method to your Cloudflare account to activate R2 storage. The deployment uses R2 for static assets, D1 for the database, and KV for caching, all of which operate within free tier limits for low-to-moderate traffic.
How do I update my self-hosted OpenSEO deployment?
Pull the latest changes from the every-app/open-seo repository, run pnpm install to update dependencies, and execute pnpm deploy:selfhost --yes to apply changes. The Alchemy CLI will update the Worker and run any pending database migrations without destroying existing data.
Where is application data persisted in a Cloudflare Workers environment?
Data persists in Cloudflare D1 (a SQLite-compatible edge database) for structured data, R2 for static files and assets, and KV for session caching and OAuth state. These bindings are defined in wrangler.jsonc and injected into the Worker at runtime.
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 →