5c7de96b7f
Two intertwined bugs reported in #427 by @iSchumi6210: 1. Login silently fails over HTTP. Backend defaulted COOKIE_SECURE to true when NODE_ENV=production. Over plain HTTP the browser drops the Secure cookie → next /auth/session request returns 401 → redirect back to /admin/login → no error shown. picpeak-setup.sh writes NODE_ENV=production but never writes COOKIE_SECURE, so every first-time install without a reverse proxy hits this. 2. Admin password is generated but admins can't find it. The 001_init.js migration writes the generated password to data/ADMIN_CREDENTIALS.txt inside the backend container, but picpeak-setup.sh only copies it out when --reset-admin-password is passed. Default-path users never see it and resort to manual bcrypt updates in psql. Changes: - tokenUtils.js: production default goes from `true` to `'auto'`. On real HTTPS req.secure is true → Secure flag is still emitted (no security regression for reverse-proxy deployments). On plain HTTP req.secure is false → Secure flag omitted → login works. Users who explicitly want the strict HTTPS-only behaviour can still set COOKIE_SECURE=true. - .env.example: rewrite the COOKIE_SECURE block to make the new default obvious and explain when to override (set =true for strict, =false to skip the per-request check, leave unset for the auto behaviour). - picpeak-setup.sh (both Docker and native paths): - Write COOKIE_SECURE=auto explicitly to the generated .env (defense in depth so the right behaviour is preserved even if the backend default flips again later) - After migrations, ALWAYS copy ADMIN_CREDENTIALS.txt out of the backend container/data dir to the host data dir, chmod 600, and print the email + password to the install output. The credentials file remains as a backup record that the operator should delete after noting the password. Verified locally with all 4 permutations of NODE_ENV × COOKIE_SECURE: production, unset → HTTPS: secure=true ✓ HTTP: secure=false ✓ (was both true) production, =true → both: secure=true (strict opt-in preserved) production, =auto → HTTPS: secure=true HTTP: secure=false (already-correct) development, unset → both: secure=false (dev unchanged)
106 lines
3.9 KiB
Bash
106 lines
3.9 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: 'auto' in production, false in dev (#427)
|
|
# true - always set Secure (HTTPS-only cookies; breaks plain-HTTP access —
|
|
# login appears to succeed but the browser silently drops the
|
|
# cookie, leaving you in a redirect loop. Only set this if you
|
|
# ALWAYS reach the site via HTTPS)
|
|
# false - never set Secure (allows HTTP; cookies not protected on HTTPS)
|
|
# auto - decide per request: Secure on HTTPS, not on HTTP. Reads
|
|
# req.secure from Express which respects X-Forwarded-Proto from a
|
|
# trusted reverse proxy. This is the default and is the right
|
|
# choice for most deployments.
|
|
#
|
|
# Why 'auto' is the default in production:
|
|
# - On real HTTPS (reverse proxy with X-Forwarded-Proto), req.secure is
|
|
# true → Secure flag is still emitted. No security regression vs. true.
|
|
# - On plain HTTP (LAN access, first-time install before reverse proxy is
|
|
# wired up), req.secure is false → Secure flag is omitted → login works
|
|
# instead of silently looping back to /admin/login.
|
|
#
|
|
# When you'd set this explicitly:
|
|
# - COOKIE_SECURE=true → strict HTTPS-only deployments where you want
|
|
# defense in depth against accidentally serving over HTTP.
|
|
# - COOKIE_SECURE=false → you intentionally only ever serve over HTTP and
|
|
# don't want the per-request check (rare).
|
|
#
|
|
# Requirements for 'auto' mode to detect HTTPS correctly:
|
|
# 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 |