Simplify Docker self-hosting configuration

This commit is contained in:
Ben Senescu 2026-03-09 23:37:58 -04:00
parent 2d01ce5196
commit d490dde51f
8 changed files with 16 additions and 82 deletions

View File

@ -15,9 +15,11 @@ VITE_APP_ID=open-seo
# # PORT=3001 # # PORT=3001
# ------------------------------------------------------------- # -------------------------------------------------------------
# --- Docker self-hosting only (standalone local mode) --- # --- Docker self-hosting only (local mode) ---
# See SELF_HOSTING_DOCKER.md # See SELF_HOSTING_DOCKER.md
# Docker compose runs with BYPASS_GATEWAY_LOCAL_ONLY=true. # Docker compose runs with BYPASS_GATEWAY_LOCAL_ONLY=true.
# Optional host/container port (defaults to 3001):
# PORT=3001
# Optional in .env because compose already sets it. # Optional in .env because compose already sets it.
# BYPASS_GATEWAY_LOCAL_ONLY=true # BYPASS_GATEWAY_LOCAL_ONLY=true
# Optional override (defaults to open-seo): # Optional override (defaults to open-seo):
@ -26,4 +28,4 @@ VITE_APP_ID=open-seo
# # See README.md for instructions for how to get this. # # See README.md for instructions for how to get this.
# DATAFORSEO_API_KEY= # DATAFORSEO_API_KEY=
# Legacy gateway auth keys are not needed in standalone Docker mode. # Legacy gateway auth keys are not needed in Docker self-host mode.

View File

