15a8ab41fd
Adds a third value for the COOKIE_SECURE environment variable that decides the cookie Secure flag per-request based on req.secure. This unblocks a common self-hosted setup where the same PicPeak deployment is reachable over both HTTPS (via reverse proxy) and plain HTTP (e.g. LAN access at http://192.168.x.x:3001). Behavior unset - legacy default: follows NODE_ENV (production=true, dev=false) true - always set Secure (unchanged) false - never set Secure (unchanged) auto - NEW: use req.secure per request. In practice this means Secure on HTTPS requests (when X-Forwarded-Proto: https reaches Express via a trusted proxy) and no Secure flag on plain HTTP requests. The existing trust proxy config (`app.set('trust proxy', 'loopback, linklocal, uniquelocal')` in server.js) means X-Forwarded-Proto is honored when forwarded from local/private-network proxies, which covers Docker network setups and most self-hosted deployments behind NPM, Traefik, or Caddy. auto is strictly opt-in. The default behavior is unchanged, so existing users see no difference. A follow-up release can consider promoting auto to the default after real-world feedback. Also fixed (latent bug, benefits everyone) Cookie clear operations (clearAdminAuthCookie, clearGalleryAuthCookies) previously wrote the same `secure` attribute as the set path. When a cookie was set with Secure=true over HTTPS and the clear request came over HTTP (or vice versa under auto mode), some browsers would reject the Set-Cookie delete header, leaving the cookie in place. Browsers match cookies by (name, domain, path) for deletion and don't care about Secure, so the new buildClearCookieOptions() helper simply omits the secure attribute. Implementation - secureCookie string is replaced by secureCookieMode which can hold true, false, or 'auto'. - New resolveSecureFlag(res) returns the boolean for a specific response, delegating to res.req.secure when in auto mode. - buildCookieBaseOptions and buildCookieOptionsWithExpiry now take res and pass it through. - New buildClearCookieOptions() deliberately omits `secure`. - setAdminAuthCookie / setGalleryAuthCookies / clearAdminAuthCookie / clearGalleryAuthCookies all updated to thread res where needed. Public signatures unchanged — every caller already has res in scope. Testing Verified against a real Express instance inside the backend container with trust proxy configured, covering: - (unset) + NODE_ENV=production -> secure: true (legacy) - (unset) + NODE_ENV=development -> secure: false (legacy) - COOKIE_SECURE=true + req.secure=false -> secure: true (literal wins) - COOKIE_SECURE=false + req.secure=true -> secure: false (literal wins) - COOKIE_SECURE=auto + X-Forwarded-Proto: https -> secure: true - COOKIE_SECURE=auto + plain HTTP -> secure: false - clearCookie always omits the secure attribute Documentation Added a COOKIE_SECURE block to both .env.example files (root for docker-compose, backend/.env.example for native install) explaining the four values, when to use auto, and the two requirements (proxy must forward X-Forwarded-Proto, proxy IP must be in the trust list). Also documented COOKIE_SAMESITE and COOKIE_DOMAIN alongside, which were previously undocumented.
93 lines
3.1 KiB
Bash
93 lines
3.1 KiB
Bash
# Backend Environment Variables Example
|
|
# Copy this file to .env and update with your values
|
|
|
|
# Application
|
|
NODE_ENV=production
|
|
PORT=3001
|
|
|
|
# Security
|
|
# Generate with: openssl rand -base64 32
|
|
JWT_SECRET=your-very-secure-jwt-secret-at-least-32-characters-long-example123456
|
|
|
|
# Auth cookie Secure flag
|
|
# unset - default: follows NODE_ENV (production=true, dev=false)
|
|
# true - always set Secure (HTTPS-only cookies; breaks plain-HTTP access)
|
|
# false - never set Secure (allows HTTP; cookies not protected on HTTPS)
|
|
# auto - decide per request: Secure on HTTPS, not on HTTP
|
|
#
|
|
# Use COOKIE_SECURE=auto if your deployment is reachable over both HTTPS
|
|
# (via a reverse proxy like Nginx Proxy Manager, Traefik, Caddy) AND plain
|
|
# HTTP (e.g. LAN access at http://192.168.x.x:3001). The backend reads
|
|
# req.secure from Express, which respects the X-Forwarded-Proto header
|
|
# when the proxy is in the trust list.
|
|
#
|
|
# Requirements for auto mode:
|
|
# 1. Your reverse proxy MUST send X-Forwarded-Proto: https on HTTPS
|
|
# requests. Standard configs for NPM/Traefik/Caddy do this by default.
|
|
# 2. The proxy must be on a trusted IP range. By default PicPeak trusts
|
|
# loopback and private networks (127.0.0.1, 10.x, 172.16-31.x,
|
|
# 192.168.x, link-local). Proxies outside those ranges need custom
|
|
# trust proxy configuration.
|
|
# COOKIE_SECURE=auto
|
|
|
|
# Cookie SameSite attribute (Lax | Strict | None). Default: Lax
|
|
# COOKIE_SAMESITE=Lax
|
|
|
|
# Cookie Domain — set this if serving auth cookies across subdomains.
|
|
# Leave unset for same-origin setups.
|
|
# COOKIE_DOMAIN=.example.com
|
|
|
|
# URLs (adjust for your domain)
|
|
ADMIN_URL=https://photos.example.com
|
|
FRONTEND_URL=https://photos.example.com
|
|
BACKEND_URL=https://photos.example.com # Or https://api.photos.example.com if separate
|
|
|
|
# API URL for email assets (logos, images in emails)
|
|
# This must be the publicly accessible URL where recipients can load images
|
|
# If not set, defaults to http://localhost:3001 which will break images in production emails
|
|
API_URL=https://photos.example.com/api
|
|
|
|
# Database Configuration
|
|
DATABASE_CLIENT=pg
|
|
DB_HOST=localhost
|
|
DB_PORT=5432
|
|
DB_USER=picpeak
|
|
DB_PASSWORD=your-secure-database-password-change-this
|
|
DB_NAME=picpeak
|
|
|
|
# Email Configuration (Examples for common providers)
|
|
# Gmail example:
|
|
# SMTP_HOST=smtp.gmail.com
|
|
# SMTP_PORT=587
|
|
# SMTP_SECURE=false
|
|
# SMTP_USER=your-email@gmail.com
|
|
# SMTP_PASS=your-app-specific-password
|
|
|
|
# SendGrid example:
|
|
SMTP_HOST=smtp.sendgrid.net
|
|
SMTP_PORT=587
|
|
SMTP_SECURE=false
|
|
SMTP_USER=apikey
|
|
SMTP_PASS=your-sendgrid-api-key
|
|
EMAIL_FROM=noreply@example.com
|
|
|
|
# Storage Paths
|
|
# IMPORTANT: STORAGE_PATH must be set to avoid file path resolution issues
|
|
# Docker deployment:
|
|
STORAGE_PATH=/app/storage
|
|
EVENTS_PATH=/app/storage/events
|
|
ARCHIVE_PATH=/app/storage/events/archived
|
|
|
|
# Local development:
|
|
# STORAGE_PATH=./storage
|
|
# EVENTS_PATH=./storage/events
|
|
# ARCHIVE_PATH=./storage/events/archived
|
|
|
|
# Analytics Backend Configuration (OPTIONAL)
|
|
# Used for server-side tracking only
|
|
# Primary configuration should be done through Admin UI > Settings > Analytics
|
|
# UMAMI_URL=https://analytics.example.com
|
|
# UMAMI_WEBSITE_ID=b4d3c2a1-5678-90ab-cdef-1234567890ab
|
|
|
|
# Logging
|
|
LOG_LEVEL=info |