docs: Add better Cloudflare Hosting docs (#10)

* chore: bump @every-app/sdk to 0.1.14 for deploy install

* Add selfhosting to Cloudflare file

* Revise Cloudflare deployment instructions in README

Updated instructions for Cloudflare deployment and setup.

* docs: streamline self-hosting docs and split Cloudflare guide

* save
This commit is contained in:
Ben Senescu 2026-03-10 21:44:50 -04:00 committed by GitHub
parent e701988262
commit 991799932f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 149 additions and 153 deletions

155
README.md
View File

@ -1,11 +1,9 @@
# OpenSEO # OpenSEO
OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too expensive or bloated, OpenSEO is a pay by usage alternative that you actually control. OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too expensive or bloated, OpenSEO is a pay-as-you-go alternative that you actually control.
![OpenSEO demo (placeholder)](https://github.com/user-attachments/assets/6a928771-66ff-486b-b131-a54a3943985f) ![OpenSEO demo (placeholder)](https://github.com/user-attachments/assets/6a928771-66ff-486b-b131-a54a3943985f)
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/every-app/open-seo)
## Table of Contents ## Table of Contents
- [Why Use This](#why-use-this) - [Why Use This](#why-use-this)
@ -15,7 +13,7 @@ OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too
- [Pricing / Costs (Free + API costs)](#pricing--costs) - [Pricing / Costs (Free + API costs)](#pricing--costs)
- [DataForSEO API Key Setup](#dataforseo-api-key-setup) - [DataForSEO API Key Setup](#dataforseo-api-key-setup)
- [Self-hosting](#self-hosting) - [Self-hosting](#self-hosting)
- [Cloudflare Deployment + Access Setup](#cloudflare-deployment--access-setup) - [Cloudflare Self-Hosting](#cloudflare-self-hosting)
- [Docker Self Hosting](#docker-self-hosting) - [Docker Self Hosting](#docker-self-hosting)
- [Local Development](#local-development) - [Local Development](#local-development)
- [Contributing](#contributing) - [Contributing](#contributing)
@ -26,7 +24,7 @@ OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too
- Open source and self-hostable. - Open source and self-hostable.
- No subscriptions. - No subscriptions.
- Focused workflows instead of a giant, complex SEO suite. - Focused workflows instead of a giant, complex SEO suite.
- AI Native - Use your own tools like Claude Code / Cowork for more powerful AI features than what other platforms provide. - AI-native: use your own tools like Claude Code / Cowork for more powerful AI features than other platforms provide.
## Main SEO Workflows ## Main SEO Workflows
@ -41,6 +39,7 @@ OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too
Top priorities: Top priorities:
- Backlinks
- Rank tracking - Rank tracking
- AI content workflows - AI content workflows
@ -49,7 +48,7 @@ If something important is missing, please join the [Discord](https://discord.gg/
## Community ## Community
Email me: ben@everyapp.dev Email me: ben@everyapp.dev
Join discord to chat: [Discord](https://discord.gg/c9uGs3cFXr) Join Discord to chat: [Discord](https://discord.gg/c9uGs3cFXr)
Follow along for updates: Follow along for updates:
@ -69,7 +68,7 @@ For cost estimates, see [DataForSEO API Cost Reference](#seo-api-cost-reference)
## DataForSEO API Key Setup ## DataForSEO API Key Setup
OpenSEO use DataForSEO to get the SEO info. You need an API key to connect OpenSEO to the service. OpenSEO uses DataForSEO to fetch SEO data. You need an API key to connect OpenSEO to the service.
1. Go to [DataForSEO API Access](https://app.dataforseo.com/api-access). 1. Go to [DataForSEO API Access](https://app.dataforseo.com/api-access).
2. Request API credentials by email (`API key by email` or `API password by email`). 2. Request API credentials by email (`API key by email` or `API password by email`).
@ -88,71 +87,28 @@ printf '%s' 'YOUR_LOGIN:YOUR_PASSWORD' | base64
OpenSEO supports two self-hosting paths: OpenSEO supports two self-hosting paths:
- Cloudflare for hosting on the internet (Recommended).
- Docker for your homelab or local use. - Docker for your homelab or local use.
- Cloudflare for use across multiple devices or for your team.
If you already have Docker installed (or are willing to install it), that is the quickest way to test OpenSEO.
Use this quick guide: Use this quick guide:
- Choose Cloudflare when:
- You've never used Docker before.
- You want a more SaaS like experience.
- You want to use it from multiple devices or with teammates.
- You want support for more powerful features in the future like sharing public links to reports or site audits rendering your websites javascript.
- Choose Docker when: - Choose Docker when:
- You already have Docker installed and want to get setup most quickly. - You already have Docker installed and want to get set up quickly.
- You have a homelab setup. - You have a homelab setup.
- You only want to use OpenSEO locally on one device. - You only want to use OpenSEO locally on one device.
- Choose Cloudflare when:
## Cloudflare Deployment + Access Setup - You want a more SaaS like experience.
- You want to use it from multiple devices or with teammates.
You can use the Deploy button at the top of this README or run with Wrangler directly. - You want support for more powerful future features, such as sharing public links to reports or running site audits that render your website's JavaScript.
### 1) Deploy the Worker
Clicking this button will open a page to deploy OpenSEO in your Cloudflare account.
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/every-app/open-seo)
### 2) Set required environment variables
OpenSEO needs these vars in production:
- `DATAFORSEO_API_KEY`: base64-encoded `login:password` from DataForSEO.
- `AUTH_MODE=cloudflare_access`
- `TEAM_DOMAIN`: your Access team domain (for example `https://your-team.cloudflareaccess.com`).
- `POLICY_AUD`: Access Application Audience tag for your OpenSEO app.
You can set plain vars and secrets with Wrangler:
```sh
pnpm exec wrangler secret put DATAFORSEO_API_KEY
pnpm exec wrangler secret put POLICY_AUD
pnpm exec wrangler secret put TEAM_DOMAIN
pnpm exec wrangler secret put AUTH_MODE
```
You can also set these in Cloudflare Dashboard under Worker Settings.
### 3) Configure Cloudflare Access
In Cloudflare Zero Trust:
1. Create an Access application for your OpenSEO route/domain.
2. Add policy rules for the identities/groups allowed to access OpenSEO.
3. Ensure requests to your Worker include `cf-access-jwt-assertion`.
4. Copy values into OpenSEO config:
- Access team domain -> `TEAM_DOMAIN`
- Access app AUD tag -> `POLICY_AUD`
### 4) Validate setup
- Visit your OpenSEO URL.
- You should be prompted by Cloudflare Access if not signed in.
- After sign-in, the app should load normally.
- If config is missing, OpenSEO shows an in-app setup error that links back to this section.
## Docker Self Hosting ## Docker Self Hosting
Prerequisites:
- Install Docker: https://www.docker.com/products/docker-desktop/
Quickstart: Quickstart:
1. `cp .env.example .env` 1. `cp .env.example .env`
@ -160,7 +116,17 @@ Quickstart:
3. `docker compose up` 3. `docker compose up`
4. Open `http://localhost:<PORT>` (default `3001`) 4. Open `http://localhost:<PORT>` (default `3001`)
For runtime details, caveats, and troubleshooting, see [`SELF_HOSTING_DOCKER.md`](./SELF_HOSTING_DOCKER.md). For more info, see [`SELF_HOSTING_DOCKER.md`](./SELF_HOSTING_DOCKER.md).
## Cloudflare Self-Hosting
### Deploy the Worker
Clicking this button opens a page to deploy OpenSEO in your Cloudflare account. If you do not have an account yet, it will take you to account creation first (OpenSEO works great on the free plan).
Reference these docs while deploying since the Cloudflare UI doesn't indicate what steps you need to take: [`SELF_HOSTING_CLOUDFLARE.md`](./SELF_HOSTING_CLOUDFLARE.md).
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/every-app/open-seo)
## Local Development ## Local Development
@ -170,58 +136,30 @@ For runtime details, caveats, and troubleshooting, see [`SELF_HOSTING_DOCKER.md`
- [pnpm](https://pnpm.io/) - [pnpm](https://pnpm.io/)
- A DataForSEO account/API credentials - A DataForSEO account/API credentials
### Run Locally (Quick Test) ### Local Development Workflow
1. Copy env template:
```sh ```sh
cp .env.example .env.local cp .env.example .env.local
```
2. Install and run:
```sh
pnpm install pnpm install
# Initialize local DB schema (required on a fresh machine) # Run once per fresh local DB
pnpm run db:migrate:local pnpm run db:migrate:local
# This runs in local_noauth mode for local use and quick testing.
# Option 1
pnpm run dev
# Option 2 (Recommended)
# This log file makes it easier for your coding agent to debug.
mkdir .logs
touch .logs/dev-server.log
# This command uses portless, which is great for worktrees. It also pipes logs to that fixed file, which is helpful for agent debugging output.
pnpm dev:agents pnpm dev:agents
``` ```
`pnpm dev` runs on `http://localhost:3001` by default (or `PORT` from `.env.local`) in `AUTH_MODE=local_noauth`.
`pnpm dev:agents` runs through [portless](https://github.com/vercel-labs/portless) at `http://open-seo.localhost:1355` by default. `pnpm dev:agents` runs through [portless](https://github.com/vercel-labs/portless) at `http://open-seo.localhost:1355` by default.
When using a git worktree, [portless](https://github.com/vercel-labs/portless) prefixes the branch name, for example `http://feature-name.open-seo.localhost:1355`. When using a git worktree, [portless](https://github.com/vercel-labs/portless) prefixes the branch name, for example `http://feature-name.open-seo.localhost:1355`.
Running locally is the fastest way to test core flows.
### Local Development Workflow (for coding agents)
```sh
# This log file make it easier for your coding agent to debug.
mkdir .logs
touch .logs/dev-server.log
# Run once per fresh local DB
pnpm run db:migrate:local
# terminal 1: start once and keep running
pnpm dev:agents
```
- `pnpm dev:agents` mirrors output to `.logs/dev-server.log` (gitignored).
- The log file is overwritten on each run.
### Auth modes
- `AUTH_MODE=cloudflare_access` (default): validates Cloudflare Access JWTs (`cf-access-jwt-assertion`) using `TEAM_DOMAIN` + `POLICY_AUD`.
- `AUTH_MODE=local_noauth`: local trusted mode, no auth check, injects `admin@localhost`.
- `AUTH_MODE=hosted`: reserved for upcoming multi-tenant auth flow (not yet implemented).
Local scripts (`pnpm dev` and `pnpm dev:agents`) set `AUTH_MODE=local_noauth` automatically.
Use `AUTH_MODE=cloudflare_access pnpm dev` when you specifically want to test Access validation locally.
For Cloudflare deployments, ensure Cloudflare Access is enabled on your Worker route/domain and provide `TEAM_DOMAIN` + `POLICY_AUD` in environment variables.
### Database Commands ### Database Commands
Generate migration: Generate migration:
@ -236,6 +174,17 @@ Migrate local DB:
pnpm run db:migrate:local pnpm run db:migrate:local
``` ```
### Auth modes
- `AUTH_MODE=cloudflare_access` (default): validates Cloudflare Access JWTs (`cf-access-jwt-assertion`) using `TEAM_DOMAIN` + `POLICY_AUD`.
- `AUTH_MODE=local_noauth`: local trusted mode, no auth check, injects `admin@localhost`.
- `AUTH_MODE=hosted`: reserved for upcoming multi-tenant auth flow (not yet implemented).
Local scripts (`pnpm dev` and `pnpm dev:agents`) set `AUTH_MODE=local_noauth` automatically.
Use `AUTH_MODE=cloudflare_access pnpm dev` when you specifically want to test Access validation locally.
For Cloudflare deployments, ensure Cloudflare Access is enabled on your Worker route/domain and provide `TEAM_DOMAIN` + `POLICY_AUD` in environment variables.
## Contributing ## Contributing
Contributions are very welcome. Contributions are very welcome.

View File

@ -0,0 +1,85 @@
# Cloudflare Self-Hosting
This guide covers:
1. Initial setup after clicking Deploy to Cloudflare
2. How to update to the latest OpenSEO version
3. How to add teammates
## Initial setup
### 1) Deploy from GitHub
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/every-app/open-seo)
Click the deploy button, there are lots of fields on the deploy form, but you only need to do the below steps.
1. Connect your Git provider (GitHub/GitLab).
2. Leave the resource naming fields as default unless you have a reason to change them.
3. Click `Create and Deploy`.
4. Wait 1-2 minutes for deployment to finish.
### 2) Configure authentication and secrets
In the Cloudflare dashboard:
1. Go to `Compute` -> `Workers & Pages` -> your OpenSEO Worker.
2. Open `Settings`.
3. In `Domains & Routes`, enable `Cloudflare Access` for the `workers.dev` route.
4. Save the values shown by Cloudflare Access.
5. In `Variables & Secrets`, add:
- `POLICY_AUD` (from Access setup)
- `TEAM_DOMAIN` (domain from `JWKS_URL`, for example `https://your-team.cloudflareaccess.com`)
- `DATAFORSEO_API_KEY`
### 3) Validate setup
1. Open your Worker URL again.
2. Sign in with Cloudflare Access.
3. OpenSEO should load after login.
If login fails, re-check the three secrets and Access toggle.
## How to update to the latest OpenSEO version
If your repo was created from the Cloudflare Deploy button, use this flow.
### One-time setup
Run this once in your local repo:
```bash
git remote add upstream https://github.com/every-app/open-seo.git
git fetch upstream
```
### Update steps (use every time)
```bash
git fetch upstream
cp wrangler.jsonc wrangler.local.backup.jsonc
git checkout main
git reset --hard upstream/main
cp wrangler.local.backup.jsonc wrangler.jsonc
git add wrangler.jsonc
git commit -m "restore Cloudflare settings" || true
git push --force-with-lease origin main
```
Why this is needed:
- `wrangler.jsonc` has your Cloudflare resource IDs.
- The update step keeps your IDs while pulling the newest OpenSEO code.
## Give teammates access to OpenSEO
To let teammates sign in to OpenSEO, update your Cloudflare Access policy.
1. Open Cloudflare Zero Trust.
2. Go to Access -> Applications.
3. Open your OpenSEO application.
4. Edit the `Allow` policy.
5. Add teammate emails (or your company email domain / group).
6. Save.
After saving, teammates can open your OpenSEO URL and sign in through Cloudflare Access.

View File

@ -1,86 +1,48 @@
# Docker Self-Hosting # Docker Self-Hosting
This guide runs OpenSEO as a local service. Run OpenSEO locally with Docker.
In this mode, OpenSEO runs with `AUTH_MODE=local_noauth`, so request authentication is disabled and a local admin user (`admin@localhost`) is injected automatically. In Docker mode, OpenSEO uses `AUTH_MODE=local_noauth` (no auth checks, local admin user `admin@localhost`).
## Prerequisites ## Prerequisites
- Docker Desktop (or Docker Engine + Docker Compose) - Docker Desktop (or Docker Engine + Docker Compose)
## Security and runtime caveats ## Quickstart
This stack is local-first and uses dev runtimes to emulate Cloudflare Worker bindings.
- Do not expose these ports directly to the public internet.
- There is no built-in auth check in this mode.
- If you expose it beyond localhost, put it behind the same authentication layer you use for your other self-hosted services (or use the [Cloudflare deployment path](./README.md#cloudflare-deployment--access-setup)).
## 1) Configure env values
From the repository root:
```bash ```bash
cp .env.example .env cp .env.example .env
```
Set values as needed in `.env`.
Required:
- `DATAFORSEO_API_KEY`
Optional:
- `PORT` (defaults to `3001`)
- `AUTH_MODE=local_noauth` (Docker compose already sets this)
## 2) Start OpenSEO
```bash
docker compose up docker compose up
``` ```
URL: Set `DATAFORSEO_API_KEY` in `.env`, then open `http://localhost:<PORT>` (default `3001`).
- OpenSEO: `http://localhost:<PORT>` (defaults to `3001`) Optional env values:
Boot behavior: - `PORT` (defaults to `3001`)
- `AUTH_MODE=local_noauth` (already set in compose)
- Uses dependencies installed during image build. ## Common commands
- Applies local D1 migrations on start.
- Starts local dev runtime (Vite).
## Troubleshooting - Restart service after env changes:
- OpenSEO env values seem stale: restart OpenSEO:
```bash ```bash
docker compose up -d open-seo docker compose up -d open-seo
``` ```
- If migrations fail on first run, rebuild and retry: - Rebuild image (after dependency or Docker config changes):
```bash
docker compose down
docker compose up
```
If you update dependencies or Docker build config, force a rebuild:
```bash ```bash
docker compose up --build docker compose up --build
``` ```
## Stop and cleanup - Stop:
Stop stack:
```bash ```bash
docker compose down docker compose down
``` ```
Stop and remove Docker volumes: - Stop and remove volumes:
```bash ```bash
docker compose down -v docker compose down -v