Docker vs Cloudflare Workers Self-Hosting for OpenSEO: Architecture and Deployment Guide
OpenSEO supports two distinct self-hosting models—Docker containers and Cloudflare Workers—that differ fundamentally in runtime environment, infrastructure automation, security architecture, and global distribution.
The every-app/open-seo repository provides production-ready configurations for both deployment modes. While both methods execute the same application logic, Docker self-hosting keeps execution on infrastructure you control, whereas Cloudflare Workers distributes the application across Cloudflare's global edge network. Your choice determines how you handle authentication, database provisioning, scaling, and request latency.
Execution Environment and Runtime Architecture
Docker Container Runtime
In the Docker model, OpenSEO runs inside a Linux container on a host you fully control—whether a local machine, virtual private server, or on-premise hardware. According to Dockerfile.selfhost, the image bundles a complete Node.js runtime environment and executes the application as a traditional long-running process. You must provision and connect a PostgreSQL database (or Cloudflare D1 via tunnel) separately, managing the container lifecycle through Docker Compose or orchestration platforms like Kubernetes.
Cloudflare Edge Runtime
The Cloudflare Workers deployment compiles OpenSEO into a lightweight V8 isolate that runs on Cloudflare's global network. The wrangler.jsonc configuration file defines how Wrangler bundles the code and uploads it to Cloudflare's edge nodes. Unlike Docker, this serverless model requires no persistent container; instead, the platform spins up execution environments on-demand at the nearest data center to the requesting user.
Infrastructure and Deployment Workflow
Docker Compose Method
Deploying via Docker relies on the compose.yaml file, which pulls the container image from GitHub Container Registry (ghcr.io/every-app/open-seo:latest). You control the deployment through standard Docker commands:
# Configure local environment
cp .env.example .env
# Edit DATAFORSEO_API_KEY, optional PORT, etc.
# Start services
docker compose up -d
This approach requires you to manually configure networking, TLS termination, and reverse proxies. Version pinning is achieved by setting OPEN_SEO_IMAGE=ghcr.io/every-app/open-seo:<tag> in your environment file and restarting the service.
Cloudflare Wrangler Automation
The Cloudflare pathway automates infrastructure provisioning through the pnpm deploy:selfhost --yes command. As implemented in scripts/selfhost-preflight.ts, this script validates local configuration before creating Cloudflare D1 databases, KV namespaces, and R2 buckets automatically. The deployment flow requires Cloudflare authentication via pnpm alchemy login and bootstraps the state store with pnpm alchemy cloudflare bootstrap:
# Authenticate and bootstrap
pnpm alchemy login
pnpm alchemy cloudflare bootstrap
# Configure self-host environment
cp .env.selfhost.example .env.selfhost
# Edit DATAFORSEO_API_KEY, ACCESS_ALLOWED_EMAILS, etc.
# Deploy to edge
pnpm deploy:selfhost --yes
Authentication and Security Models
Local No-Auth Mode (Docker)
By default, Docker deployments set AUTH_MODE=local_noauth, disabling internal application authentication. Security responsibility shifts entirely to your infrastructure; you must protect the exposed TCP port (default 3001) using a reverse proxy, VPN tunnel, or private network segmentation.
Zero-Trust Access (Cloudflare)
Cloudflare Workers installations leverage Cloudflare Access out-of-the-box. The deployment creates a Zero-Trust application requiring authentication via the email addresses specified in ACCESS_ALLOWED_EMAILS. TLS termination and DDoS protection are handled automatically by Cloudflare's global CDN, with no additional proxy configuration required.
Storage and Database Architecture
Docker self-hosting requires you to attach a PostgreSQL database yourself, typically defined alongside the application container in your Compose configuration or connected to an external managed database service. All state persists on infrastructure you maintain.
Conversely, the Cloudflare deployment provisions D1 (serverless SQLite), KV (key-value store), and R2 (object storage) automatically during the deploy:selfhost execution. This eliminates database server maintenance but binds your data to Cloudflare's platform.
Networking and Global Distribution
Docker exposes a single TCP port that you must route to the internet manually, creating a single point of origin for all traffic. Cloudflare Workers automatically deploys to a *.workers.dev subdomain (or custom domain) with global anycast routing, serving requests from the nearest edge location without additional configuration.
Scalability Characteristics
Scaling Docker requires horizontal container replication via Docker Swarm, Kubernetes, or larger host provisioning—operations you must manage yourself. Cloudflare Workers offers implicit scaling; the platform automatically distributes execution across its global infrastructure, handling load spikes without manual intervention or container orchestration.
Deployment Quickstart Examples
Docker Self-Hosting
Following the instructions in docs/SELF_HOSTING_DOCKER.md:
# 1. Prepare environment variables
cp .env.example .env
# Edit .env to set DATAFORSEO_API_KEY
# 2. Launch container stack
docker compose up -d
# 3. Verify health endpoint
curl http://localhost:3001/api/health
Cloudflare Workers Self-Hosting
Following the instructions in docs/SELF_HOSTING_CLOUDFLARE.md:
# 1. Clone and setup
git clone https://github.com/every-app/open-seo.git
cd open-seo
corepack enable
pnpm install
# 2. Authenticate with Cloudflare
pnpm alchemy login
pnpm alchemy cloudflare bootstrap
# 3. Configure deployment
cp .env.selfhost.example .env.selfhost
# Edit ACCESS_ALLOWED_EMAILS, DATAFORSEO_API_KEY
# 4. Deploy
pnpm deploy:selfhost --yes
# 5. Test deployment
curl https://<your-worker>.workers.dev/api/health
Summary
- Docker runs OpenSEO as a containerized Node.js process on your infrastructure, requiring manual database provisioning, reverse proxy configuration, and scaling management.
- Cloudflare Workers executes OpenSEO as V8 isolates on Cloudflare's edge network, automatically provisioning D1, KV, and R2 storage while handling global distribution, TLS, and authentication via Cloudflare Access.
- Authentication defaults to disabled (
local_noauth) in Docker, placing security burden on your network architecture, whereas Cloudflare enforces Zero-Trust Access with email-based authentication. - Deployment involves
docker compose up -dfor Docker versuspnpm deploy:selfhost --yesfor Cloudflare, with the latter automating infrastructure creation defined inwrangler.jsonc. - Scaling is manual in Docker (container replication) and automatic in Cloudflare Workers (serverless edge distribution).
Frequently Asked Questions
Which self-hosting option is easier for beginners?
Cloudflare Workers self-hosting requires less infrastructure knowledge because the pnpm deploy:selfhost --yes command automatically provisions databases, storage, and security policies. Docker requires familiarity with container networking, reverse proxies, and PostgreSQL administration, making it better suited for teams with existing DevOps expertise.
Can I migrate from Docker to Cloudflare Workers without losing data?
Migration requires manual data export and import because Docker typically uses PostgreSQL while Cloudflare uses D1 (SQLite-compatible). You would need to export your PostgreSQL data and import it into the D1 database created by the Cloudflare deployment, as the two storage backends use different SQL dialects and connection methods.
How do costs compare between Docker and Cloudflare Workers self-hosting?
Docker costs are limited to your host and database expenses (VM rental or hardware amortization), while Cloudflare Workers incurs usage-based charges for D1 queries, KV reads/writes, and R2 storage. Note that Cloudflare R2 requires a payment method on file even for the free tier, whereas Docker self-hosting can run entirely on free open-source software.
Is telemetry collected in both deployment modes?
Yes, both modes send telemetry to OpenSEO's backend by default, though it can be disabled in Docker by setting OPENSEO_TELEMETRY_DISABLED=1 in your environment file. The Cloudflare Workers implementation runs the same telemetry logic within the V8 isolate, requiring no additional container-level configuration to operate.
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 →