feat: support direct IP service access
TallyNote release / linux-x64 (push) Successful in 7m17s

This commit is contained in:
Qiufeng
2026-09-01 20:57:56 +08:00
parent bcc63b8117
commit eeeec54d10
12 changed files with 365 additions and 27 deletions
+17 -2
View File
@@ -69,7 +69,8 @@ export function loadConfig() {
const installPrefix = path.resolve(process.env.TALLYNOTE_INSTALL_PREFIX ?? (updateStrategyRaw === "systemd" ? path.dirname(projectRoot) : projectRoot));
const host = process.env.TALLYNOTE_HOST ?? "127.0.0.1";
const port = integerEnv("TALLYNOTE_PORT", 3000, 1);
const publicOrigin = process.env.TALLYNOTE_PUBLIC_ORIGIN ?? `http://${host}:${port}`;
const originHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
const publicOrigin = process.env.TALLYNOTE_PUBLIC_ORIGIN ?? `http://${originHost}:${port}`;
let parsedOrigin: URL;
try {
parsedOrigin = new URL(publicOrigin);
@@ -88,7 +89,14 @@ export function loadConfig() {
const isProduction = process.env.NODE_ENV === "production" || process.env.TALLYNOTE_ENV === "production";
const cookieSecure = booleanEnv("TALLYNOTE_COOKIE_SECURE", parsedOrigin.protocol === "https:");
// Direct IP access is useful during a first deployment, but it is not
// encrypted. Keep this explicitly opt-in so a public install cannot
// accidentally expose session cookies over HTTP.
const allowInsecureHttp = booleanEnv("TALLYNOTE_ALLOW_INSECURE_HTTP", false);
const publicHost = parsedOrigin.hostname.replace(/^\[|\]$/g, "").toLowerCase();
if (["0.0.0.0", "::"].includes(publicHost)) {
throw new Error("TALLYNOTE_PUBLIC_ORIGIN 不能使用通配监听地址,请填写服务器 IP 或域名");
}
const localOrigin = ["127.0.0.1", "localhost", "::1"].includes(publicHost);
const appVersion = (() => {
try {
@@ -122,6 +130,7 @@ export function loadConfig() {
timezone,
trustProxy: trustProxyEnv(),
cookieSecure,
allowInsecureHttp,
appVersion,
updateMetadataUrl,
updateAllowedHosts,
@@ -166,7 +175,13 @@ export function loadConfig() {
isProduction,
};
if (!localOrigin && (parsedOrigin.protocol !== "https:" || !cookieSecure)) {
if (!localOrigin && parsedOrigin.protocol !== "https:" && !allowInsecureHttp) {
throw new Error("公网 HTTP 访问必须显式启用 TALLYNOTE_ALLOW_INSECURE_HTTP=true;生产环境建议使用 HTTPS");
}
if (!localOrigin && parsedOrigin.protocol !== "https:" && cookieSecure) {
throw new Error("HTTP public origin 不能启用安全 Cookie");
}
if (!localOrigin && parsedOrigin.protocol === "https:" && !cookieSecure) {
throw new Error("公网部署必须使用 HTTPS 并启用安全 Cookie");
}
if (parsedOrigin.protocol === "https:" && !cookieSecure) {