diff --git a/app/routes/_data.machines._index/route.tsx b/app/routes/_data.machines._index/route.tsx index 707c2e6..6c9b7d9 100644 --- a/app/routes/_data.machines._index/route.tsx +++ b/app/routes/_data.machines._index/route.tsx @@ -46,6 +46,7 @@ export async function loader({ request }: LoaderFunctionArgs) { users: users.users, magic, server: context.headscaleUrl, + publicServer: context.headscalePublicUrl, } } @@ -73,7 +74,10 @@ export default function Page() {

- + diff --git a/app/routes/_data.settings.auth-keys._index/route.tsx b/app/routes/_data.settings.auth-keys._index/route.tsx index 1fa34a0..5118bd6 100644 --- a/app/routes/_data.settings.auth-keys._index/route.tsx +++ b/app/routes/_data.settings.auth-keys._index/route.tsx @@ -102,7 +102,7 @@ export async function loader({ request }: LoaderFunctionArgs) { return { keys: preAuthKeys.flatMap(keys => keys.preAuthKeys), users: users.users, - server: context.headscaleUrl, + server: context.headscalePublicUrl ?? context.headscaleUrl, } } diff --git a/app/utils/config/headplane.ts b/app/utils/config/headplane.ts index 3bde49a..732b630 100644 --- a/app/utils/config/headplane.ts +++ b/app/utils/config/headplane.ts @@ -15,6 +15,7 @@ import log from '~/utils/log' export interface HeadplaneContext { debug: boolean headscaleUrl: string + headscalePublicUrl?: string cookieSecret: string integration: IntegrationFactory | undefined @@ -56,12 +57,18 @@ export async function loadContext(): Promise { const { config, contextData } = await checkConfig(path) let headscaleUrl = process.env.HEADSCALE_URL + let headscalePublicUrl = process.env.HEADSCALE_PUBLIC_URL + if (!headscaleUrl && !config) { throw new Error('HEADSCALE_URL not set') } if (config) { headscaleUrl = headscaleUrl ?? config.server_url + if (!headscalePublicUrl) { + // Fallback to the config value if the env var is not set + headscalePublicUrl = config.public_url + } } if (!headscaleUrl) { @@ -76,6 +83,7 @@ export async function loadContext(): Promise { context = { debug, headscaleUrl, + headscalePublicUrl, cookieSecret, integration: await loadIntegration(), config: contextData, @@ -84,6 +92,10 @@ export async function loadContext(): Promise { log.info('CTXT', 'Starting Headplane with Context') log.info('CTXT', 'HEADSCALE_URL: %s', headscaleUrl) + if (headscalePublicUrl) { + log.info('CTXT', 'HEADSCALE_PUBLIC_URL: %s', headscalePublicUrl) + } + log.info('CTXT', 'Integration: %s', context.integration?.name ?? 'None') log.info('CTXT', 'Config: %s', contextData.read ? `Found ${contextData.write ? '' : '(Read Only)'}` diff --git a/docs/Configuration.md b/docs/Configuration.md index 88d5001..5c52170 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -9,6 +9,7 @@ You can configure Headplane using environment variables. #### Optional Variables +- **`HEADSCALE_PUBLIC_URL`**: The public URL of your Headscale server (if different from `HEADSCALE_URL`). - **`DEBUG`**: Enable debug logging (default: `false`). - **`HOST`**: The host to bind the server to (default: `0.0.0.0`). - **`PORT`**: The port to bind the server to (default: `3000`).