diff --git a/.env.example b/.env.example index dc686dc..bff168a 100644 --- a/.env.example +++ b/.env.example @@ -15,9 +15,11 @@ VITE_APP_ID=open-seo # # PORT=3001 # ------------------------------------------------------------- -# --- Docker self-hosting only (standalone local mode) --- +# --- Docker self-hosting only (local mode) --- # See SELF_HOSTING_DOCKER.md # 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. # BYPASS_GATEWAY_LOCAL_ONLY=true # 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. # 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. diff --git a/README.md b/README.md index 97cbfa7..9725b4d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ OpenSEO is an SEO tool for _the people_. If tools like Semrush or Ahrefs are too - [Community](#community) - [Pricing / Costs (Free + API costs)](#pricing--costs) - [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) - [Contributing](#contributing) - [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! -## Docker Self Hosting (Standalone OpenSEO) +## Docker Self Hosting Quickstart: 1. `cp .env.example .env` 2. Set `DATAFORSEO_API_KEY` in `.env` 3. `docker compose up` -4. Open `http://localhost:3001` +4. Open `http://localhost:` (default `3001`) For runtime details, caveats, and troubleshooting, see [`SELF_HOSTING_DOCKER.md`](./SELF_HOSTING_DOCKER.md). diff --git a/SELF_HOSTING_DOCKER.md b/SELF_HOSTING_DOCKER.md index 543cc87..bc0581e 100644 --- a/SELF_HOSTING_DOCKER.md +++ b/SELF_HOSTING_DOCKER.md @@ -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. @@ -32,7 +32,7 @@ Required: Optional: -- `OPENAI_API_KEY` +- `PORT` (defaults to `3001`) - `VITE_APP_ID` (defaults to `open-seo`) - `BYPASS_GATEWAY_LOCAL_ONLY=true` (Docker compose already sets this) @@ -44,7 +44,7 @@ docker compose up URL: -- OpenSEO: `http://localhost:3001` +- OpenSEO: `http://localhost:` (defaults to `3001`) Boot behavior: diff --git a/compose.yaml b/compose.yaml index cf37fe0..1b5231f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -5,22 +5,21 @@ services: dockerfile: self-host/Dockerfile.selfhost working_dir: /app environment: - - PORT=3001 + - PORT=${PORT:-3001} - BYPASS_GATEWAY_LOCAL_ONLY=true - VITE_APP_ID=${VITE_APP_ID:-open-seo} - - VITE_GATEWAY_URL=${VITE_GATEWAY_URL:-http://localhost:3001} - - GATEWAY_URL=${GATEWAY_URL:-http://localhost:3001} + - VITE_GATEWAY_URL=${VITE_GATEWAY_URL:-http://localhost:${PORT:-3001}} + - GATEWAY_URL=${GATEWAY_URL:-http://localhost:${PORT:-3001}} - DATAFORSEO_API_KEY=${DATAFORSEO_API_KEY} - - OPENAI_API_KEY=${OPENAI_API_KEY:-} - VITE_SHOW_DEVTOOLS=false command: [ "sh", "-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: - - "127.0.0.1:3001:3001" + - "127.0.0.1:${PORT:-3001}:${PORT:-3001}" volumes: - .:/app - open_seo_node_modules:/app/node_modules diff --git a/knip.jsonc b/knip.jsonc index dc80a9e..a63d875 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -8,8 +8,6 @@ "drizzle.config.ts", // DB index re-exports schema for convenience "src/db/index.ts", - // Docker self-host runtime entrypoint scripts - "self-host/scripts/*.mjs", ], "project": ["**/*.{js,mjs,ts,tsx}", "!src/routeTree.gen.ts"], "ignore": [ diff --git a/self-host/Dockerfile.gateway-selfhost b/self-host/Dockerfile.gateway-selfhost deleted file mode 100644 index bdaf80b..0000000 --- a/self-host/Dockerfile.gateway-selfhost +++ /dev/null @@ -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 diff --git a/self-host/scripts/download-archive.mjs b/self-host/scripts/download-archive.mjs deleted file mode 100644 index 22c5785..0000000 --- a/self-host/scripts/download-archive.mjs +++ /dev/null @@ -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 - -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 ", - ); - 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())); diff --git a/self-host/scripts/resolve-gateway-tag.mjs b/self-host/scripts/resolve-gateway-tag.mjs deleted file mode 100644 index 2880785..0000000 --- a/self-host/scripts/resolve-gateway-tag.mjs +++ /dev/null @@ -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);