# How to Set Up OpenSEO for Self-Hosting with Docker: A Complete Deployment Guide

> Deploy OpenSEO for self-hosting with Docker easily. This guide provides complete steps to containerize your application using Docker Compose for a portable and efficient setup.

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

---

**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`](https://github.com/every-app/open-seo/blob/main/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:

```bash

# 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:

```bash

# 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:

```bash
docker compose up -d

```

The [`compose.yaml`](https://github.com/every-app/open-seo/blob/main/compose.yaml) file automatically:
- Pulls `ghcr.io/every-app/open-seo:latest` (or a custom tag specified via `OPEN_SEO_IMAGE`)
- Injects variables from your `.env` file
- Sets required runtime flags including `AUTH_MODE=local_noauth` and `CLOUDFLARE_INCLUDE_PROCESS_ENV=true`
- Mounts the named volume `open_seo_data` to persist build artifacts

### Verify the Deployment

Monitor the startup process and wait for the initial Vite SSR build to complete:

```bash
docker compose logs -f open-seo

```

The [`docker-entrypoint.sh`](https://github.com/every-app/open-seo/blob/main/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-lockfile` for reproducible dependencies
- Sets [`docker-entrypoint.sh`](https://github.com/every-app/open-seo/blob/main/docker-entrypoint.sh) as 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`](https://github.com/every-app/open-seo/blob/main/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_data` volume)
- Launches the HTTP server on the configurable `PORT` environment 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:

```bash

# 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 access
- `PORT`: HTTP server port (defaults to `3001`)

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:

```bash
OPENSEO_TELEMETRY_DISABLED=1

# or

DO_NOT_TRACK=1

```

After modifying environment variables, recreate the container:

```bash
docker compose up -d --force-recreate open-seo

```

## Common Operations

**View real-time logs:**

```bash
docker compose logs -f open-seo

```

**Restart after configuration changes:**

```bash
docker compose up -d --force-recreate open-seo

```

**Stop the service:**

```bash
docker compose down

```

**Update to the latest image:**

```bash
docker compose pull open-seo
docker compose up -d

```

## Summary

- OpenSEO self-hosting uses a Node 22-based Docker image with `Dockerfile.selfhost` to ensure proper HTTPS certificate handling for internal workerd processes.
- The [`compose.yaml`](https://github.com/every-app/open-seo/blob/main/compose.yaml) orchestrates the container, injecting `.env` variables and persisting build data in the `open_seo_data` volume.
- The [`docker-entrypoint.sh`](https://github.com/every-app/open-seo/blob/main/docker-entrypoint.sh) script 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=1` or `DO_NOT_TRACK=1` in 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`](https://github.com/every-app/open-seo/blob/main/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.