feat(server): add HTTPS with self-signed certs

Default to HTTPS with optional loopback HTTP, generate/rotate self-signed certs via node-forge, and surface Local/Remote connection URLs. Update /api/meta schema, UI remote access overlay, and desktop shells to follow the new startup output.
This commit is contained in:
Shantur Rathore
2026-02-08 15:48:00 +00:00
parent 7eb1551e4b
commit 338a88fb5a
16 changed files with 866 additions and 225 deletions

View File

@@ -119,10 +119,18 @@ export class AuthManager {
reply.header("Set-Cookie", buildSessionCookie(this.cookieName, sessionId))
}
setSessionCookieWithOptions(reply: FastifyReply, sessionId: string, options?: { secure?: boolean }) {
reply.header("Set-Cookie", buildSessionCookie(this.cookieName, sessionId, options))
}
clearSessionCookie(reply: FastifyReply) {
reply.header("Set-Cookie", buildSessionCookie(this.cookieName, "", { maxAgeSeconds: 0 }))
}
clearSessionCookieWithOptions(reply: FastifyReply, options?: { secure?: boolean }) {
reply.header("Set-Cookie", buildSessionCookie(this.cookieName, "", { maxAgeSeconds: 0, ...options }))
}
private requireAuthStore(): AuthStore {
if (!this.authStore) {
throw new Error("Auth store is unavailable")
@@ -143,8 +151,11 @@ function resolvePath(filePath: string) {
return path.resolve(filePath)
}
function buildSessionCookie(name: string, value: string, options?: { maxAgeSeconds?: number }) {
function buildSessionCookie(name: string, value: string, options?: { maxAgeSeconds?: number; secure?: boolean }) {
const parts = [`${name}=${encodeURIComponent(value)}`, "HttpOnly", "Path=/", "SameSite=Lax"]
if (options?.secure) {
parts.push("Secure")
}
if (options?.maxAgeSeconds !== undefined) {
parts.push(`Max-Age=${Math.max(0, Math.floor(options.maxAgeSeconds))}`)
}