# How to Self‑Host OpenSEO: Docker and Cloudflare Workers Deployment Guide

> Learn to self-host OpenSEO using Docker for private networks or Cloudflare Workers for production edge hosting. Deploy the every-app/open-seo repository effortlessly.

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

---

**The OpenSEO application from the `every-app/open-seo` repository can be self‑hosted either via a lightweight Docker container for private networks or deployed to Cloudflare Workers for production‑scale edge hosting.**

OpenSEO is a modern TypeScript application that bundles an SEO analysis UI with an MCP (Model Context Protocol) server, fetching all data from the DataForSEO API. Whether you choose the simplicity of Docker or the scalability of Cloudflare’s serverless platform, both paths share a common core architecture defined in the `src/` directory and validated by pre‑flight checks.

## Prerequisites for Both Deployment Paths

Before deploying OpenSEO, you must obtain a **DataForSEO API key** by base64‑encoding your `email:password` credentials. This key is the only mandatory secret required by the pre‑flight validation logic in [`src/lib/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/selfhost-preflight.ts).

- **Docker path**: Docker Desktop or Docker Engine + Compose.
- **Cloudflare path**: Node.js 22+, pnpm, and a Cloudflare account with R2 enabled.

## Option 1: Docker Self‑Hosting (Simple)

The Docker workflow is designed for private networks and rapid local testing. It uses the `Dockerfile.selfhost` definition and disables built‑in authentication via `AUTH_MODE=local_noauth`, making it suitable only behind a reverse proxy or VPN.

### Environment Configuration

Copy the example environment file and configure your DataForSEO credentials:

```bash
cp .env.example .env

# Edit .env and set:

# DATAFORSEO_API_KEY=<base64_encoded_email_password>

# AUTH_MODE=local_noauth

```

Optional variables in [`src/lib/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/selfhost-preflight.ts) include `PORT` (defaults to 3001), `ALLOWED_HOST`, and `OPENSEO_TELEMETRY_DISABLED`.

### Running the Container

Deploy OpenSEO using the pre‑built GitHub Container Registry image:

```bash
docker compose up -d

```

The [`docker-compose.yml`](https://github.com/every-app/open-seo/blob/main/docker-compose.yml) pulls `ghcr.io/every-app/open-seo:latest` and exposes the UI and MCP endpoints on your configured port. According to the source in [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md), the container executes [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) before starting the main application to validate that `DATAFORSEO_API_KEY` is present and that the selected `AUTH_MODE` is supported.

## Option 2: Cloudflare Workers (Recommended)

For production environments, OpenSEO targets Cloudflare’s edge network. This deployment provisions a **D1 database** for SQLite‑compatible storage, **KV namespaces** for static assets, and **R2 buckets** for large file storage (e.g., PDF content analysis), all orchestrated via the Wrangler configuration in `wrangler.jsonc`.

### Initial Setup and Authentication

Clone the repository and enable the Alchemy deployment framework:

```bash
git clone https://github.com/every-app/open-seo.git
cd open-seo
corepack enable
pnpm install
pnpm alchemy login  # Grants access:write scope

pnpm alchemy cloudflare bootstrap  # Creates state-store Worker

```

### Configuration and Deployment

Copy the self‑host template and define access controls:

```bash
cp .env.selfhost.example .env.selfhost

# Required: DATAFORSEO_API_KEY

# Required: ACCESS_ALLOWED_EMAILS (comma‑separated Cloudflare Access allowlist)

# Optional: TEAM_DOMAIN, POLICY_AUD for SSO integration

```

Execute the deployment command:

```bash
pnpm deploy:selfhost --yes

```

This single command, defined in the project scripts, provisions all cloud resources, applies database migrations, and deploys the Worker. As detailed in [`docs/SELF_HOSTING_CLOUDFLARE.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_CLOUDFLARE.md), the resulting instance is protected by **Cloudflare Access**, restricting the UI and [`src/router.tsx`](https://github.com/every-app/open-seo/blob/main/src/router.tsx) MCP endpoints to the emails specified in `ACCESS_ALLOWED_EMAILS`.

### Architecture Overview

When running on Cloudflare, OpenSEO utilizes:
- **Worker**: The compiled Vite application serving HTTP requests and MCP API calls.
- **D1**: Relational database for user data, projects, and ranking history.
- **KV**: Low‑latency key‑value storage for application state.
- **R2**: Object storage for large binary uploads.
- **Access**: Identity‑aware proxy enforcing authentication before traffic reaches the Worker.

## Pre‑Flight Checks and Telemetry

OpenSEO runs a validation layer before boot to prevent misconfigurations. The [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) entry point calls the core logic in [`src/lib/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/selfhost-preflight.ts) to verify environment variables and abort startup if critical checks fail (e.g., missing API keys).

By default, an optional telemetry beacon reports anonymous installation status to help the maintainers track deployment health. Disable this tracking by setting either `OPENSEO_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1` in your environment file, as documented in the Docker hosting guide.

## Summary

- **OpenSEO** is a TypeScript MCP server and UI that requires a **DataForSEO API key** to function.
- The **Docker** path (`Dockerfile.selfhost`) offers rapid deployment with `docker compose up -d` but requires `AUTH_MODE=local_noauth`, suitable only for private networks.
- The **Cloudflare** path is the recommended production setup, using `pnpm deploy:selfhost --yes` to provision D1, KV, R2, and Access resources automatically.
- The **pre‑flight script** ([`src/lib/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/selfhost-preflight.ts)) validates configuration before startup and supports opt‑out telemetry via `OPENSEO_TELEMETRY_DISABLED`.

## Frequently Asked Questions

### What is the MCP server in OpenSEO?

The **MCP server** is an HTTP API exposed by [`src/router.tsx`](https://github.com/every-app/open-seo/blob/main/src/router.tsx) that allows AI agents (such as Claude Code or OpenClaw) to request SEO data programmatically. When self‑hosting, you can connect compatible agents to your protected instance to automate SEO analysis workflows.

### Can I run OpenSEO without a DataForSEO account?

No. All SEO data fetching depends on the **DataForSEO API**, and the pre‑flight check in [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) will fail if `DATAFORSEO_API_KEY` is missing or malformed. You must encode your DataForSEO credentials as a base64 string (`email:password`) to populate this variable.

### Is Docker safe for production use?

The Docker configuration sets `AUTH_MODE=local_noauth` by default, disabling all authentication checks in the application logic. Therefore, the Docker path should only be used in private networks or behind a reverse proxy that provides its own authentication layer. For internet‑facing deployments, use the **Cloudflare Workers** path with Cloudflare Access enabled.

### How do I update a self‑hosted OpenSEO instance?

For **Docker** deployments, run `docker compose pull && docker compose up -d` to fetch the latest `ghcr.io/every-app/open-seo:latest` image. For **Cloudflare** deployments, pull the latest code from the `every-app/open-seo` repository and rerun `pnpm deploy:selfhost --yes` to apply updates and database migrations automatically.