How to Set Up OpenSEO for Self-Hosting with Docker: A Complete Deployment Guide
OpenSEO can be deployed as a fully containerized application using Docker Compose, bundling the Node 22 runtime, application code, and automated build steps into a single portable image.
The every-app/open-seo repository provides production-ready containerization files that enable you to run the entire SEO platform locally or on your own infrastructure. This guide walks through the complete setup process using the official Dockerfile.selfhost and compose.yaml configuration, from environment preparation to custom image builds.
Prerequisites
Before deploying OpenSEO via Docker, ensure you have the following:
- Docker Engine (20.10+) and Docker Compose (v2+) installed on your host
- A DataForSEO API key (base64-encoded string of your
email:password) - At least 2GB of RAM allocated to Docker for the initial Vite build process
The container architecture requires the full Node 22 base image (not Alpine) to provide a proper CA trust store for the internal Cloudflare workerd process used by the application.
Step-by-Step Installation
Clone and Configure Environment
First, obtain the repository files and prepare your environment configuration:
# Clone the repository
git clone https://github.com/every-app/open-seo.git
cd open-seo
# Copy the environment template
cp .env.example .env
Edit the .env file to set your DATAFORSEO_API_KEY. This value must be a base64-encoded string of your DataForSEO email and password joined by a colon:
# Generate your key if needed
echo -n "your-email@domain.com:your-password" | base64
# Add to .env
DATAFORSEO_API_KEY=your_base64_encoded_key_here
The .env.example file contains all required and optional configuration values, including optional AI service keys and telemetry settings.
Launch the Container
Start the application using the pre-built image from the GitHub Container Registry:
docker compose up -d
The compose.yaml file automatically:
- Pulls
ghcr.io/every-app/open-seo:latest(or a custom tag specified viaOPEN_SEO_IMAGE) - Injects variables from your
.envfile - Sets required runtime flags including
AUTH_MODE=local_noauthandCLOUDFLARE_INCLUDE_PROCESS_ENV=true - Mounts the named volume
open_seo_datato persist build artifacts
Verify the Deployment
Monitor the startup process and wait for the initial Vite SSR build to complete:
docker compose logs -f open-seo
The docker-entrypoint.sh script handles pre-flight database migrations, conditional Vite builds, and server startup. Once healthy, the application is accessible at http://localhost:3001 (or your configured PORT).
Docker's native health-check pings the /api/health endpoint every 30 seconds after an initial 5-minute start period, ensuring the container is only marked healthy when fully ready.
Understanding the Docker Architecture
Dockerfile.selfhost Structure
The Dockerfile.selfhost defines a minimal production image that:
- Uses the full Node 22 image to ensure proper HTTPS certificate authority validation for workerd processes
- Installs pnpm and copies the application source
- Executes
pnpm install --frozen-lockfilefor reproducible dependencies - Sets
docker-entrypoint.shas the container entrypoint
This configuration ensures the Cloudflare workerd runtime has access to the host's CA trust store for outbound HTTPS calls.
Entrypoint and Health Checks
The docker-entrypoint.sh script performs critical startup logic:
- Runs database migrations before serving traffic
- Conditionally executes the Vite SSR build (cached in subsequent restarts via
open_seo_datavolume) - Launches the HTTP server on the configurable
PORTenvironment variable - Defines the health-check endpoint at
/api/health
The Dockerfile includes a HEALTHCHECK instruction that uses this endpoint to monitor container readiness.
Building Custom Images
To modify the source code or use a specific version, build a local image:
# Build from modified source
docker build -f Dockerfile.selfhost -t open-seo:local .
# Run with your custom image
OPEN_SEO_IMAGE=open-seo:local docker compose up -d
This approach is essential when developing custom plugins or modifying the core application logic before deployment.
Configuration and Telemetry
Required Environment Variables
The following variables must be configured in your .env file:
DATAFORSEO_API_KEY: Base64-encoded authentication for DataForSEO API accessPORT: HTTP server port (defaults to3001)
Optional variables include AI service keys (OpenAI, Anthropic) and database connection strings if not using the default SQLite setup.
Disabling Telemetry
OpenSEO includes opt-out telemetry. To disable data collection, add either of these lines to your .env file:
OPENSEO_TELEMETRY_DISABLED=1
# or
DO_NOT_TRACK=1
After modifying environment variables, recreate the container:
docker compose up -d --force-recreate open-seo
Common Operations
View real-time logs:
docker compose logs -f open-seo
Restart after configuration changes:
docker compose up -d --force-recreate open-seo
Stop the service:
docker compose down
Update to the latest image:
docker compose pull open-seo
docker compose up -d
Summary
- OpenSEO self-hosting uses a Node 22-based Docker image with
Dockerfile.selfhostto ensure proper HTTPS certificate handling for internal workerd processes. - The
compose.yamlorchestrates the container, injecting.envvariables and persisting build data in theopen_seo_datavolume. - The
docker-entrypoint.shscript handles migrations, conditional Vite SSR builds, and server startup, exposing a health-check endpoint at/api/health. - A DataForSEO API key (base64-encoded) is the only mandatory configuration for basic operation.
- Telemetry can be disabled via
OPENSEO_TELEMETRY_DISABLED=1orDO_NOT_TRACK=1in your environment file.
Frequently Asked Questions
What is the minimum server requirement for self-hosting OpenSEO?
OpenSEO requires Docker with at least 2GB of available RAM for the initial build process, though subsequent restarts consume less memory due to cached build artifacts in the open_seo_data volume. The container uses a standard Node 22 runtime image and exposes port 3001 by default.
Why does the Dockerfile use the full Node 22 image instead of Alpine?
According to the OpenSEO source code, the full Node 22 image is required because the internal Cloudflare workerd process needs a proper CA (Certificate Authority) trust store for making outbound HTTPS calls. Alpine-based images lack the necessary CA certificates that workerd requires to function correctly.
How do I update my OpenSEO installation to the latest version?
Run docker compose pull open-seo to fetch the latest image from ghcr.io/every-app/open-seo:latest, then execute docker compose up -d to recreate the container. Your data persists in the named volume, and the docker-entrypoint.sh script will handle any necessary database migrations automatically during startup.
Can I run OpenSEO without DataForSEO integration?
No, the DATAFORSEO_API_KEY is currently a mandatory requirement for the application to function, as specified in the .env.example template. This base64-encoded key authenticates your requests to the DataForSEO API, which provides the core search engine data that powers OpenSEO's analysis features.
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 →