Improve security and deployment flexibility for external access

Update README and application configurations to support reverse proxy setups, including TLS termination and proper cookie handling, and add an option to seed demo meetings.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c15da2be-cee7-4cbb-8d58-f9fcc3c38ed7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/FvHcc7z
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
riyadhafraa
2026-05-15 10:38:44 +00:00
parent fa31fb6374
commit 77f8096deb
5 changed files with 126 additions and 10 deletions
+39 -1
View File
@@ -13,6 +13,25 @@ const app: Express = express();
app.set("trust proxy", 1);
// Self-hosted deployments are commonly fronted by a TLS-terminating
// proxy that does NOT forward `X-Forwarded-Proto: https` to the
// upstream (e.g. `tailscale serve`, ngrok free tier, some Cloudflare
// Tunnel configs). Without that header, `req.secure` stays false and
// the session cookie (when marked `secure: true`) is silently dropped
// — login appears to succeed but the very next request is unauth'd.
//
// Setting `TRUST_PROXY_HTTPS=true` tells us to treat every incoming
// request as if it arrived over HTTPS. Only enable this when the
// edge proxy you control actually terminates TLS in front of Tx OS.
const trustProxyHttps =
(process.env.TRUST_PROXY_HTTPS ?? "").toLowerCase() === "true";
if (trustProxyHttps) {
app.use((req, _res, next) => {
req.headers["x-forwarded-proto"] = "https";
next();
});
}
app.use(
pinoHttp({
logger,
@@ -55,11 +74,30 @@ app.use(
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// The session cookie should only be marked `secure` when the user is
// actually reaching us over HTTPS. We derive that from PUBLIC_BASE_URL
// instead of NODE_ENV so a self-hosted production install that's only
// reachable over plain HTTP (e.g. internal LAN, no TLS yet) still
// works without operator surgery.
const publicBaseUrl = process.env.PUBLIC_BASE_URL ?? "";
const sessionCookieSecure =
publicBaseUrl.startsWith("https://") || trustProxyHttps;
export const sessionMiddleware = session({
store: new PgSession({
pool,
tableName: "user_sessions",
// Auto-create the session table on first boot. Drizzle's migrations
// intentionally exclude `user_sessions` (see lib/db/drizzle.config.ts)
// because the schema is owned by connect-pg-simple, not by us. Without
// this flag, the very first login on a fresh install 500s.
createTableIfMissing: true,
}),
// Honour `X-Forwarded-Proto` from upstream proxies when deciding
// whether to set the secure cookie. Combined with `app.set("trust
// proxy", 1)` above, this makes the cookie work end-to-end behind
// Caddy / nginx / Cloudflare / Tailscale.
proxy: true,
secret: process.env.SESSION_SECRET ?? (() => {
if (process.env.NODE_ENV === "production") {
throw new Error("SESSION_SECRET must be set in production");
@@ -69,7 +107,7 @@ export const sessionMiddleware = session({
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === "production",
secure: sessionCookieSecure,
httpOnly: true,
maxAge: 7 * 24 * 60 * 60 * 1000,
sameSite: "lax",