diff --git a/README.md b/README.md
index 37d4f99b..3f4d9549 100644
--- a/README.md
+++ b/README.md
@@ -408,6 +408,8 @@ Caddy handles TLS and WebSockets automatically.
| `FORCE_HTTPS` | Optional. When `true`: 301-redirects HTTP to HTTPS, sends HSTS, adds CSP `upgrade-insecure-requests`, forces the session cookie `secure` flag. Useful behind a TLS-terminating reverse proxy. Requires `TRUST_PROXY`. | `false` |
| `HSTS_INCLUDE_SUBDOMAINS` | When `true`: adds the `includeSubDomains` directive to the HSTS header, extending HTTPS enforcement to all subdomains. Only effective when HSTS is active (`FORCE_HTTPS=true` or `NODE_ENV=production`). Leave `false` if you run other services on sibling subdomains over plain HTTP. | `false` |
| `COOKIE_SECURE` | Controls the `secure` flag on the `trek_session` cookie. Auto-derived: on when `NODE_ENV=production` or `FORCE_HTTPS=true`. Escape hatch: set `false` to allow session cookies over plain HTTP. Not recommended in production. | auto |
+| `SESSION_DURATION` | How long a login session stays valid when **"Remember me" is unchecked** (the default): sets the `trek_session` JWT `exp` and issues a browser-session cookie (cleared when the browser closes). Accepts `ms`-style strings: `1h`, `12h`, `7d`, `30d`, `90d`. Invalid values warn at startup and fall back to the default. | `24h` |
+| `SESSION_DURATION_REMEMBER` | Session length when **"Remember me" is ticked** at login: a longer-lived JWT plus a persistent `trek_session` cookie that survives browser restarts. Same format and startup-fallback behaviour as `SESSION_DURATION`. | `30d` |
| `TRUST_PROXY` | Number of trusted reverse proxies. Tells the server to read client IP from `X-Forwarded-For` and protocol from `X-Forwarded-Proto`. Defaults to `1` in production; off in dev unless set. | `1` |
| `ALLOW_INTERNAL_NETWORK` | Allow outbound requests to private/RFC-1918 IPs (e.g. Immich on your LAN). Loopback and link-local addresses remain blocked. | `false` |
| `APP_URL` | Public base URL of this instance (e.g. `https://trek.example.com`). Required when OIDC is enabled; used as base for email notification links. | — |
diff --git a/charts/trek/templates/configmap.yaml b/charts/trek/templates/configmap.yaml
index 33efce0c..62693a5a 100644
--- a/charts/trek/templates/configmap.yaml
+++ b/charts/trek/templates/configmap.yaml
@@ -28,6 +28,12 @@ data:
{{- if .Values.env.COOKIE_SECURE }}
COOKIE_SECURE: {{ .Values.env.COOKIE_SECURE | quote }}
{{- end }}
+ {{- if .Values.env.SESSION_DURATION }}
+ SESSION_DURATION: {{ .Values.env.SESSION_DURATION | quote }}
+ {{- end }}
+ {{- if .Values.env.SESSION_DURATION_REMEMBER }}
+ SESSION_DURATION_REMEMBER: {{ .Values.env.SESSION_DURATION_REMEMBER | quote }}
+ {{- end }}
{{- if .Values.env.TRUST_PROXY }}
TRUST_PROXY: {{ .Values.env.TRUST_PROXY | quote }}
{{- end }}
diff --git a/charts/trek/values.yaml b/charts/trek/values.yaml
index 0f19d230..f0205423 100644
--- a/charts/trek/values.yaml
+++ b/charts/trek/values.yaml
@@ -34,6 +34,10 @@ env:
# When "true": adds includeSubDomains to the HSTS header. Only effective when HSTS is active. Leave "false" if sibling subdomains still run over plain HTTP.
# COOKIE_SECURE: "true"
# Auto-derived (true in production or when FORCE_HTTPS=true). Set "false" to force cookies over plain HTTP. Not recommended for production.
+ # SESSION_DURATION: "24h"
+ # How long a login session stays valid when "Remember me" is unchecked (the default): trek_session JWT exp + a browser-session cookie. Accepts 1h, 12h, 7d, 30d, 90d. Defaults to 24h.
+ # SESSION_DURATION_REMEMBER: "30d"
+ # Session length when "Remember me" is ticked: a longer-lived JWT + persistent cookie that survives browser restarts. Same format as SESSION_DURATION. Defaults to 30d.
# TRUST_PROXY: "1"
# Trusted proxy hops for X-Forwarded-For/X-Forwarded-Proto. Defaults to 1 in production. Must be set for FORCE_HTTPS to work.
# ALLOW_INTERNAL_NETWORK: "false"
diff --git a/docker-compose.yml b/docker-compose.yml
index bc8dd02c..17cbdcae 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -23,6 +23,7 @@ services:
- LOG_LEVEL=${LOG_LEVEL:-info} # info = concise user actions; debug = verbose admin-level details
# - DEFAULT_LANGUAGE=en # Default language on the login page for users with no saved preference. Browser/OS language is auto-detected first; this is the fallback. Supported: de, en, es, fr, hu, nl, br, cs, pl, ru, zh, zh-TW, it, ar
# - SESSION_DURATION=30d # How long users stay logged in (trek_session JWT + cookie maxAge). Accepts: 1h | 12h | 7d | 30d | 90d. Default: 24h
+# - SESSION_DURATION_REMEMBER=30d # Session length when "Remember me" is ticked at login: longer-lived JWT + persistent cookie that survives browser restarts. Same format as SESSION_DURATION. Default: 30d
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-} # Comma-separated origins for CORS and email notification links
# - FORCE_HTTPS=true # Optional. Enables HTTPS redirect, HSTS, CSP upgrade-insecure-requests, and secure cookies behind a TLS proxy
# - HSTS_INCLUDE_SUBDOMAINS=false # When true: adds includeSubDomains to the HSTS header. Only effective when HSTS is active. Leave false if sibling subdomains still run over plain HTTP.
diff --git a/server/.env.example b/server/.env.example
index 2d9d573d..216ad1c7 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -9,6 +9,7 @@ NODE_ENV=development # development = development mode; production = production m
TZ=UTC # Timezone for logs, reminders and scheduled tasks (e.g. Europe/Berlin)
# DEFAULT_LANGUAGE=en # Default language on the login page for users with no saved preference (default: en)
# SESSION_DURATION=30d # How long users stay logged in — sets the trek_session JWT exp + cookie maxAge. Accepts 1h, 12h, 7d, 30d, 90d. Default: 24h
+# SESSION_DURATION_REMEMBER=30d # Session length when "Remember me" is ticked at login — longer-lived JWT + persistent cookie that survives browser restarts. Same format as SESSION_DURATION. Default: 30d
# Supported values: de, en, es, fr, hu, nl, br, cs, pl, ru, zh, zh-TW, it, ar
# Note: browser/OS language is detected automatically first; this is the fallback when no match is found.
LOG_LEVEL=info # info = concise user actions; debug = verbose admin-level details
diff --git a/unraid-template.xml b/unraid-template.xml
index 5eae6de1..00068d8b 100644
--- a/unraid-template.xml
+++ b/unraid-template.xml
@@ -41,6 +41,8 @@
true
1
false
+ 24h
+ 30d
admin@trek.local
diff --git a/wiki/Install-Unraid.md b/wiki/Install-Unraid.md
index 0edf49d6..8f142ec1 100644
--- a/wiki/Install-Unraid.md
+++ b/wiki/Install-Unraid.md
@@ -45,7 +45,7 @@ The Unraid template exposes the following fields in the container UI:
### Advanced Variables
-Additional variables (`PORT`, `NODE_ENV`, `LOG_LEVEL`, `DEFAULT_LANGUAGE`, `FORCE_HTTPS`, `TRUST_PROXY`, `COOKIE_SECURE`, `ALLOW_INTERNAL_NETWORK`, all OIDC variables, `MCP_RATE_LIMIT`, `MCP_MAX_SESSION_PER_USER`, `DEMO_MODE`) are available under **Advanced View** in the template editor.
+Additional variables (`PORT`, `NODE_ENV`, `LOG_LEVEL`, `DEFAULT_LANGUAGE`, `FORCE_HTTPS`, `TRUST_PROXY`, `COOKIE_SECURE`, `ALLOW_INTERNAL_NETWORK`, `SESSION_DURATION`, `SESSION_DURATION_REMEMBER`, all OIDC variables, `MCP_RATE_LIMIT`, `MCP_MAX_SESSION_PER_USER`, `DEMO_MODE`) are available under **Advanced View** in the template editor.
## Setting the Encryption Key