From 67d3c13bb6a2e84a374a2bd486faec36428b9657 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 8 Sep 2026 14:12:04 -0400 Subject: [PATCH] Fix .env.example: missing Matrix vars, plus a real parse_ini_file outage (#63) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Primary fix (#63): added the 5 env vars config.php reads and README documents but .env.example never listed: MATRIX_DOMAIN, SYNAPSE_ADMIN_URL, SYNAPSE_ADMIN_TOKEN, MATRIX_NOTIFY_COMMENTS, and MATRIX_NOTIFY_ASSIGNMENTS. A deployer following only .env.example had no indication these existed, silently missing watcher Matrix DMs and comment/assignment notifications. While verifying the fix by actually running .env.example through parse_ini_file() (what config.php calls), found this file could not be parsed at all — a real, currently-live outage for anyone following its own first-line instruction ("Copy this file to .env and fill in your values"): 1. PHP's ini parser treats "#" comments as fragile: punctuation like parentheses or quotes inside a "#" comment can throw a syntax error even though the line is meant to be inert. The file's header comment itself (and 15+ other comment lines) tripped this. Switched every comment to ";", which parse_ini_file treats as a true inert comment regardless of content — verified with isolated repros of both prefixes under all three INI_SCANNER_* modes. 2. LDAP_BIND_DN's example value contained unquoted "=" and commas, violating the file's own documented quoting rule and causing a second, independent parse failure. Quoted it (and the two other comma-bearing LDAP DN values) to match the rule. config.php has zero fallback for a parse failure — it die()s immediately — so either bug alone would have taken down every fresh deployment that didn't hand-edit the example file's comments first. Verified end-to-end: copied .env.example to a real .env file unmodified and ran it through config.php's exact parse_ini_file + quote-stripping logic; it now parses cleanly with all 23 keys (including the 5 new ones) and LDAP_BIND_DN resolves to the correct unquoted DN string. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MGDKHiU5RJdo3dqQUDow3X --- .env.example | 93 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/.env.example b/.env.example index cbce12a..4b76f6f 100644 --- a/.env.example +++ b/.env.example @@ -1,60 +1,79 @@ -# Tinker Tickets Environment Configuration -# Copy this file to .env and fill in your values -# -# NOTE: This file is parsed with parse_ini_file(). Any value containing special -# characters (#, ;, =, quotes, spaces, etc.) MUST be wrapped in double quotes, -# e.g. DB_PASS="p@ss;word#1". The application now fails loudly (dies with a clear -# error) if the .env file cannot be parsed, so an unquoted special character will -# take the whole app down rather than silently using a wrong value. +; Tinker Tickets Environment Configuration +; Copy this file to .env and fill in your values +; +; NOTE: This file is parsed with PHP's parse_ini_file. Any value containing +; special characters -- #, ;, =, quotes, spaces, etc. -- MUST be wrapped in +; double quotes, e.g. DB_PASS="p@ss;word#1". The application now fails loudly +; -- dies with a clear error -- if the .env file cannot be parsed, so an +; unquoted special character will take the whole app down rather than +; silently using a wrong value. +; +; Comments in this file use ";" rather than "#": PHP's ini parser treats "#" +; comments as fragile -- punctuation like parentheses or quotes inside a "#" +; comment can produce a syntax error even though the line is meant to be +; inert, silently breaking every value below it. ";" comments don't have this +; problem, so keep using ";" for any comment added to this file. -# Database Configuration +; Database Configuration DB_HOST=10.10.10.50 DB_USER=tinkertickets DB_PASS=your_password_here DB_NAME=ticketing_system -# Matrix Webhook (optional - for notifications via matrix-hookshot) -# Set to your hookshot generic webhook URL, e.g.: -# https://matrix.lotusguild.org/webhook/ +; Matrix Webhook (optional - for notifications via matrix-hookshot) +; Set to your hookshot generic webhook URL, e.g.: +; https://matrix.lotusguild.org/webhook/uuid-goes-here MATRIX_WEBHOOK_URL= -# Matrix users to @mention on every new ticket (comma-separated Matrix user IDs) -# e.g. @jared:matrix.lotusguild.org,@alice:matrix.lotusguild.org +; Matrix users to @mention on every new ticket (comma-separated Matrix user IDs) +; e.g. @jared:matrix.lotusguild.org,@alice:matrix.lotusguild.org MATRIX_NOTIFY_USERS= -# Application Domain (required for Matrix webhook ticket links) -# Set this to your public domain (e.g., t.lotusguild.org) +; Matrix homeserver domain (used to build Matrix user IDs from LLDAP usernames) +MATRIX_DOMAIN= + +; Synapse internal URL and admin token (used to resolve usernames -> Matrix IDs +; for watcher DMs) +SYNAPSE_ADMIN_URL= +SYNAPSE_ADMIN_TOKEN= + +; Optional: send a Matrix notification on comments and/or assignments (0/1) +MATRIX_NOTIFY_COMMENTS=0 +MATRIX_NOTIFY_ASSIGNMENTS=0 + +; Application Domain (required for Matrix webhook ticket links) +; Set this to your public domain, e.g. t.lotusguild.org APP_DOMAIN= -# Allowed Hosts for HTTP_HOST validation (comma-separated) -# Include all domains that can access this application +; Allowed Hosts for HTTP_HOST validation (comma-separated) +; Include all domains that can access this application ALLOWED_HOSTS=localhost,127.0.0.1 -# Trusted reverse proxy IP(s), comma-separated (e.g. the Authelia/nginx proxy). -# Set this to the IP address(es) of your reverse proxy. Authelia forward-auth -# headers (Remote-User / Remote-Groups) and forwarded client IPs are only -# trusted when REMOTE_ADDR is in this list. -# -# Leaving this EMPTY disables reverse-proxy verification entirely: the app then -# trusts Remote-User / Remote-Groups headers from ANY source. That is unsafe if -# the PHP backend is reachable directly (bypassing the proxy), because a client -# can then spoof those headers and log in as an admin. Only leave it empty when -# network topology guarantees PHP is reachable solely via the trusted proxy. -# -# Exact IP match only (no CIDR). Example (single proxy): TRUSTED_PROXIES=10.10.10.27 -# Example (multiple): TRUSTED_PROXIES=10.10.10.27,10.10.10.28 +; Trusted reverse proxy IPs, comma-separated -- e.g. the Authelia/nginx proxy. +; Set this to the IP address(es) of your reverse proxy. Authelia forward-auth +; headers (Remote-User / Remote-Groups) and forwarded client IPs are only +; trusted when REMOTE_ADDR is in this list. +; +; Leaving this EMPTY disables reverse-proxy verification entirely: the app then +; trusts Remote-User / Remote-Groups headers from ANY source. That is unsafe if +; the PHP backend is reachable directly (bypassing the proxy), because a client +; can then spoof those headers and log in as an admin. Only leave it empty when +; network topology guarantees PHP is reachable solely via the trusted proxy. +; +; Exact IP match only (no CIDR). Example (single proxy): TRUSTED_PROXIES=10.10.10.27 +; Example (multiple): TRUSTED_PROXIES=10.10.10.27,10.10.10.28 TRUSTED_PROXIES= -# Timezone (default: America/New_York) +; Timezone (default: America/New_York) TIMEZONE=America/New_York -# LDAP / lldap (for user avatar lookups) +; LDAP / lldap (for user avatar lookups) LDAP_ENABLED=true LDAP_HOST=10.10.10.39 LDAP_PORT=3890 -LDAP_BIND_DN=uid=tinker-tickets,ou=people,dc=example,dc=com +LDAP_BIND_DN="uid=tinker-tickets,ou=people,dc=example,dc=com" LDAP_BIND_PW= -LDAP_BASE_DN=dc=example,dc=com -LDAP_USER_BASE=ou=people,dc=example,dc=com -# How long to cache avatar images locally (seconds, default 3600) +LDAP_BASE_DN="dc=example,dc=com" +LDAP_USER_BASE="ou=people,dc=example,dc=com" +; How long to cache avatar images locally (seconds, default 3600) AVATAR_CACHE_TTL=3600