# EverShelf — Configuration # Copy this file to .env and fill in your values: # cp .env.example .env # # All settings here can also be changed from the in-app Settings screen and # will be written back to this file automatically. # ───────────────────────────────────────────────────────────────────────────── # ── AI ──────────────────────────────────────────────────────────────────────── # Google Gemini API key (required for AI features: expiry reading, recipe gen, …) # Get one free at: https://aistudio.google.com/app/apikey GEMINI_API_KEY= # ── Shopping list (Bring!) ──────────────────────────────────────────────────── # Credentials for the Bring! app (optional — app works without it) BRING_EMAIL= BRING_PASSWORD= # ── Text-to-Speech (TTS) ───────────────────────────────────────────────────── # Works with Home Assistant, a local TTS server, or any HTTP endpoint. # TTS_ENABLED: master switch (true/false) TTS_ENABLED=false # TTS_URL: endpoint that receives the text payload TTS_URL= # TTS_TOKEN: Authorization token sent as Bearer header (or empty) TTS_TOKEN= # TTS_METHOD: HTTP method (POST or GET) TTS_METHOD=POST # TTS_AUTH_TYPE: how the token is sent (bearer | basic | none) TTS_AUTH_TYPE=bearer # TTS_CONTENT_TYPE: request Content-Type header TTS_CONTENT_TYPE=application/json # TTS_PAYLOAD_KEY: JSON key that carries the text (e.g. "message", "text") TTS_PAYLOAD_KEY=message # TTS_ENGINE: preferred browser TTS engine ('browser', 'server', 'custom') — optional TTS_ENGINE= # TTS_RATE / TTS_PITCH: speech rate and pitch multipliers (1 = normal) TTS_RATE=1 TTS_PITCH=1 # TTS_AUTH_HEADER_NAME / VALUE: custom HTTP header for authentication (optional) TTS_AUTH_HEADER_NAME= TTS_AUTH_HEADER_VALUE= # TTS_EXTRA_FIELDS: additional JSON fields as key=value pairs, comma-separated (optional) TTS_EXTRA_FIELDS= # ── User preferences ───────────────────────────────────────────────────────── # These mirror the toggle switches in the Settings screen. DEFAULT_PERSONS=1 PREF_VELOCE=false PREF_POCAFAME=false PREF_SCADENZE=true PREF_HEALTHY=false PREF_OPENED=true PREF_ZEROWASTE=false # Dietary restrictions shown to the AI (e.g. "vegetariano,senza glutine") DIETARY= # ── Appliances ──────────────────────────────────────────────────────────────── # Comma-separated list of appliances available in your kitchen. # Used by the AI when generating recipes. APPLIANCES=Forno,Microonde,Friggitrice ad aria,Pentola a pressione # ── Camera ─────────────────────────────────────────────────────────────────── # Default camera for barcode scanning ('environment' = rear, 'user' = front) CAMERA_FACING=environment # ── Smart Kitchen Scale ─────────────────────────────────────────────────────── # SCALE_ENABLED: enables the scale integration SCALE_ENABLED=false # SCALE_GATEWAY_URL: address of the EverShelf Scale Gateway (Android app) SCALE_GATEWAY_URL= # ── Meal Plan ──────────────────────────────────────────────────────────────── # MEAL_PLAN_ENABLED: show the weekly meal planner tab in Settings MEAL_PLAN_ENABLED=false # ── Screensaver (kiosk / tablet mode) ──────────────────────────────────────── SCREENSAVER_ENABLED=false # SCREENSAVER_TIMEOUT: inactivity seconds before screensaver activates (default 5 min) SCREENSAVER_TIMEOUT=300 # ── Price estimates ─────────────────────────────────────────────────────────── # PRICE_ENABLED: show AI-estimated price column on the shopping list PRICE_ENABLED=false # PRICE_COUNTRY: country used for price context (e.g. "Italia", "Germany") PRICE_COUNTRY=Italia # PRICE_CURRENCY: ISO 4217 currency code (e.g. EUR, USD, GBP) PRICE_CURRENCY=EUR # PRICE_UPDATE_MONTHS: how many months to cache a price before re-fetching (default 3) PRICE_UPDATE_MONTHS=3 # ── Cleanup / retention ────────────────────────────────────────────────────── # RECIPE_RETENTION_DAYS: delete auto-generated recipe plans older than N days RECIPE_RETENTION_DAYS=7 # TRANSACTION_RETENTION_DAYS: keep stock transaction history for N days. # Smart Shopping uses this history to compute purchase frequencies. # WARNING: values below 30 will cause the shopping list to appear nearly empty. # Minimum enforced at runtime: 30 days. TRANSACTION_RETENTION_DAYS=90 # ── Local Backup ───────────────────────────────────────────────────────────── # BACKUP_ENABLED: run a daily incremental backup via cron (true/false) BACKUP_ENABLED=true # BACKUP_RETENTION_DAYS: keep local backups for N days (minimum 1) BACKUP_RETENTION_DAYS=3 # ── Google Drive Backup ─────────────────────────────────────────────────────── # GDRIVE_ENABLED: upload the daily backup to Google Drive (requires a service account) GDRIVE_ENABLED=false # # Setup steps: # 1. Create a Google Cloud project and enable the Drive API # 2. Create a Service Account and download the JSON key # 3. Create a Drive folder and share it with the service account email # 4. Paste the JSON content below (or set GDRIVE_SERVICE_ACCOUNT_FILE to the path) # 5. Set GDRIVE_FOLDER_ID to the Drive folder ID (from its URL) # # GDRIVE_SERVICE_ACCOUNT_JSON: full JSON content of the service account key GDRIVE_SERVICE_ACCOUNT_JSON= # GDRIVE_SERVICE_ACCOUNT_FILE: alternative — path to the service account JSON file GDRIVE_SERVICE_ACCOUNT_FILE= # GDRIVE_FOLDER_ID: ID of the Drive folder where backups will be stored GDRIVE_FOLDER_ID= # GDRIVE_RETENTION_DAYS: delete Drive backups older than N days (0 = keep all) GDRIVE_RETENTION_DAYS=30 # ── Security ───────────────────────────────────────────────────────────────── # API_TOKEN: when set, all API calls require header X-API-Token (or ?api_token= for HA). # SETTINGS_TOKEN: legacy alias — use API_TOKEN for new installs. API_TOKEN= SETTINGS_TOKEN= # CORS_ORIGIN: comma-separated allowed origins (empty = same-origin only, no wildcard) CORS_ORIGIN= # GitHub automatic issue reporting (encrypted storage recommended) # Option A — plain ( .env is gitignored ): # GH_ISSUE_TOKEN=ghp_... # Option B — encrypted (php scripts/encrypt-gh-token.php 'ghp_...' 'secret-key'): GH_ISSUE_TOKEN= GH_ISSUE_TOKEN_ENC= GH_ISSUE_TOKEN_KEY= # NOTE: Run `php scripts/migrate-env-security.php` once after upgrading to migrate legacy tokens. # INSTANCE_NAME: display name for this EverShelf instance (used by the HA integration # for Zeroconf discovery label and device name in Home Assistant). # Defaults to the server hostname if left empty. INSTANCE_NAME= # ── Home Assistant Integration ──────────────────────────────────────────────── # All HA settings can also be configured from the Settings → 🏠 tab. # # HA_ENABLED: master switch for all HA features (webhooks, TTS, sensors) HA_ENABLED=false # HA_URL: base URL of your HA instance — no trailing slash # Examples: http://homeassistant.local:8123 or http://192.168.1.50:8123 HA_URL= # HA_TOKEN: Long-Lived Access Token (HA Profile → Security → Long-Lived Access Tokens) HA_TOKEN= # HA_TTS_ENTITY: media_player entity for recipe step TTS (e.g. media_player.living_room) HA_TTS_ENTITY= # HA_WEBHOOK_ID: ID of an HA automation's Webhook trigger HA_WEBHOOK_ID= # HA_WEBHOOK_EVENTS: comma-separated events to fire webhooks for # Available: expiry, shopping_add, stock_update, barcode_scan HA_WEBHOOK_EVENTS=expiry,shopping_add,stock_update # HA_NOTIFY_SERVICE: HA notify service for push alerts (e.g. notify.mobile_app_my_phone) HA_NOTIFY_SERVICE= # HA_EXPIRY_DAYS: days before expiry to trigger expiry alert (default 3) HA_EXPIRY_DAYS=3 # ── Developer / demo ───────────────────────────────────────────────────────── # DEMO_MODE: when true, all write operations are blocked (for public demos) DEMO_MODE=false # CRON_LOG_MAX_BYTES: rotate data/cron.log when larger (default 524288 = 512 KB) CRON_LOG_MAX_BYTES=524288