Environment variables
There are ~337 environment variables across the four repos (backend 159, crms-middleware 124,
frontend 51, pdf-service 3). This page is the map, grouped by concern — the committed
.env.example files (blank values) + config/*.php are the exhaustive, always-current source. Names and
purpose only; no values appear anywhere in these docs. 🔐 marks a secret to rotate on handover.
Core — app / DB / cache / queue / logging
Section titled “Core — app / DB / cache / queue / logging”Standard Laravel config, shared by backend (BE) and crms-middleware (MW): APP_NAME/APP_ENV/
APP_DEBUG/APP_URL, APP_KEY 🔐, LOG_CHANNEL/LOG_LEVEL, DB_* (+ DB_PASSWORD 🔐,
DB_ROOT_PASSWORD 🔐), REDIS_HOST/REDIS_PORT (+ REDIS_PASSWORD 🔐), the driver set
(CACHE_DRIVER/QUEUE_CONNECTION/SESSION_DRIVER/SESSION_LIFETIME), MAIL_* (+ MAIL_PASSWORD 🔐),
PUSHER_* (+ PUSHER_APP_SECRET 🔐), MinIO dev storage (+ MINIO_ROOT_PASSWORD 🔐),
SANCTUM_STATEFUL_DOMAINS, TELESCOPE_ENABLED, and PROMETHEUS_METRICS_ENABLED +
PROMETHEUS_SCRAPE_METRICS_TOKEN 🔐.
CRM integration (mostly crms-middleware)
Section titled “CRM integration (mostly crms-middleware)”The largest group — the CRM integration model explains the shape.
- Backend → middleware (BE):
CRMS_MIDDLEWARE_{BASE_URL,AUTH_URL,API_URL,GRANT_TYPE,CLIENT_ID}+CRMS_MIDDLEWARE_CLIENT_SECRET🔐 (Passportclient_credentials). - Write auth → Logic Apps (MW):
LINK_DEV_{AUTH_URL,GRANT_TYPE,RESOURCE,CLIENT_ID}+LINK_DEV_CLIENT_SECRET🔐 (Azure AD v1.0resource=). - Read auth → per-country OData (MW):
{EGYPT,OMAN,MONTENEGRO}_CRM_{AUTH_URL,GRANT_TYPE,SCOPE,BASE_URL, CLIENT_ID}+ each_CLIENT_SECRET🔐 (v2.0scope=). The client id/secret are identical acrossLINK_DEV_*and all three*_CRM_*— one Azure AD app (see the single-credential note). - Logic-App operation URLs (MW): one
*_URLper operation, grouped:LEAD_*(3),SALE_CRM_*/UNIT_*(unit/sale, ~9),SALESMAN_CRM_API_*(~14),CRM_API_EOI_*(~9),SHOPPER_DETAILS_URL,CRM_BROKER_SELF_SIGNUP,UNIT_SERVICE_SUBMIT/UNIT_RESELL_ASSISTANCE. See the full list incrms-middleware/.env.example. - Mocks (dev):
OMAN_CRM_BROKER_CRM_MOCK_ENABLED+_BASE_URL,CRM_LEAD_ELIGIBLE_CRM_MOCK_ENABLED. - CMS (Payload):
CMS_{BASE_URL,AUTH_URL,API_URL,CLIENT_ID,GRANT_TYPE}+CMS_CLIENT_SECRET🔐.
Payments
Section titled “Payments”- Backend — Paymob (per Egyptian destination):
{ELGOUNA,MAKADI,OWEST}_PAYMOB_API_KEY🔐 +_HMAC_SECRET🔐 +{dest}_{USD,EGP}_PAYMOB_INTEGRATION_ID;PAYMOB_{AUTH,ORDER,PAYMENT_KEY}_URL. - Backend — Thawani (Oman):
THAWANI_{API_URL,CREATE_SESSION_URL,SUCCESS_URL,CANCEL_URL,PUBLIC_KEY}+THAWANI_SECRET_KEY🔐. (THAWANI_CREATE_SESSION_URL— the endpointThawaniServiceactually POSTs to — is read from config but absent from.env.example; see drift.) - Backend — WSPG (Montenegro):
WSPG_{API_URL,SHOP_ID,SUCCESS_URL,CANCEL_URL,FAIL_URL}+WSPG_SECRET_KEY🔐. - Frontend redirect targets:
NX_PAYMOB_IFRAME_URL,NX_THAWANI_IFRAME_URL,NX_THAWANI_PUBLIC_KEY,NX_WSPAY_PAYMENT_URL.
Adding a gateway? See Add a payment gateway.
PDF service
Section titled “PDF service”| Var | Repo | Default | Purpose |
|---|---|---|---|
PDF_SERVICE_URL |
BE | http://localhost:3001 |
Microservice base URL |
PDF_SERVICE_TOKEN 🔐 |
BE | — | Bearer sent to the PDF service |
PDF_SERVICE_TIMEOUT |
BE | 120 (s) |
HTTP client timeout |
PDF_SERVICE_GENERATE_RATE_LIMIT_PER_MINUTE |
BE | 5 |
Per-user generate throttle |
SALES_OFFER_DISK / SALES_OFFER_EXPIRY_DAYS |
BE (config/filesystems.php) |
— / 14 |
Disk + expiry (⚠ not in .env.example — see drift) |
API_TOKEN 🔐 |
pdf-service | — | Bearer for POST /api/sales-offer |
PORT / BODY_PAYLOAD_LIMIT |
pdf-service | 3001 / 20mb |
Listen port / max body |
Auth / SSO & frontend URLs (backend)
Section titled “Auth / SSO & frontend URLs (backend)”- Microsoft SSO (sales-man):
AZURE_{CLIENT_ID,TENANT_ID,OBJECT_ID}+AZURE_CLIENT_SECRET🔐 (the secret theazureconfig group reads,config/services.php:63). ⚠.env.exampleshipsAZURE_SECRET_IDinstead — which the SSO group doesn’t consume — soAZURE_CLIENT_SECRETis a drift (see below). - Per-persona SPA URLs (payment/redirect targets):
SHOPPER_FRONTEND_URL,BROKER_FRONTEND_URL,SALES_MAN_FRONTEND_URL,SHOPPER_ADMIN_FRONTEND_URL,BROKER_DASHBOARD_URL,FRONTEND_RESET_PASS_PATH, the Oman pre-reg document paths. - Mail services (OAuth):
ORASCOM_MAIL_*+ORASCOM_MAIL_CLIENT_SECRET🔐;ORASCOM_OMAN_PRE_REGISTRATION_MAIL_*+ its_CLIENT_SECRET🔐.
Integrations & observability (backend)
Section titled “Integrations & observability (backend)”SENTRY_LARAVEL_DSN 🔐 + sample-rate/env; the OTEL_* set (backend-only tracing/metrics/logs);
FIREBASE_CREDENTIALS 🔐 (push); GA4 (GOOGLE_ANALYTICS_* + _PRIVATE_KEY/_PRIVATE_KEY_ID 🔐);
AWS_* (S3 media; AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY 🔐); Infobip SMS (INFOBIP_BASE_URL/
_SENDER_ID + INFOBIP_API_KEY 🔐, ALLOW_SEND_SMS); ALLOW_TEST_OTP + OTP_TEST_CODE 🔐 (the
test-OTP bypass — must be off in prod); Currency-Layer (CURRENY_LAYER_API_URL + CURRENY_LAYER_API_KEY
🔐 — note the intentional CURRENY typo); ops recipient lists (EOI_FAILED_EMAILS, ADMIN_EMAIL, …);
UNIT_BLOCK_DURATION/UPDATE_INFO_DURATION (default 1 day, the reservation window — see the
CRM-owned TTL).
Frontend NX_* (inlined into the browser bundle)
Section titled “Frontend NX_* (inlined into the browser bundle)”Per-app API endpoints (NX__<persona>_API_ENDPOINT + _ENDPOINT_PREFIX) and token-storage keys
(NX_*_ACCESS_TOKEN_KEY — the auth model lists the defaults); refresh-token
config; the payment redirect vars (above); per-app Sentry DSNs + Firebase web config (public by
design); and a set of feature flags (NX_HIDE_*, NX__ENABLE_EOI, NX_ALLOW_MULTIPLE_RESERVATIONS, …).
The two exceptions that must not be here: NX_CLIENT_SECRET and NX_CURRENY_LAYER_API_KEY (see the
danger callout at the top).
Config-vs-.env.example drift (fill these in for a real environment)
Section titled “Config-vs-.env.example drift (fill these in for a real environment)”Several vars are read from config/*.php but missing from the committed .env.example — an operator
who just copies .env.example won’t set them:
- Backend:
SALES_OFFER_DISK,SALES_OFFER_EXPIRY_DAYS(config/filesystems.php:27-28). - Middleware:
MICROSOFT_ADMIN_GUID,CRM_EXCHANGE_RATE_URL(config/services.php). - Frontend: the per-project Thawani keys
NX_THAWANI_{AMAZI,RAYA,SIFAH_FARMS,SOLARIS,BEACHFRONT2}_PUBLIC_KEY(note theBEACHFRONT2) — consumed in code but only the genericNX_THAWANI_PUBLIC_KEYships in.env.example. - Backend:
THAWANI_CREATE_SESSION_URL(config/payment.php:23) andAZURE_CLIENT_SECRET(config/services.php:63, the SSO secret the code reads) — both read from config but absent frombackend/.env.example(which instead ships an unusedAZURE_SECRET_ID).
Secrets to rotate on handover
Section titled “Secrets to rotate on handover”Every 🔐 above. The critical set: APP_KEY; DB/Redis/Mail/Pusher/MinIO passwords; AWS_SECRET_ACCESS_KEY;
PROMETHEUS_SCRAPE_METRICS_TOKEN; the CRM chain (CRMS_MIDDLEWARE_CLIENT_SECRET, LINK_DEV_CLIENT_SECRET,
the three *_CRM_CLIENT_SECRET, CMS_CLIENT_SECRET); all Paymob keys/HMAC secrets, THAWANI_SECRET_KEY,
WSPG_SECRET_KEY; PDF_SERVICE_TOKEN / pdf API_TOKEN; AZURE_CLIENT_SECRET; the two mail *_CLIENT_SECRET;
FIREBASE_CREDENTIALS; GOOGLE_ANALYTICS_PRIVATE_KEY; INFOBIP_API_KEY; CURRENY_LAYER_API_KEY;
OTP_TEST_CODE; and — because they shipped to the browser — NX_CLIENT_SECRET and
NX_CURRENY_LAYER_API_KEY.
