joelniklaus's picture
joelniklaus HF Staff
deploy: 3804adc3edeea13240af7f334f11c3f9f046b73f
fc9f257 verified
Raw
History Blame Contribute Delete
6.68 kB
import { resolve } from "node:path";
import { z } from "zod";
const schema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]).default("production"),
PORT: z.coerce.number().int().min(1).max(65535).default(7860),
HARBOR_HF_NAMESPACE: z.string().min(1).max(160),
HARBOR_HF_BUCKET_ID: z.string().min(3).max(320),
HARBOR_HF_BUCKET_ROOT: z.string().min(1).default("/data"),
HARBOR_HF_STORE_MODE: z.enum(["bucket", "filesystem"]).optional(),
HARBOR_HF_PROJECTION_PATH: z.string().min(1).default("/tmp/harbor-hf/control.sqlite"),
HARBOR_HF_AUTH_PATH: z.string().min(1).default("/tmp/harbor-hf/auth.sqlite"),
HARBOR_HF_PROFILES_ROOT: z.string().min(1).default("./profiles"),
HARBOR_HF_CAPACITY_PROFILE_ALIAS: z.string().min(2).max(160).optional(),
HARBOR_HF_MAX_ACTIVE_JOBS: z.coerce.number().int().min(1).max(1024).default(16),
HARBOR_HF_TASK_IMAGE_MIRROR_REPOSITORY: z
.string()
.regex(
/^[a-z0-9]+(?:[.-][a-z0-9]+)*(?::[0-9]{1,5})?\/[a-z0-9]+(?:[._-][a-z0-9]+)*(?:\/[a-z0-9]+(?:[._-][a-z0-9]+)*)*$/,
)
.default("ghcr.io/huggingface/harbor-hf-trial-worker"),
HARBOR_HF_WEB_ROOT: z.string().min(1).default("./apps/control-web/dist"),
HARBOR_HF_AUTH_MODE: z.enum(["oauth", "development"]).default("oauth"),
HARBOR_HF_WRITE_MODE: z.enum(["disabled", "enabled"]).default("disabled"),
HARBOR_HF_PUBLIC_ORIGIN: z.string().url().optional(),
SPACE_HOST: z.string().min(1).optional(),
OAUTH_CLIENT_ID: z.string().min(1).optional(),
OAUTH_CLIENT_SECRET: z.string().min(1).optional(),
OAUTH_SCOPES: z.string().min(1).default("openid profile"),
OPENID_PROVIDER_URL: z.string().url().optional(),
HF_TOKEN: z.string().min(8).optional(),
HF_INFERENCE_TOKEN: z.string().min(8).optional(),
HARBOR_HF_RECONCILE_INTERVAL_MS: z.coerce
.number()
.int()
.min(100)
.max(60000)
.default(2000),
HARBOR_HF_SYNC_INTERVAL_MS: z.coerce
.number()
.int()
.min(1000)
.max(300000)
.default(30000),
HARBOR_HF_OBSERVE_INTERVAL_MS: z.coerce
.number()
.int()
.min(100)
.max(300000)
.default(5000),
HARBOR_HF_WORKER_RECEIPT_GRACE_MS: z.coerce
.number()
.int()
.min(0)
.max(300000)
.default(60000),
HARBOR_HF_SOURCE_REVISION: z.string().min(7).max(160).default("development"),
HARBOR_HF_BOOTSTRAP_OPERATOR_SUBJECTS: z.string().default(""),
});
export interface AppConfig {
node_env: "development" | "test" | "production";
port: number;
namespace: string;
bucket_id: string;
bucket_root: string;
store_mode: "bucket" | "filesystem";
projection_path: string;
auth_path: string;
profiles_root: string;
capacity_profile_alias: string | null;
max_active_jobs: number;
task_image_mirror_repository: string;
web_root: string;
auth_mode: "oauth" | "development";
write_mode: "disabled" | "enabled";
public_origin: string;
oauth: {
issuer: string;
client_id: string;
client_secret: string;
scopes: string;
callback_url: string;
session_ttl_seconds: number;
} | null;
hf_token: string | null;
hf_inference_token: string | null;
reconcile_interval_ms: number;
sync_interval_ms: number;
observe_interval_ms: number;
worker_receipt_grace_ms: number;
source_revision: string;
bootstrap_operator_subjects: string[];
}
function normalizePublicOrigin(value: string): string {
const url = new URL(value);
if (
!["http:", "https:"].includes(url.protocol) ||
url.username ||
url.password ||
url.pathname !== "/" ||
url.search ||
url.hash
)
throw new Error("public origin must contain only an HTTP or HTTPS origin");
return url.origin;
}
export function loadConfig(environment: NodeJS.ProcessEnv = process.env): AppConfig {
const parsed = schema.parse(environment);
if (parsed.NODE_ENV === "production" && parsed.HARBOR_HF_AUTH_MODE !== "oauth") {
throw new Error("production requires OAuth authentication");
}
const storeMode =
parsed.HARBOR_HF_STORE_MODE ??
(parsed.NODE_ENV === "production" ? "bucket" : "filesystem");
if (storeMode === "bucket" && !parsed.HF_TOKEN) {
throw new Error("Bucket-backed service requires HF_TOKEN");
}
if (parsed.HARBOR_HF_WRITE_MODE !== "disabled" && !parsed.HF_TOKEN) {
throw new Error("write-enabled service requires HF_TOKEN");
}
if (
parsed.HF_TOKEN &&
parsed.HF_INFERENCE_TOKEN &&
parsed.HF_TOKEN === parsed.HF_INFERENCE_TOKEN
) {
throw new Error("control and inference credentials must be distinct");
}
const publicOrigin = normalizePublicOrigin(
parsed.HARBOR_HF_PUBLIC_ORIGIN ??
(parsed.SPACE_HOST
? `https://${parsed.SPACE_HOST}`
: `http://127.0.0.1:${parsed.PORT}`),
);
let oauth: AppConfig["oauth"] = null;
if (parsed.HARBOR_HF_AUTH_MODE === "oauth") {
if (
!parsed.OAUTH_CLIENT_ID ||
!parsed.OAUTH_CLIENT_SECRET ||
!parsed.OPENID_PROVIDER_URL
) {
throw new Error("OAuth mode requires the Hugging Face OIDC environment");
}
oauth = {
issuer: parsed.OPENID_PROVIDER_URL,
client_id: parsed.OAUTH_CLIENT_ID,
client_secret: parsed.OAUTH_CLIENT_SECRET,
scopes: parsed.OAUTH_SCOPES,
callback_url: `${publicOrigin}/auth/callback`,
session_ttl_seconds: 12 * 60 * 60,
};
}
return {
node_env: parsed.NODE_ENV,
port: parsed.PORT,
namespace: parsed.HARBOR_HF_NAMESPACE,
bucket_id: parsed.HARBOR_HF_BUCKET_ID,
bucket_root: resolve(parsed.HARBOR_HF_BUCKET_ROOT),
store_mode: storeMode,
projection_path: resolve(parsed.HARBOR_HF_PROJECTION_PATH),
auth_path: resolve(parsed.HARBOR_HF_AUTH_PATH),
profiles_root: resolve(parsed.HARBOR_HF_PROFILES_ROOT),
capacity_profile_alias: parsed.HARBOR_HF_CAPACITY_PROFILE_ALIAS ?? null,
max_active_jobs: parsed.HARBOR_HF_MAX_ACTIVE_JOBS,
task_image_mirror_repository: parsed.HARBOR_HF_TASK_IMAGE_MIRROR_REPOSITORY,
web_root: resolve(parsed.HARBOR_HF_WEB_ROOT),
auth_mode: parsed.HARBOR_HF_AUTH_MODE,
write_mode: parsed.HARBOR_HF_WRITE_MODE,
public_origin: publicOrigin,
oauth,
hf_token: parsed.HF_TOKEN ?? null,
hf_inference_token: parsed.HF_INFERENCE_TOKEN ?? null,
reconcile_interval_ms: parsed.HARBOR_HF_RECONCILE_INTERVAL_MS,
sync_interval_ms: parsed.HARBOR_HF_SYNC_INTERVAL_MS,
observe_interval_ms: parsed.HARBOR_HF_OBSERVE_INTERVAL_MS,
worker_receipt_grace_ms: parsed.HARBOR_HF_WORKER_RECEIPT_GRACE_MS,
source_revision: parsed.HARBOR_HF_SOURCE_REVISION,
bootstrap_operator_subjects: parsed.HARBOR_HF_BOOTSTRAP_OPERATOR_SUBJECTS.split(",")
.map((item) => item.trim())
.filter(Boolean),
};
}