# ── Immich Server Connection (required) ────────────────────────── # Parsed once at startup by lib/env.ts. An unparsable URL is reported and # treated as unset, which lands you on the setup screen rather than a crash. # Base URL of your Immich instance (must be a valid URL) IMMICH_API_URL=http://your-immich-server:2283 # Immich API key (from Admin → API Keys) IMMICH_API_KEY=your-api-key-here # ── Optional Settings ──────────────────────────────────────────── # All have sensible defaults; an unparsable value falls back to the default. # Site title shown in the header (string, default: "Gallery") SITE_TITLE=My Photography # Subtitle displayed below the title (string, default: "") SITE_SUBTITLE=A visual journal # Cache TTL in seconds (integer >= 0, default: 300 = 5 minutes) CACHE_TTL=300 # How long (in seconds) an expired cache entry may still be served while the # Immich server is unreachable. Keeps the public gallery online across an # Immich restart instead of showing an error page. Set to 0 to disable. # Default: 86400 (24 hours) STALE_MAX_AGE=86400 # Cache-buster for image and video URLs (any string, default: empty = off). # Images are served with a one-year immutable cache, so browsers never # revalidate them. If you regenerate thumbnails in Immich, or rotate/edit a # photo, the asset ID stays the same and visitors keep seeing the old version. # Bump this value (e.g. 1 → 2) to change every image URL at once and force a # refetch. Leave it unset in normal operation. # IMAGE_CACHE_VERSION=1 # How long to wait for a response from Immich, in milliseconds # (integer, minimum 1000, default: 15000 = 15 seconds). # Bounds the wait for a *response* only — downloading a large photo or a long # video is not capped by this. Raise it if metadata search on very large albums # times out; lower it to fail faster when Immich is unreachable. # IMMICH_TIMEOUT_MS=15000 # Rate limit for image proxy (integer >= 1, requests per minute per IP, default: 120) # RATE_LIMIT_RPM=120 # Number of reverse proxies in front of the app (nginx/Traefik/Caddy = 1, # Cloudflare in front of nginx = 2). Required for correct rate limiting behind # a proxy — without it the client IP is read from a spoofable header. # The app must be reachable ONLY through the proxy (bind to 127.0.0.1). # TRUSTED_PROXY_HOPS=1 # Secret for signing auth cookies and encrypting asset tokens. REQUIRED in # production: without it the server refuses to start. In development a random # one is generated per process, so every restart invalidates all existing image # URLs and logins — set it there too unless you enjoy that. # Generate one with: openssl rand -hex 32 AUTH_SECRET=change-me-to-a-long-random-string # Webhook secret for cache invalidation (optional, string). # Set this to a long random string and configure Immich to send webhooks to # POST /api/webhook with an x-immich-signature header (HMAC-SHA256 of the body). # If not set, the webhook endpoint returns 501 and is effectively disabled. # WEBHOOK_SECRET=your-long-random-webhook-secret # ── Admin Panel ────────────────────────────────────────────────── # Set a password to enable the visual admin panel at /admin. # Leave unset or empty to disable the admin UI entirely. # ADMIN_PASSWORD=your-secure-admin-password # ── Site URL ───────────────────────────────────────────────────── # Used for sitemap.xml, the feed and structured data when `url:` is not # set in settings.yaml. The settings file takes precedence, so the admin # panel's field always does what it appears to do. # SITE_URL=https://folio.example # ── Update notice ──────────────────────────────────────────────── # The admin dashboard compares the running version against the latest # GitHub release and shows the result in the status list. One request a # day, cached, and it fails quietly when there is no network. # Set to false to switch it off — the dashboard then only names the # version it is running. # UPDATE_CHECK=false # ── Site password (optional) ───────────────────────────────────── # Puts the WHOLE public site behind one password. Overrides # `sitePassword` in settings.yaml, so it can be rotated without # touching the file. /admin keeps its own password. # SITE_PASSWORD=your-site-password # ── Album configuration ────────────────────────────────────────── # Albums, subpages, hero image, and passwords are defined in content/gallery.yaml # See content/gallery.yaml.example for the full reference.