feat(scripts): free trusted HTTPS via sslip.io for public-IP remote i… (#460)

* feat(scripts): free trusted HTTPS via sslip.io for public-IP remote installs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: refactor setup scripts

* chore: generate sdk

* chore: fix messaging for setup_remote script

* fix: fix ffmpeg download url

* feat: centralise and simplify the url configuration

* fix: force script run as sudo

* fix: fix documentation

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Abhishek 2026-06-27 17:19:29 +05:30 committed by GitHub
parent 3309face2c
commit 78427817a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 838 additions and 392 deletions

View file

@ -5,6 +5,31 @@ export function getServerBackendUrl() {
return process.env.BACKEND_URL || 'http://api:8000';
}
/**
* Resolve the base URL the browser should use to reach the backend API.
*
* Precedence:
* 1. NEXT_PUBLIC_BACKEND_URL explicit build-time operator config, always wins.
* 2. backendApiEndpoint the URL the backend reports it is running on via /health
* (surfaced through AppConfigContext). This is the address the browser actually
* reaches the backend at; for a backend on a private IP it is that private IP.
* Unknown at module init, so createClientConfig seeds without it and
* AppConfigProvider upgrades the client once /health resolves.
* 3. window.location.origin same-origin public deployment.
*
* This is the browserAPI order. It is intentionally NOT tunnel-aware: the
* Cloudflare tunnel URL is only for externally-hosted consumers (telephony
* webhooks, MCP, external API triggers) that cannot reach a private IP see
* resolveWebhookBaseUrl.
*/
export function resolveBrowserBackendUrl(backendApiEndpoint?: string | null): string {
return (
process.env.NEXT_PUBLIC_BACKEND_URL ||
backendApiEndpoint ||
(typeof window !== 'undefined' ? window.location.origin : '')
);
}
export const createClientConfig: CreateClientConfig = (config) => {
// Use different URLs for server-side vs client-side
const isServer = typeof window === 'undefined';
@ -13,7 +38,10 @@ export const createClientConfig: CreateClientConfig = (config) => {
if (isServer) {
baseUrl = getServerBackendUrl();
} else {
baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL || window.location.origin;
// The backend-reported endpoint is not known yet at module init;
// AppConfigProvider upgrades the client base URL once /health reports it
// (when no explicit NEXT_PUBLIC_BACKEND_URL is configured).
baseUrl = resolveBrowserBackendUrl();
}
return {

16
ui/src/lib/webhookUrl.ts Normal file
View file

@ -0,0 +1,16 @@
/**
* Public base URL that external callers (telephony providers, webhook senders)
* should use to reach this deployment's API.
*
* Prefers the Cloudflare tunnel URL the backend reports via /health (set when the
* host has no public IP, so `window.location.origin` would be a private/LAN
* address an external caller can't reach), then a build-time configured backend
* URL, then the current origin (correct for a same-origin public deployment).
*/
export function resolveWebhookBaseUrl(tunnelUrl?: string | null): string {
return (
tunnelUrl ||
process.env.NEXT_PUBLIC_BACKEND_URL ||
(typeof window !== "undefined" ? window.location.origin : "")
);
}