diff --git a/compact/tracking_config_deathvalley.xml b/compact/tracking_config_deathvalley.xml
index bd6d93ede3a09ca7eccf72ac64edc2d45766e110..d3276b6f94b50f05b4c0afbff83ddaeacfce78da 100644
--- a/compact/tracking_config_deathvalley.xml
+++ b/compact/tracking_config_deathvalley.xml
@@ -100,6 +100,7 @@
   </documentation>
   <plugins>
     <plugin name="FileLoader">
+      <arg value="cache:$DETECTOR_PATH"/>
       <arg value="file:calibrations/materials-map.cbor"/>
       <arg value="url:https://eicweb.phy.anl.gov/EIC/detectors/athena/uploads/4a4e7c8eb6089b634d762d112c89bd5d/material-maps.cbor"/>
     </plugin>
diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp
index 618f50aaf9b22b25de1a2bb3c223c15635002034..917dc873db98f491b65ae4c0479daf147d5ad634 100644
--- a/src/FileLoader.cpp
+++ b/src/FileLoader.cpp
@@ -8,6 +8,7 @@
 
 #include <filesystem>
 #include <iostream>
+#include <cstdlib>
 #include <string>
 
 namespace fs = std::filesystem;
@@ -57,6 +58,24 @@ long load_file(
     return 0;
   }
 
+  // parse cache for environment variables
+  auto pos = std::string::npos;
+  while ((pos = cache.find('$')) != std::string::npos) {
+    auto after = cache.find_first_not_of(
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+      "abcdefghijklmnopqrstuvwxyz"
+      "0123456789"
+      "_",
+      pos + 1);
+    if (after == std::string::npos) after = cache.size(); // cache ends on env var
+    auto env_name = cache.substr(pos + 1, after - pos - 1);
+    auto env_value = std::getenv(env_name.c_str());
+    if (env_value == nullptr) env_value = "";
+    cache.erase(pos, after - pos);
+    cache.insert(pos, env_value);
+    printout(INFO, "FileLoader", "$" + env_name + " -> " + env_value);
+  }
+
   // create file path
   fs::path file_path(file);