@ -12,7 +12,7 @@ OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too
- [Community](#community) - [Community](#community)
- [Pricing / Costs (Free + API costs)](#pricing--costs) - [Pricing / Costs (Free + API costs)](#pricing--costs)
- [Self Hosting (Deploy on Cloudflare) \[5-10 minutes\]](#self-hosting-deploy-on-cloudflare-5-10-minutes) - [Self Hosting (Deploy on Cloudflare) \[5-10 minutes\]](#self-hosting-deploy-on-cloudflare-5-10-minutes)
- [Docker Self Hosting (Standalone OpenSEO)](#docker-self-hosting-standalone-openseo) - [Docker Self Hosting](#docker-self-hosting)
- [Local Development](#local-development) - [Local Development](#local-development)
- [Contributing](#contributing) - [Contributing](#contributing)
- [SEO API Cost Reference](#seo-api-cost-reference) - [SEO API Cost Reference](#seo-api-cost-reference)
@ -144,14 +144,14 @@ npx wrangler secret put DATAFORSEO_API_KEY
Now you're all set! Go back to the gateway, click on the OpenSEO app, and start getting better at SEO! Now you're all set! Go back to the gateway, click on the OpenSEO app, and start getting better at SEO!
## Docker Self Hosting (Standalone OpenSEO) ## Docker Self Hosting
Quickstart: Quickstart:
1. `cp .env.example .env` 1. `cp .env.example .env`
2. Set `DATAFORSEO_API_KEY` in `.env` 2. Set `DATAFORSEO_API_KEY` in `.env`
3. `docker compose up` 3. `docker compose up`
4. Open `http://localhost:3001` 4. Open `http://localhost:<PORT>` (default `3001`)
For runtime details, caveats, and troubleshooting, see [`SELF_HOSTING_DOCKER.md`](./SELF_HOSTING_DOCKER.md). For runtime details, caveats, and troubleshooting, see [`SELF_HOSTING_DOCKER.md`](./SELF_HOSTING_DOCKER.md).

View File

@ -1,6 +1,6 @@
# Docker Self-Hosting (Standalone OpenSEO) # Docker Self-Hosting
This guide runs OpenSEO as a standalone local service without Every App Gateway. This guide runs OpenSEO as a local service without Every App Gateway.
In this mode, OpenSEO runs with `BYPASS_GATEWAY_LOCAL_ONLY=true`, so authentication and Gateway-managed user accounts are disabled. In this mode, OpenSEO runs with `BYPASS_GATEWAY_LOCAL_ONLY=true`, so authentication and Gateway-managed user accounts are disabled.
@ -32,7 +32,7 @@ Required:
Optional: Optional:
- `OPENAI_API_KEY` - `PORT` (defaults to `3001`)
- `VITE_APP_ID` (defaults to `open-seo`) - `VITE_APP_ID` (defaults to `open-seo`)
- `BYPASS_GATEWAY_LOCAL_ONLY=true` (Docker compose already sets this) - `BYPASS_GATEWAY_LOCAL_ONLY=true` (Docker compose already sets this)
@ -44,7 +44,7 @@ docker compose up
URL: URL:
- OpenSEO: `http://localhost:3001` - OpenSEO: `http://localhost:<PORT>` (defaults to `3001`)
Boot behavior: Boot behavior:

View File

@ -5,22 +5,21 @@ services:
dockerfile: self-host/Dockerfile.selfhost dockerfile: self-host/Dockerfile.selfhost
working_dir: /app working_dir: /app
environment: environment:
- PORT=3001 - PORT=${PORT:-3001}
- BYPASS_GATEWAY_LOCAL_ONLY=true - BYPASS_GATEWAY_LOCAL_ONLY=true
- VITE_APP_ID=${VITE_APP_ID:-open-seo} - VITE_APP_ID=${VITE_APP_ID:-open-seo}
- VITE_GATEWAY_URL=${VITE_GATEWAY_URL:-http://localhost:3001} - VITE_GATEWAY_URL=${VITE_GATEWAY_URL:-http://localhost:${PORT:-3001}}
- GATEWAY_URL=${GATEWAY_URL:-http://localhost:3001} - GATEWAY_URL=${GATEWAY_URL:-http://localhost:${PORT:-3001}}
- DATAFORSEO_API_KEY=${DATAFORSEO_API_KEY} - DATAFORSEO_API_KEY=${DATAFORSEO_API_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
- VITE_SHOW_DEVTOOLS=false - VITE_SHOW_DEVTOOLS=false
command: command:
[ [
"sh", "sh",
"-c", "-c",
"pnpm run db:migrate:local && pnpm exec vite dev --host 0.0.0.0 --port 3001", "pnpm run db:migrate:local && pnpm exec vite dev --host 0.0.0.0 --port ${PORT:-3001}",
] ]
ports: ports:
- "127.0.0.1:3001:3001" - "127.0.0.1:${PORT:-3001}:${PORT:-3001}"
volumes: volumes:
- .:/app - .:/app
- open_seo_node_modules:/app/node_modules - open_seo_node_modules:/app/node_modules

View File

@ -8,8 +8,6 @@
"drizzle.config.ts", "drizzle.config.ts",
// DB index re-exports schema for convenience // DB index re-exports schema for convenience
"src/db/index.ts", "src/db/index.ts",
// Docker self-host runtime entrypoint scripts
"self-host/scripts/*.mjs",
], ],
"project": ["**/*.{js,mjs,ts,tsx}", "!src/routeTree.gen.ts"], "project": ["**/*.{js,mjs,ts,tsx}", "!src/routeTree.gen.ts"],
"ignore": [ "ignore": [

View File

@ -1,22 +0,0 @@
FROM node:22
ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME:$PATH
WORKDIR /app
RUN corepack enable
COPY self-host/scripts/resolve-gateway-tag.mjs self-host/scripts/download-archive.mjs /tmp/scripts/
ARG GATEWAY_RELEASE_TAG=
RUN gateway_tag=$(node /tmp/scripts/resolve-gateway-tag.mjs) \
&& echo "Downloading Gateway source for tag: ${gateway_tag}" \
&& node /tmp/scripts/download-archive.mjs "https://github.com/every-app/every-app/archive/refs/tags/${gateway_tag}.tar.gz" /tmp/every-app-source.tar.gz \
&& mkdir -p /tmp/every-app-source \
&& tar -xzf /tmp/every-app-source.tar.gz -C /tmp/every-app-source \
&& source_root=$(find /tmp/every-app-source -mindepth 1 -maxdepth 1 -type d | head -n 1) \
&& cp -R "$source_root/apps/every-app-gateway/." /app \
&& rm -rf /tmp/every-app-source /tmp/every-app-source.tar.gz /tmp/scripts
RUN pnpm install --frozen-lockfile

View File

@ -1,20 +0,0 @@
// Downloads a file from a URL and writes it to a local path.
// Usage: node self-host/scripts/download-archive.mjs <url> <output-path>
import { writeFileSync } from "node:fs";
const [url, outputPath] = process.argv.slice(2);
if (!url || !outputPath) {
console.error(
"Usage: node self-host/scripts/download-archive.mjs <url> <output-path>",
);
process.exit(1);
}
const res = await fetch(url);
if (!res.ok) {
throw new Error("Failed to download source archive: " + String(res.status));
}
writeFileSync(outputPath, Buffer.from(await res.arrayBuffer()));

View File

@ -1,23 +0,0 @@
// Resolves the gateway release tag to use for the selfhost Docker build.
// If GATEWAY_RELEASE_TAG is set, prints it and exits.
// Otherwise fetches the latest release tag from the GitHub API.
const tag = process.env.GATEWAY_RELEASE_TAG;
if (tag) {
process.stdout.write(tag);
process.exit(0);
}
const res = await fetch(
"https://api.github.com/repos/every-app/every-app/releases/latest",
);
if (!res.ok) {
throw new Error("Failed to resolve latest release: " + String(res.status));
}
const parsed = await res.json();
if (!parsed.tag_name) {
throw new Error("Missing tag_name in latest release payload");
}
process.stdout.write(parsed.tag_name);