---
title: "Deploy OpenSEO"
description: "Open-source SEO platform for keyword research and site audits"
category: "Analytics"
url: https://railway.com/deploy/open-seo
---

# Deploy OpenSEO

Open-source SEO platform for keyword research and site audits

**[Deploy OpenSEO on Railway](https://railway.com/template/open-seo)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/open-seo/manifest.json

- **Creator:** A3A
- **Category:** Analytics

## Template content

### gateway https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/caddy.svg

- **Source:** https://github.com/gridalpha/openseo-railway
- **Health check:** /healthz
- **Public domain:** Yes

### open-seo https://raw.githubusercontent.com/every-app/open-seo/main/public/android-chrome-512x512.png

- **Source:** https://github.com/gridalpha/openseo-railway
- **Health check:** /api/health

## Documentation

# Deploy and Host OpenSEO on Railway

OpenSEO is an open-source SEO platform — keyword research, rank tracking, backlink and competitor analysis, site audits and AI-visibility tracking — built as an alternative to Semrush, Ahrefs and Ubersuggest. Instead of a per-seat subscription it runs on your own DataForSEO API key, so you pay the data vendor directly for the queries you make. It is MIT-licensed, ships first-class MCP support so agents like Claude Code and Codex can pull SEO data themselves, and is aimed at founders and small teams.

Self-host OpenSEO on Railway and this template gives you two services. `open-seo` is the application, built from upstream's self-host image with the client and worker bundle already compiled, so a container starts serving in seconds. `gateway` is a Caddy reverse proxy holding the only public domain and HTTP basic auth. That split matters: OpenSEO's Docker self-host mode has no authentication of its own, just a single injected admin user, and upstream's docs say to run it behind an auth-protected proxy. Requests hit `gateway`, the credential is checked, and the call is forwarded over the private network to `open-seo`, which has no public domain.

![Diagram of the OpenSEO app and Caddy gateway services on Railway](https://res.cloudinary.com/rroe4rtk/image/upload/v1788805253/openseo-architecture.png)

## Getting Started with OpenSEO on Railway

Deploy the template, set a `GATEWAY_PASSWORD`, and wait for both services to go green. Open the public URL on `gateway` and the browser asks for a username and password; the username defaults to `openseo`. There is no second login inside the app, so that credential is the whole access control — pick something long.

You land on the dashboard of a project called "Default" with an onboarding checklist. The first card asks what site you are working on; enter your domain and save, and the other cards start working against it. The quickest proof the deployment is healthy is the Site Audit page: enter a URL, set a page limit, leave Lighthouse unchecked and start it. The crawler is part of the app, so it runs before anything external is configured, and in a minute or two you get pages crawled, response times, and issues by severity.

Everything else — keyword volumes, backlinks, domain overviews, rank checks — needs a DataForSEO account. Set `DATAFORSEO_API_KEY` on `open-seo` to the base64 of your login and API password, not the key shown on the DataForSEO dashboard:

```
printf 'you@example.com:your-api-password' | base64
```

`/api/health` reports database status and, per feature, whether that key, a Google OAuth client and an OpenRouter key are configured. The AI & MCP page has the MCP server URL for your agent.

![OpenSEO dashboard listing site audit issues for a project](https://res.cloudinary.com/rroe4rtk/image/upload/v1788805255/openseo-dashboard.png)

![Crawled pages table from a finished OpenSEO site audit](https://res.cloudinary.com/rroe4rtk/image/upload/v1788805256/openseo-site-audit.png)

![OpenSEO MCP server URL with agent setup guides](https://res.cloudinary.com/rroe4rtk/image/upload/v1788805258/openseo-ai-mcp.png)

## About Hosting OpenSEO

Commercial SEO suites bundle data and interface into one agency-priced subscription. OpenSEO separates them: the interface is yours to run, the data comes from DataForSEO at wholesale rates, and your keyword lists and crawl results stay in your own database.

Key features:

- Keyword research with volume, difficulty and CPC, plus clustering and saved lists
- Rank tracking across domains, with position history
- Backlink and competitor analysis, and domain overviews
- Site audits: an in-app crawler that reads `robots.txt`, stays on the audited origin, and reports broken links, redirect chains, missing tags, thin content and indexability problems
- AI visibility: brand lookup and a prompt explorer
- Search Console and Analytics connections, an MCP server, and packaged SEO skills

The app is one Cloudflare Worker bundle running under workerd. Its database, key-value stores, object storage, durable objects and background workflows all write to a single directory, which is why the template mounts a volume rather than provisioning Postgres or Redis. Caddy is the only piece with a public address, and serves an unauthenticated `/healthz` so Railway can probe it without the credential.

## Why Deploy OpenSEO on Railway

Railway removes the setup work self-hosting normally implies:

- Both services build from one source repository and deploy on push
- A managed volume keeps projects, audits and keyword lists across redeploys
- Private networking keeps the application off the public internet
- HTTPS, a public domain, health checks and restart policies are configured for you

## Common Use Cases

- A founder or in-house marketer replacing a Semrush or Ahrefs seat with a per-query bill
- An agency running keyword research and monthly audits across client domains
- A developer wiring the MCP server into Claude Code or Codex so the agent researches keywords and audits pages as it writes

## Dependencies for OpenSEO

- `ghcr.io/every-app/open-seo:latest` — the application
- `caddy:2-alpine` — the basic-auth gateway in front of it
- A persistent volume at `/data` on the `open-seo` service
- A DataForSEO account, for every feature that queries live SEO data

### Environment Variables Reference

| Variable | Service | Purpose |
|---|---|---|
| `GATEWAY_PASSWORD` | gateway | The password you sign in with. Required |
| `GATEWAY_USERNAME` | gateway | Defaults to `openseo` |
| `DATAFORSEO_API_KEY` | open-seo | base64 of your DataForSEO `login:password`; unlocks keyword, backlink, domain and rank data |
| `ALLOWED_HOST` | open-seo | Host allow-list. Use a leading-dot form of your own domain when you attach one |
| `OPENROUTER_API_KEY` | open-seo | Enables SAM, the in-app SEO agent |
| `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` / `BETTER_AUTH_SECRET` | open-seo | Search Console and Analytics; all three together |
| `OPENSEO_TELEMETRY_DISABLED` | open-seo | `1` switches off upstream's anonymous usage heartbeat |

### Deployment Dependencies

- Source and image: [every-app/open-seo](https://github.com/every-app/open-seo) (MIT), published as `ghcr.io/every-app/open-seo`
- Docs: [self-hosting](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md), [DataForSEO key setup](https://github.com/every-app/open-seo/blob/main/docs/DATAFORSEO_API_KEY.md)
- Runtime: Node 22 with the Cloudflare workerd runtime

## Hardware Requirements for Self-Hosting OpenSEO

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU |
| RAM | 1 GB | 2 GB |
| Storage | 5 GB volume | 5–10 GB, by audit history |
| Runtime | Node 22 / workerd | Node 22 / workerd |

Crawling is spiky: a large audit fetches and parses many pages at once, so raise memory before the page limit.

## Self-Hosting OpenSEO

Upstream ships a Compose file. Clone the repo, add your key to `.env` and start it:

```
git clone https://github.com/every-app/open-seo.git
cd open-seo
cp .env.example .env
echo "DATAFORSEO_API_KEY=your-base64-key" >> .env
docker compose up -d
```

That listens on `127.0.0.1:3001` with authentication disabled — fine on a laptop, unsafe elsewhere. To run one container by hand:

```
docker run -d --name open-seo -p 127.0.0.1:3001:3001 \
  -e AUTH_MODE=local_noauth \
  -e CLOUDFLARE_INCLUDE_PROCESS_ENV=true \
  -e DATAFORSEO_API_KEY=your-base64-key \
  -v open_seo_data:/app/.wrangler \
  ghcr.io/every-app/open-seo:latest
```

Deploying on Railway skips the proxy, TLS and volume work, and adds the authentication Docker mode leaves out.

## How Much Does OpenSEO Cost to Self-Host?

OpenSEO itself is free and MIT-licensed. Self-hosting costs the Railway container plus a 5 GB volume, and DataForSEO for the queries you run. Most single-site or small-agency usage lands in single-digit to low double-digit dollars a month, against the hundreds a comparable commercial seat costs. There is no licence key, seat count or feature gate in the open-source build.

## FAQ

**What is OpenSEO?**

An open-source SEO platform covering keyword research, rank tracking, backlinks, competitor analysis, site audits and AI visibility. MIT-licensed, reading its data from DataForSEO with your own key, so there is no per-seat subscription.

**What does this Railway template deploy?**

Two services: `open-seo`, the application, and `gateway`, a Caddy reverse proxy holding HTTP basic auth and the public domain. The app gets a volume; nothing else is required.

**Why is there a proxy service in front of the app?**

OpenSEO's self-host mode has no login screen: it runs with a single injected admin user and expects to sit behind your own authentication. The gateway supplies that and keeps the app off the public internet, which is why the only credential you choose is a password.

**Why does the app service need a volume?**

The app runs as a Cloudflare Worker under workerd, and its database, key-value stores, object storage and workflow state all live on disk in one directory. The volume keeps projects, audits, keywords and rank history across redeploys.

**Do I need a DataForSEO key to try it?**

Not to deploy it. The app boots, the dashboard works, and the site audit crawler runs without one, because that crawler is part of the app. Keyword volumes, backlinks, domain overviews and rank checks query DataForSEO, so they wait on the key.

**How do I connect OpenSEO to Claude Code or Codex?**

Open the AI & MCP page and copy the MCP server URL — your public URL plus `/mcp`. Add it to your agent as a custom MCP server; the page carries per-agent instructions and an installer for OpenSEO's packaged SEO skills.



## Similar templates

- [Typesense vs Meilisearch](https://railway.com/deploy/typesense-vs-meilisearch) — self-hosted Typesense vs Meilisearch
- [Betterlytics](https://railway.com/deploy/betterlytics) — Betterlytics is a cookieless analytics platform GDPR-compliant.
- [Finance Tracker](https://railway.com/deploy/finance-tracker-1) — Private multi-user household finance ledger with budgets and CSV import.

Open this page in a browser: https://railway.com/deploy/open-seo
