mirror of
https://github.com/tale/headplane.git
synced 2026-07-27 08:08:56 +00:00
30dd718d68
allows defining oidc config without enabling it
139 lines
4.1 KiB
TypeScript
139 lines
4.1 KiB
TypeScript
import { join } from "node:path";
|
|
import { exit, versions } from "node:process";
|
|
import { createHonoServer } from "react-router-hono-server/node";
|
|
|
|
import log from "~/utils/log";
|
|
|
|
import { loadIntegration } from "./config/integration";
|
|
import { loadConfig } from "./config/load";
|
|
import { createDbClient } from "./db/client.server";
|
|
import { createHeadscaleInterface } from "./headscale/api";
|
|
import { loadHeadscaleConfig } from "./headscale/config-loader";
|
|
import { createHeadplaneAgent } from "./hp-agent";
|
|
import { createSessionStorage } from "./web/sessions";
|
|
|
|
declare global {
|
|
const __PREFIX__: string;
|
|
const __VERSION__: string;
|
|
}
|
|
|
|
// MARK: Side-Effects
|
|
// This module contains a side-effect because everything running here
|
|
// exists for the lifetime of the process, making it appropriate.
|
|
log.info("server", "Running Node.js %s", versions.node);
|
|
let config: HeadplaneConfig;
|
|
|
|
try {
|
|
config = await loadConfig();
|
|
} catch (error) {
|
|
if (error instanceof ConfigError) {
|
|
log.error("server", "Unable to load configuration: %s", error.message);
|
|
}
|
|
|
|
exit(1);
|
|
}
|
|
|
|
const db = await createDbClient(join(config.server.data_path, "hp_persist.db"));
|
|
const agents = await createHeadplaneAgent(config.integration?.agent, config.headscale.url, db);
|
|
|
|
const hsApi = await createHeadscaleInterface(config.headscale.url, config.headscale.tls_cert_path);
|
|
|
|
// We also use this file to load anything needed by the react router code.
|
|
// These are usually per-request things that we need access to, like the
|
|
// helper that can issue and revoke cookies.
|
|
export type LoadContext = typeof appLoadContext;
|
|
|
|
import "react-router";
|
|
import { HeadplaneConfig } from "./config/config-schema";
|
|
import { ConfigError } from "./config/error";
|
|
import { createLazyOidcConnector } from "./web/oidc-connector";
|
|
|
|
declare module "react-router" {
|
|
interface AppLoadContext extends LoadContext {}
|
|
}
|
|
|
|
const appLoadContext = {
|
|
config,
|
|
hs: await loadHeadscaleConfig(
|
|
config.headscale.config_path,
|
|
config.headscale.config_strict,
|
|
config.headscale.dns_records_path,
|
|
),
|
|
|
|
// TODO: Better cookie options in config
|
|
sessions: await createSessionStorage({
|
|
secret: config.server.cookie_secret,
|
|
db,
|
|
oidcUsersFile: config.oidc?.user_storage_file,
|
|
cookie: {
|
|
name: "_hp_auth",
|
|
secure: config.server.cookie_secure,
|
|
maxAge: config.server.cookie_max_age,
|
|
domain: config.server.cookie_domain,
|
|
},
|
|
}),
|
|
|
|
hsApi,
|
|
agents,
|
|
integration: await loadIntegration(config.integration),
|
|
oidcConnector:
|
|
config.oidc && config.oidc.enabled !== false
|
|
? createLazyOidcConnector(
|
|
config.server.base_url,
|
|
config.oidc,
|
|
hsApi.getRuntimeClient(config.oidc.headscale_api_key),
|
|
)
|
|
: undefined,
|
|
db,
|
|
};
|
|
|
|
declare module "react-router" {
|
|
interface AppLoadContext extends LoadContext {}
|
|
}
|
|
|
|
export default createHonoServer({
|
|
overrideGlobalObjects: true,
|
|
port: config.server.port,
|
|
hostname: config.server.host,
|
|
beforeAll: async (app) => {
|
|
app.use(__PREFIX__, async (c) => {
|
|
return c.redirect(`${__PREFIX__}/`);
|
|
});
|
|
},
|
|
serveStaticOptions: {
|
|
publicAssets: {
|
|
// This is part of our monkey-patch for react-router-hono-server
|
|
// To see the first part, go to the patches/ directory.
|
|
rewriteRequestPath: (path) => path.replace(`${__PREFIX__}`, ""),
|
|
},
|
|
clientAssets: {
|
|
// This is part of our monkey-patch for react-router-hono-server
|
|
// To see the first part, go to the patches/ directory.
|
|
rewriteRequestPath: (path) => path.replace(`${__PREFIX__}`, ""),
|
|
},
|
|
},
|
|
|
|
// Only log in development mode
|
|
defaultLogger: import.meta.env.DEV,
|
|
getLoadContext() {
|
|
// TODO: This is the place where we can handle reverse proxy translation
|
|
// This is better than doing it in the OIDC client, since we can do it
|
|
// for all requests, not just OIDC ones.
|
|
return appLoadContext;
|
|
},
|
|
|
|
listeningListener(info) {
|
|
log.info("server", "Running on %s:%s", info.address, info.port);
|
|
},
|
|
});
|
|
|
|
process.on("SIGINT", () => {
|
|
log.info("server", "Received SIGINT, shutting down...");
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on("SIGTERM", () => {
|
|
log.info("server", "Received SIGTERM, shutting down...");
|
|
process.exit(0);
|
|
});
|