Simplify Docker self-hosting configuration
This commit is contained in:
parent
2d01ce5196
commit
d490dde51f
@ -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.
|
||||||
|
|||||||
@ -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).
|
||||||
|
|
||||||
|
|||||||
@ -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:
|
||||||
|
|
||||||
|
|||||||
11
compose.yaml
11
compose.yaml
@ -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
|
||||||
|
|||||||
@ -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": [
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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()));
|
|
||||||
@ -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);
|
|
||||||
Loading…
x
Reference in New Issue
Block a user