diff --git a/index.js b/index.js index 987711f..a636bcf 100644 --- a/index.js +++ b/index.js @@ -66,13 +66,30 @@ app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(express.static("public")); app.use(fileUpload()); + +// In production we sit behind an HTTPS-terminating proxy (Cloudflare/nginx) that +// forwards plain HTTP to Node, so trust its X-Forwarded-Proto header — otherwise +// Express thinks every request is HTTP and a Secure cookie would never be sent. +// Locally there's no proxy and no HTTPS, so Secure must stay off or login breaks. +const isProd = process.env.NODE_ENV === "production"; +if (isProd) app.set("trust proxy", 1); + app.use( session({ store: new SQLiteStore({ client: db, expired: { clear: true } }), secret: SESSION_SECRET, resave: false, saveUninitialized: true, - cookie: { secure: false }, + // Persistent login: without a maxAge this is a session cookie and iOS/PWAs + // drop it on their own schedule, logging people out at random. Browsers cap + // persistent cookies to ~400 days, so we set a long window and roll it + // forward on every request — visit within 400 days and you stay logged in. + rolling: true, + cookie: { + secure: isProd, // HTTPS-only in prod; off locally so http://localhost works + sameSite: "lax", + maxAge: 1000 * 60 * 60 * 24 * 400, + }, }), ); diff --git a/update-deployed.sh b/update-deployed.sh index 96c371e..c35dd27 100755 --- a/update-deployed.sh +++ b/update-deployed.sh @@ -106,6 +106,22 @@ else echo "SESSION_SECRET already present in $APP_DIR/.env" fi +# Production runs behind HTTPS; NODE_ENV=production flips on Secure cookies and +# trust-proxy in index.js. Set it idempotently so every deploy guarantees it. +if ! grep -Eq '^NODE_ENV=production$' .env; then + if grep -Eq '^NODE_ENV=' .env; then + ENV_TMP="$(mktemp)" + awk '/^NODE_ENV=/ { print "NODE_ENV=production"; next } { print }' .env >"$ENV_TMP" + cat "$ENV_TMP" >.env + rm -f "$ENV_TMP" + else + printf '\nNODE_ENV=production\n' >>.env + fi + echo "Set NODE_ENV=production in $APP_DIR/.env" +else + echo "NODE_ENV=production already present in $APP_DIR/.env" +fi + PM2_TARGET="" if command -v pm2 >/dev/null 2>&1; then PM2_TARGET="$(pm2 jlist 2>/dev/null | APP_DIR="$APP_DIR" node -e '