# How to Monitor and Debug Self‑Hosted OpenSEO Instances

> Learn to monitor and debug your self-hosted OpenSEO instances using built-in tools like health endpoints, telemetry, and diagnostic logs. Ensure optimal performance and troubleshoot issues effectively.

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

---

**Self‑hosted OpenSEO deployments ship with a health endpoint, a telemetry heartbeat, and a startup pre‑flight script that collectively expose runtime status, validate configuration, and stream diagnostic logs to standard output.**

OpenSEO is an open‑source SEO automation platform maintained in the `every-app/open-seo` repository. When you run the self‑hosted variant via Docker, the runtime exposes several first‑party mechanisms for observability. Below is a complete guide to leveraging the health API, telemetry worker, and container logs to keep your instance healthy.

## Built‑in Health Endpoint

The application exposes an unauthenticated `GET /api/health` route that returns a JSON map of per‑feature setup checks. These checks cover database connectivity, DataForSEO API keys, Google Search Console authentication, and other critical dependencies.

In [`src/routes/api/health.ts`](https://github.com/every-app/open-seo/blob/main/src/routes/api/health.ts), the handler re‑uses the same check map consumed by the Docker pre‑flight script, ensuring consistency between startup validation and runtime queries. You can poll this endpoint from any monitoring system or curl it locally for a quick pulse check.

```bash
curl -s http://localhost:8787/api/health | jq .

```

Typical output includes status keys for each subsystem:

```json
{
  "dataforseo": "ok",
  "google-search-console": "ok",
  "database": "ok",
  "selfHostTelemetry": "ok"
}

```

## Self‑Host Telemetry Heartbeat

A lightweight background worker in [`src/server/lib/self-host-telemetry.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/self-host-telemetry.ts) periodically pings the OpenSEO telemetry service. It reports the results of the health checks alongside counts of processed audits, rank checks, and MCP calls.

If the heartbeat fails, the module emits debug logs to standard error. This gives you immediate visibility into network partitions or authentication issues without exposing sensitive data in the heartbeat payload itself.

To inspect telemetry activity in real time, filter the Docker logs:

```bash
docker logs --follow open-seo-selfhost | grep "self-host telemetry"

```

A successful heartbeat appears as:

```

🟢 self-host telemetry heartbeat succeeded (runId=abc123)

```

## Startup Validation with Pre‑flight Checks

Before the application accepts traffic, [`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) executes inside the container (as defined in `Dockerfile.selfhost`). This TypeScript script validates required environment variables, tests connectivity to external APIs such as DataForSEO and Google Search Console, and runs the same health checks exposed by `/api/health`.

Any failure aborts the container start, giving you immediate feedback at deploy time rather than runtime. For example, a missing DataForSEO key produces:

```bash
node scripts/selfhost-preflight.ts

```

Output:

```

❌ Missing DATAFORSEO_API_KEY – aborting startup

```

Because the pre‑flight logic mirrors the health endpoint logic, passing the pre‑flight guarantees that the health endpoint will return `"ok"` for all critical dependencies.

## Log Inspection and Debugging

OpenSEO runs as a Cloudflare Workers‑compatible container, so all `console.error`, `console.warn`, and `console.debug` calls—emitted from audit workers, rank‑check workflows, and MCP tools—are captured by Docker’s logging driver.

View the full log stream:

```bash
docker logs <container>

```

Enable verbose debug logging by setting `LOG_LEVEL=debug` before starting the container:

```bash
docker run -e LOG_LEVEL=debug -p 8787:8787 everyapp/open-seo:selfhost

```

At this level, [`src/server/lib/self-host-telemetry.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/self-host-telemetry.ts) and other modules emit granular traces useful for tracing failed audit jobs or MCP tool invocations.

For production‑grade observability, forward the container’s stdout to a log aggregation service such as Loki or Datadog. The telemetry heartbeat already ships aggregated metrics to the OpenSEO SaaS dashboard, where you can view instance‑level health charts separately from raw container logs.

## Summary

- **Health endpoint** (`/api/health`): Poll this JSON endpoint to verify database, API, and authentication status at runtime.
- **Telemetry worker** ([`src/server/lib/self-host-telemetry.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/self-host-telemetry.ts)): Emits periodic heartbeats and debug logs on failure; grep container logs for `"self-host telemetry"` to verify connectivity.
- **Pre‑flight validation** ([`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts)): Catches configuration errors at container start by replicating the health checks before the server boots.
- **Docker logs**: Capture all `console.*` output from workers and workflows; enable `LOG_LEVEL=debug` for verbose tracing.

## Frequently Asked Questions

### How often does the self‑host telemetry heartbeat run?

The background worker in [`src/server/lib/self-host-telemetry.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/self-host-telemetry.ts) sends a heartbeat on an interval defined by the telemetry configuration, typically every few minutes. Each ping includes the current health check results and aggregate job counts, allowing the SaaS dashboard to plot instance health over time.

### Can I disable telemetry while keeping the health endpoint?

The telemetry module respects environment variables. While the health endpoint ([`src/routes/api/health.ts`](https://github.com/every-app/open-seo/blob/main/src/routes/api/health.ts)) remains available for local monitoring, you can opt out of remote telemetry by omitting the telemetry token or setting the appropriate disable flag, though this will prevent the aggregated metrics from appearing in the OpenSEO dashboard.

### What is the difference between the pre‑flight script and the health endpoint?

[`scripts/selfhost-preflight.ts`](https://github.com/every-app/open-seo/blob/main/scripts/selfhost-preflight.ts) runs once at container startup and exits non‑zero on failure, preventing the service from starting with invalid configuration. The health endpoint ([`src/routes/api/health.ts`](https://github.com/every-app/open-seo/blob/main/src/routes/api/health.ts)) exposes the same check logic via HTTP so you can query runtime state continuously. Both use the underlying check map, but the pre‑flight acts as a gate, while the endpoint acts as a gauge.

### How do I debug a failing audit or rank‑check worker?

Set `LOG_LEVEL=debug` and inspect the Docker logs. Workers such as those in `src/server/workflows/` emit `console.debug` statements at the start and end of each job, including error stack traces on failure. Filtering the logs by the workflow ID or error keyword will isolate the specific job trace.