Environment Variables Reference#
This page provides a centralized reference for all environment variables that can be configured in data/config/custom.env.
For changes to take effect, restart the affected services:
./graphistry stop && ./graphistry up -d
# Or for specific services:
./graphistry stop forge-etl-python && ./graphistry up -d
Logging Configuration#
Variable |
Description |
Default |
|---|---|---|
|
System-wide log level |
|
|
Graphistry application log level |
|
Log levels: TRACE, DEBUG, INFO, WARN, ERROR
Notes:
TRACE: Slow due to heavy CPU-GPU trafficDEBUG: Large log volumes requiring rotationINFO: May cause large log volumes over time
Service Restart Schedules#
Variable |
Description |
Default |
|---|---|---|
|
Cron schedule for all service restarts |
disabled |
|
Cron schedule for streamgl-gpu worker restarts |
disabled |
Examples:
CRON_RESTART="5 */12 * * *" # 5min past every 12th hour
STREAMGL_GPU_WORKER_CRON_RESTART="5 */8 * * *" # 5min past every 8th hour
Timeout and Retry Settings#
HTTP Agent Settings (Transport Layer)#
Variable |
Description |
Default |
|---|---|---|
|
HTTP request timeout |
60000 |
|
HTTP keep-alive duration |
60000 |
Service Communication (Application Layer)#
Variable |
Description |
Default |
|---|---|---|
|
streamgl-viz to streamgl-gpu timeout |
30000 |
|
Number of retries for viz-to-gpu requests |
10 |
GPU Memory Watcher#
Optional safety feature for forge-etl-python that monitors GPU memory and can automatically terminate runaway processes before OOM errors.
Variable |
Description |
Default |
|---|---|---|
|
Enable GPU memory monitoring ( |
disabled |
|
How often to check GPU memory |
15 |
|
Log heartbeat interval (0 = disabled) |
disabled |
|
Log warning when memory exceeds this |
disabled |
|
Start deferred kill process |
disabled |
|
Kill if still above this after defer period |
disabled |
|
Wait time before killing |
300 |
|
Immediate kill (no defer) |
disabled |
Threshold formats: Percentage (70%, 90%) or absolute MB (8192MB, 16384MB)
Example production configuration:
FEP_GPU_WATCHER_ENABLED=1
FEP_GPU_WATCHER_POLL_SECONDS=30
FEP_GPU_WATCHER_WARN_THRESHOLD=70%
FEP_GPU_WATCHER_KILL_THRESHOLD=90%
FEP_GPU_WATCHER_IDLE_THRESHOLD=60%
FEP_GPU_WATCHER_EMERGENCY_THRESHOLD=95%
See Performance Tuning - GPU Memory Watcher for details.
Per-Service GPU Assignment#
By default, CUDA_VISIBLE_DEVICES applies to all GPU services. For advanced multi-GPU configurations, override per service.
Fallback chain:
Service-specific variable (e.g.,
FORGE_CUDA_VISIBLE_DEVICES)Global
CUDA_VISIBLE_DEVICESDefault: GPU 0
Variable |
Service |
|---|---|
|
Global default for all services |
|
forge-etl-python |
|
streamgl-gpu |
|
dask-cuda-worker |
|
dask-scheduler |
|
graph-app-kit-public |
|
graph-app-kit-private |
|
notebook |
Format support:
Integer format:
0,1,2,3(standard CUDA format)UUID format:
GPU-xxx,GPU-yyy(VMware/Nutanix/MIG environments)Mixed format NOT supported for streamgl-gpu
Examples:
# Single GPU (default)
# Leave all commented out, defaults to GPU 0
# Multi-GPU isolation
FORGE_CUDA_VISIBLE_DEVICES=0
STREAMGL_CUDA_VISIBLE_DEVICES=1
# Multi-GPU shared (round-robin assignment)
CUDA_VISIBLE_DEVICES=0,1,2,3
# VMware/Nutanix/MIG
CUDA_VISIBLE_DEVICES=GPU-xxx,GPU-yyy
See Performance Tuning - Per-Service GPU Assignment for details.
Multi-Worker GPU Configuration#
Configure worker counts for multi-GPU utilization. Workers are assigned to GPUs using round-robin distribution.
Variable |
Description |
Default |
|---|---|---|
|
forge-etl-python Hypercorn workers |
4 |
|
streamgl-gpu workers |
4 |
|
dask-cuda-worker instances |
1 |
GPU underutilization policy (matches PyTorch/dask-cuda behavior):
Workers < GPUs: Service logs WARNING, unused GPUs remain idle
Workers > GPUs: Round-robin assignment distributes workers evenly
Workers = GPUs: One-to-one assignment (optimal)
Examples:
# Dual GPU
CUDA_VISIBLE_DEVICES=0,1
FORGE_NUM_WORKERS=8
STREAMGL_NUM_WORKERS=8
DASK_NUM_WORKERS=2
# Quad GPU
CUDA_VISIBLE_DEVICES=0,1,2,3
FORGE_NUM_WORKERS=16
STREAMGL_NUM_WORKERS=16
DASK_NUM_WORKERS=4
Tip: Use the GPU Configuration Wizard to auto-generate optimal settings:
./etc/scripts/gpu-config-wizard.sh -E ./data/config/custom.env
See Performance Tuning - Multi-Worker Configuration for details.
RMM GPU Settings#
RAPIDS Memory Manager settings for GPU memory allocation.
Variable |
Description |
Default |
|---|---|---|
|
Allocator type: |
|
|
Enable memory pooling |
|
|
Initial pool size in bytes |
|
|
Maximum pool size in bytes |
None (full GPU) |
|
Enable RMM logging |
|
Note: For vGPU environments (VMware, Nutanix), set RMM_ALLOCATOR=default as vGPUs don’t support CUDA Unified Memory.
See Performance Tuning - RMM GPU Settings for details.
Cache Configuration#
Control CPU and GPU cache sizes for forge-etl-python. Sizes are per-worker.
Variable |
Description |
Default |
|---|---|---|
|
Override all CPU cache counts |
varies |
|
Override large CPU cache counts |
varies |
|
Override small CPU cache counts |
varies |
|
Override all GPU cache counts |
varies |
|
Override large GPU cache counts |
~30 |
|
Override small GPU cache counts |
varies |
Important GPU caches:
N_CACHE_ROUTES_SHAPER_TIMEBARN_CACHE_ROUTES_SHAPER_HISTOGRAMN_CACHE_ROUTES_SHAPER_SELECT_IDS_IN_GROUPN_CACHE_ARROW_LOADER_FETCH_WARM
Important CPU caches:
N_CACHE_ARROW_LOADER_FETCH_VGRAPHN_CACHE_ARROW_LOADER_FETCH_ENCODINGSN_CACHE_ARROW_LOADER_FETCH_HELPERN_CACHE_ARROW_DOWNLOADER_FETCH_UNSHAPEDN_CACHE_ARROW_DOWNLOADER_FETCH_SHAPE
See Performance Tuning - Cache Size for details.
Upload Settings#
Variable |
Description |
Default |
|---|---|---|
|
Maximum upload size |
|
Examples: 1M, 100M, 1G, 10G
Cross-Origin Embedding (CORS)#
Variable |
Description |
Default |
|---|---|---|
|
Comma-separated list of additional browser origins allowed for cross-origin API requests and visualization socket handshakes; does not control iframe embedding |
empty (no additional origins) |
CORS_ALLOWED_ORIGINS is the single source of truth for cross-origin access across the stack — read by
nginx, nexus, pivot, and the visualization realtime socket. Empty (the default) allows no additional
browser origins for those requests. This is intentional (earlier releases allowed all origins; that default
was removed for security). It does not prevent an HTTPS site from loading a Graphistry HTTPS page in an
iframe. Most deployments need no change — see the authoritative reference in
data/config/custom.env. Two distinct cases are easy to conflate:
Embedding
https://graphistry.example.com/graph.htmlin an iframe onhttps://dashboard.example.com: JavaScript inside the iframe opens the visualization socket from the Graphistry origin, which passes the socket’s own-host check. Do not add the parent page’s origin toCORS_ALLOWED_ORIGINSfor this embed. For authenticated cross-site embeds, session cookies needSameSite=None; Secure(settings above), and the browser must allow third-party cookies. The parent page must permit the iframe, and Graphistry’s response must permit that parent to frame it. An iframe sandboxed withoutallow-same-originhas an opaque origin (Origin: nullon its socket handshake) and is rejected.JavaScript running on
https://dashboard.example.comdirectly calling Graphistry’s API or socket: listhttps://dashboard.example.cominCORS_ALLOWED_ORIGINS. This admits the origin but does not authenticate the request or enable credentialed cross-origin REST or socket polling by itself.
# only when JavaScript on this different host calls Graphistry directly:
CORS_ALLOWED_ORIGINS=https://dashboard.example.com
Credentialed cross-origin REST requests are not supported. REST responses do not emit
Access-Control-Allow-Credentials; a separate frontend making browserfetchrequests must use bearer-token / API-key authentication instead ofcredentials: 'include'. Same-origin pages and iframe embeds continue to use Graphistry’s session cookies.
Realtime socket (upgrade note): the visualization’s realtime (socket.io) connection now also honors
CORS_ALLOWED_ORIGINS on its handshake, for both HTTP polling and WebSocket upgrade. The allowlist
admits an origin; it does not authenticate a socket. The visualization socket uses cookie-backed
authentication, and credentialed cross-origin polling is not enabled by this setting. The supported
iframe embed loads Graphistry’s own page and makes same-origin socket requests, so its parent origin
needs no socket allowlist entry. A sandboxed iframe without allow-same-origin instead sends
Origin: null on its socket handshake and is refused.
The first GET /graph/graph.html?dataset=... can arrive without session; the graph page normally
redirects to a URL containing session=<Graphistry session ID>. Its built-in socket client carries
that value on every transport request. Caddy hashes the value to the same engine pod in multi-engine
Kubernetes, then viz keeps each Engine.IO connection on one CPU worker. This is routing, not
authorization or a guarantee of cross-user collaboration: same-account tabs may retain one session,
but a different authenticated user opening its URL is redirected to a fresh session. Anonymous reuse
of an anonymous session is limited to 10 seconds. The app-level two-tab smoke test checks that closing
one tab leaves the other operational; the proxy fixture checks transport routing only.
A direct Socket.IO handshake without session differs from that expected first page GET. In
multi-engine Kubernetes, it can open a socket but lose its next polling request across engine pods.
Include the Graphistry session query on every direct-client connection and reconnect. Compose’s
single-engine path has no inter-pod risk. No server-side 422 rejection has been introduced while
direct-client compatibility remains under review. A VPN or changing browser IP does not affect a
session-based route.
Marketplace / turnkey deployments ship with
CORS_ALLOWED_ORIGINSempty (same-origin only, fail-closed) — the same secure default as every other distribution. Set it only if a separate different-origin frontend needs browser-side API/socket access.
Maps / Geospatial#
Enable Kepler.gl-based geospatial map visualizations.
Variable |
Description |
Default |
|---|---|---|
|
Enable geospatial map support |
|
Example:
GRAPHISTRY_ENABLE_KEPLER=true
See the PyGraphistry Maps documentation for usage details.
Quick Reference by Use Case#
Production Hardening#
LOG_LEVEL=INFO
GRAPHISTRY_LOG_LEVEL=INFO
FEP_GPU_WATCHER_ENABLED=1
FEP_GPU_WATCHER_WARN_THRESHOLD=70%
FEP_GPU_WATCHER_KILL_THRESHOLD=90%
FEP_GPU_WATCHER_EMERGENCY_THRESHOLD=95%
COOKIE_SECURE=true
Multi-GPU Setup (4 GPUs)#
CUDA_VISIBLE_DEVICES=0,1,2,3
FORGE_NUM_WORKERS=16
STREAMGL_NUM_WORKERS=16
DASK_NUM_WORKERS=4
Development / Debugging#
LOG_LEVEL=DEBUG
GRAPHISTRY_LOG_LEVEL=DEBUG
VMware / Nutanix vGPU#
RMM_ALLOCATOR=default
CUDA_VISIBLE_DEVICES=GPU-xxx,GPU-yyy
Maps / Geospatial#
GRAPHISTRY_ENABLE_KEPLER=true