mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 22:32:12 +03:00
feat: enhance runtime port management and configuration
- Updated .env.example to include optional production ports for API and dashboard. - Modified docker-compose files to utilize dynamic port configuration. - Introduced runtime-env.mjs for centralized port resolution and environment variable management. - Refactored run-next.mjs and run-standalone.mjs to leverage new runtime port handling. - Enhanced route.ts and apiBridgeServer.ts to utilize dynamic ports for improved API integration. - Updated OAuth configuration to reflect changes in port management.
This commit is contained in:
@@ -26,9 +26,12 @@ SQLITE_CLEAN_LEGACY_FILES=true
|
||||
# Canonical/base port (keeps backward compatibility)
|
||||
PORT=20128
|
||||
# Optional split ports:
|
||||
# API_PORT=20128
|
||||
# API_PORT=20129
|
||||
# API_HOST=0.0.0.0
|
||||
# DASHBOARD_PORT=20128
|
||||
# Optional Docker production host publish ports:
|
||||
# PROD_DASHBOARD_PORT=20130
|
||||
# PROD_API_PORT=20131
|
||||
NODE_ENV=production
|
||||
INSTANCE_NAME=omniroute
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ COPY --from=builder /app/public ./public
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/scripts/run-standalone.mjs ./run-standalone.mjs
|
||||
COPY --from=builder /app/scripts/runtime-env.mjs ./runtime-env.mjs
|
||||
|
||||
EXPOSE 20128
|
||||
|
||||
|
||||
@@ -67,12 +67,12 @@ function parsePort(value, fallback) {
|
||||
let port = parsePort(process.env.PORT || "20128", 20128);
|
||||
const portIdx = args.indexOf("--port");
|
||||
if (portIdx !== -1 && args[portIdx + 1]) {
|
||||
const parsed = parseInt(args[portIdx + 1], 10);
|
||||
if (isNaN(parsed)) {
|
||||
const cliPort = parsePort(args[portIdx + 1], null);
|
||||
if (cliPort === null) {
|
||||
console.error("\x1b[31m✖ Invalid port number\x1b[0m");
|
||||
process.exit(1);
|
||||
}
|
||||
port = parsed;
|
||||
port = cliPort;
|
||||
}
|
||||
|
||||
const apiPort = parsePort(process.env.API_PORT || String(port), port);
|
||||
|
||||
@@ -22,11 +22,15 @@ services:
|
||||
env_file: .env
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=20128
|
||||
- PORT=${PORT:-20128}
|
||||
- DASHBOARD_PORT=${DASHBOARD_PORT:-${PORT:-20128}}
|
||||
- API_PORT=${API_PORT:-20129}
|
||||
- API_HOST=${API_HOST:-0.0.0.0}
|
||||
- HOSTNAME=0.0.0.0
|
||||
- DATA_DIR=/app/data
|
||||
ports:
|
||||
- "20130:20128"
|
||||
- "${PROD_DASHBOARD_PORT:-20130}:${DASHBOARD_PORT:-${PORT:-20128}}"
|
||||
- "${PROD_API_PORT:-20131}:${API_PORT:-20129}"
|
||||
volumes:
|
||||
- omniroute-prod-data:/app/data
|
||||
healthcheck:
|
||||
|
||||
@@ -20,6 +20,10 @@ x-common: &common
|
||||
env_file: .env
|
||||
environment:
|
||||
- DATA_DIR=/app/data # Must match the volume mount below
|
||||
- PORT=${PORT:-20128}
|
||||
- DASHBOARD_PORT=${DASHBOARD_PORT:-${PORT:-20128}}
|
||||
- API_PORT=${API_PORT:-20129}
|
||||
- API_HOST=${API_HOST:-0.0.0.0}
|
||||
volumes:
|
||||
- omniroute-data:/app/data
|
||||
healthcheck:
|
||||
@@ -45,7 +49,8 @@ services:
|
||||
target: runner-base
|
||||
image: omniroute:base
|
||||
ports:
|
||||
- "${PORT:-20128}:20128"
|
||||
- "${DASHBOARD_PORT:-${PORT:-20128}}:${DASHBOARD_PORT:-${PORT:-20128}}"
|
||||
- "${API_PORT:-20129}:${API_PORT:-20129}"
|
||||
profiles:
|
||||
- base
|
||||
|
||||
@@ -58,7 +63,8 @@ services:
|
||||
target: runner-cli
|
||||
image: omniroute:cli
|
||||
ports:
|
||||
- "${PORT:-20128}:20128"
|
||||
- "${DASHBOARD_PORT:-${PORT:-20128}}:${DASHBOARD_PORT:-${PORT:-20128}}"
|
||||
- "${API_PORT:-20129}:${API_PORT:-20129}"
|
||||
profiles:
|
||||
- cli
|
||||
|
||||
@@ -71,8 +77,14 @@ services:
|
||||
target: runner-base
|
||||
image: omniroute:base
|
||||
ports:
|
||||
- "${PORT:-20128}:20128"
|
||||
- "${DASHBOARD_PORT:-${PORT:-20128}}:${DASHBOARD_PORT:-${PORT:-20128}}"
|
||||
- "${API_PORT:-20129}:${API_PORT:-20129}"
|
||||
environment:
|
||||
- DATA_DIR=/app/data
|
||||
- PORT=${PORT:-20128}
|
||||
- DASHBOARD_PORT=${DASHBOARD_PORT:-${PORT:-20128}}
|
||||
- API_PORT=${API_PORT:-20129}
|
||||
- API_HOST=${API_HOST:-0.0.0.0}
|
||||
- CLI_MODE=host
|
||||
- CLI_EXTRA_PATHS=/host-local/bin:/host-node/bin
|
||||
- CLI_CONFIG_HOME=/host-home
|
||||
|
||||
@@ -1,41 +1,22 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
function parsePort(value, fallback) {
|
||||
const parsed = Number.parseInt(String(value), 10);
|
||||
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;
|
||||
}
|
||||
import {
|
||||
resolveRuntimePorts,
|
||||
withRuntimePortEnv,
|
||||
spawnWithForwardedSignals,
|
||||
} from "./runtime-env.mjs";
|
||||
|
||||
const mode = process.argv[2] === "start" ? "start" : "dev";
|
||||
|
||||
const basePort = parsePort(process.env.PORT || "20128", 20128);
|
||||
const apiPort = parsePort(process.env.API_PORT || String(basePort), basePort);
|
||||
const dashboardPort = parsePort(process.env.DASHBOARD_PORT || String(basePort), basePort);
|
||||
const runtimePorts = resolveRuntimePorts();
|
||||
const { dashboardPort } = runtimePorts;
|
||||
|
||||
const args = ["./node_modules/next/dist/bin/next", mode, "--port", String(dashboardPort)];
|
||||
if (mode === "dev") {
|
||||
args.splice(2, 0, "--webpack");
|
||||
}
|
||||
|
||||
const child = spawn(process.execPath, args, {
|
||||
spawnWithForwardedSignals(process.execPath, args, {
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
OMNIROUTE_PORT: String(basePort),
|
||||
PORT: String(dashboardPort),
|
||||
DASHBOARD_PORT: String(dashboardPort),
|
||||
API_PORT: String(apiPort),
|
||||
},
|
||||
env: withRuntimePortEnv(process.env, runtimePorts),
|
||||
});
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
process.on("SIGINT", () => child.kill("SIGINT"));
|
||||
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
||||
|
||||
@@ -1,34 +1,14 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawn } from "node:child_process";
|
||||
import {
|
||||
resolveRuntimePorts,
|
||||
withRuntimePortEnv,
|
||||
spawnWithForwardedSignals,
|
||||
} from "./runtime-env.mjs";
|
||||
|
||||
function parsePort(value, fallback) {
|
||||
const parsed = Number.parseInt(String(value), 10);
|
||||
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;
|
||||
}
|
||||
const runtimePorts = resolveRuntimePorts();
|
||||
|
||||
const basePort = parsePort(process.env.PORT || "20128", 20128);
|
||||
const apiPort = parsePort(process.env.API_PORT || String(basePort), basePort);
|
||||
const dashboardPort = parsePort(process.env.DASHBOARD_PORT || String(basePort), basePort);
|
||||
|
||||
const child = spawn("node", ["server.js"], {
|
||||
spawnWithForwardedSignals("node", ["server.js"], {
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
OMNIROUTE_PORT: String(basePort),
|
||||
PORT: String(dashboardPort),
|
||||
DASHBOARD_PORT: String(dashboardPort),
|
||||
API_PORT: String(apiPort),
|
||||
},
|
||||
env: withRuntimePortEnv(process.env, runtimePorts),
|
||||
});
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
process.on("SIGINT", () => child.kill("SIGINT"));
|
||||
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
||||
|
||||
43
scripts/runtime-env.mjs
Normal file
43
scripts/runtime-env.mjs
Normal file
@@ -0,0 +1,43 @@
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
export function parsePort(value, fallback) {
|
||||
const parsed = Number.parseInt(String(value), 10);
|
||||
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;
|
||||
}
|
||||
|
||||
export function resolveRuntimePorts() {
|
||||
const basePort = parsePort(process.env.PORT || "20128", 20128);
|
||||
const apiPort = parsePort(process.env.API_PORT || String(basePort), basePort);
|
||||
const dashboardPort = parsePort(process.env.DASHBOARD_PORT || String(basePort), basePort);
|
||||
|
||||
return { basePort, apiPort, dashboardPort };
|
||||
}
|
||||
|
||||
export function withRuntimePortEnv(env, runtimePorts) {
|
||||
const { basePort, apiPort, dashboardPort } = runtimePorts;
|
||||
|
||||
return {
|
||||
...env,
|
||||
OMNIROUTE_PORT: String(basePort),
|
||||
PORT: String(dashboardPort),
|
||||
DASHBOARD_PORT: String(dashboardPort),
|
||||
API_PORT: String(apiPort),
|
||||
};
|
||||
}
|
||||
|
||||
export function spawnWithForwardedSignals(command, args, options = {}) {
|
||||
const child = spawn(command, args, options);
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
return;
|
||||
}
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
|
||||
process.on("SIGINT", () => child.kill("SIGINT"));
|
||||
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
||||
|
||||
return child;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import { getRuntimePorts } from "@/lib/runtime/ports";
|
||||
|
||||
/**
|
||||
* POST /api/cli-tools/guide-settings/:toolId
|
||||
@@ -37,6 +38,7 @@ export async function POST(request, { params }) {
|
||||
* Merges with existing config if present.
|
||||
*/
|
||||
async function saveContinueConfig({ baseUrl, apiKey, model }) {
|
||||
const { apiPort } = getRuntimePorts();
|
||||
const configPath = path.join(os.homedir(), ".continue", "config.json");
|
||||
const configDir = path.dirname(configPath);
|
||||
|
||||
@@ -82,8 +84,8 @@ async function saveContinueConfig({ baseUrl, apiKey, model }) {
|
||||
(m.omnirouteManaged === true ||
|
||||
normalizeApiBase(m.apiBase) === normalizedBaseUrl.toLowerCase() ||
|
||||
normalizeApiBase(m.apiBase).includes("omniroute") ||
|
||||
normalizeApiBase(m.apiBase).includes("localhost:20128") ||
|
||||
normalizeApiBase(m.apiBase).includes("127.0.0.1:20128") ||
|
||||
normalizeApiBase(m.apiBase).includes(`localhost:${apiPort}`) ||
|
||||
normalizeApiBase(m.apiBase).includes(`127.0.0.1:${apiPort}`) ||
|
||||
String(m.apiKey || "")
|
||||
.toLowerCase()
|
||||
.includes("sk_omniroute"))
|
||||
|
||||
@@ -36,15 +36,21 @@ function proxyRequest(req: IncomingMessage, res: ServerResponse, dashboardPort:
|
||||
if (res.headersSent) return;
|
||||
res.writeHead(502, { "content-type": "application/json" });
|
||||
res.end(
|
||||
JSON.stringify({ error: "api_bridge_unavailable", detail: String(error.message || error) })
|
||||
JSON.stringify({
|
||||
error: "api_bridge_unavailable",
|
||||
detail: String(error.message || error),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
req.on("aborted", () => {
|
||||
targetReq.destroy();
|
||||
});
|
||||
|
||||
req.pipe(targetReq);
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
var __omnirouteApiBridgeStarted: boolean | undefined;
|
||||
}
|
||||
|
||||
@@ -54,7 +60,7 @@ export function initApiBridgeServer(): void {
|
||||
const { apiPort, dashboardPort } = getRuntimePorts();
|
||||
if (apiPort === dashboardPort) return;
|
||||
|
||||
const host = process.env.API_HOST || "0.0.0.0";
|
||||
const host = process.env.API_HOST || "127.0.0.1";
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
const rawUrl = req.url || "/";
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* with the running OmniRoute server when saving tokens.
|
||||
*/
|
||||
|
||||
import { getRuntimePorts } from "@/lib/runtime/ports";
|
||||
|
||||
interface ServerCredentials {
|
||||
server: string;
|
||||
token: string;
|
||||
@@ -12,11 +14,8 @@ interface ServerCredentials {
|
||||
}
|
||||
|
||||
function getDefaultApiServer() {
|
||||
const basePort = Number.parseInt(process.env.OMNIROUTE_PORT || process.env.PORT || "20128", 10);
|
||||
const fallbackPort = Number.isFinite(basePort) ? basePort : 20128;
|
||||
const apiPort = Number.parseInt(process.env.API_PORT || String(fallbackPort), 10);
|
||||
const effectivePort = Number.isFinite(apiPort) ? apiPort : fallbackPort;
|
||||
return `http://localhost:${effectivePort}`;
|
||||
const { dashboardPort } = getRuntimePorts();
|
||||
return `http://localhost:${dashboardPort}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user