diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,18 @@
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## Unreleased
+
+### Added
+
+ - Add `nixSettings` configuration item, to more easily configure Nix settings such as `substituters`, overriding the system Nix settings.
+ - Cachix 1.7.2 support
+
+### Fixed
+
+ - Remove most uses of `c_str()`, of which at least one exhibited undefined behavior.
+ - `nix-darwin` module now reads `system` correctly from the configuration.
+
 ## [0.10.1] - 2024-02-12
 
 ### Changed
diff --git a/cbits/hercules-error.cxx b/cbits/hercules-error.cxx
--- a/cbits/hercules-error.cxx
+++ b/cbits/hercules-error.cxx
@@ -1,5 +1,8 @@
 #include "hercules-error.hh"
+#include "hercules-ci-cnix/string.hxx"
 
+using namespace hercules_ci_cnix;
+
 void
 hercules::copyErrorStrings(const nix::Error &err, const char **msgStrPtr, const char **traceStrPtr) noexcept {
     std::string msg;
@@ -7,7 +10,7 @@
         std::stringstream s;
         nix::showErrorInfo(s, err.info(), false);
         msg = s.str();
-        *msgStrPtr = strdup(msg.c_str());
+        *msgStrPtr = stringdup(msg);
     }
 
     // There's no method for getting just the trace, short of
@@ -24,6 +27,6 @@
             t = nix::trim(t);
         }
 
-        *traceStrPtr = strdup(t.c_str());
+        *traceStrPtr = stringdup(t);
     }
 }
diff --git a/data/default-herculesCI-for-flake.nix b/data/default-herculesCI-for-flake.nix
--- a/data/default-herculesCI-for-flake.nix
+++ b/data/default-herculesCI-for-flake.nix
@@ -52,7 +52,10 @@
     then attrs: attrs
     else intersectAttrs ciSystems;
 
-  getSystemNixDarwin = sys: sys.config.nixpkgs.system;
+  getSystemNixDarwin = sys:
+    if sys?options.nixpkgs.hostPlatform && sys.options.nixpkgs.hostPlatform.isDefined
+    then sys.config.nixpkgs.buildPlatform.system
+    else sys.config.nixpkgs.localSystem.system or sys.config.nixpkgs.system;
 
   getSystemNixOS = sys:
     if sys?options.nixpkgs.hostPlatform && sys.options.nixpkgs.hostPlatform.isDefined
diff --git a/hercules-ci-agent-worker/Hercules/Agent/Worker.hs b/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
--- a/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
+++ b/hercules-ci-agent-worker/Hercules/Agent/Worker.hs
@@ -11,7 +11,6 @@
 
 import Conduit
 import Control.Concurrent.STM hiding (check)
-import Control.Monad.Except
 import Control.Monad.IO.Unlift
 import Data.Aeson qualified as A
 import Data.Binary qualified as B
diff --git a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Logger.hs b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Logger.hs
--- a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Logger.hs
+++ b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Logger.hs
@@ -41,12 +41,16 @@
 
 C.include "<nix/globals.hh>"
 
+C.include "<hercules-ci-cnix/string.hxx>"
+
 C.include "hercules-aliases.h"
 
 C.include "hercules-logger.hh"
 
 C.using "namespace nix"
 
+C.using "namespace hercules_ci_cnix"
+
 initLogger :: IO ()
 initLogger =
   [C.throwBlock| void {
@@ -134,11 +138,11 @@
         const HerculesLogger::LogEntry &ln = *$(HerculesLoggerEntry *logEntryPtr);
         switch (ln.entryType) {
           case 1:
-            *$(const char **textStrPtr) = strdup(ln.text.c_str());
+            *$(const char **textStrPtr) = stringdup(ln.text);
             *$(int *levelPtr) = ln.level;
             return ln.entryType;
           case 2:
-            *$(const char **textStrPtr) = strdup(ln.text.c_str());
+            *$(const char **textStrPtr) = stringdup(ln.text);
             *$(int *levelPtr) = ln.level;
             *$(uint64_t *activityIdPtr) = ln.activityId;
             *$(uint64_t *typePtr) = ln.type;
@@ -229,7 +233,7 @@
             *$(uint64_t *uintPtr) = field.i;
             return 0;
           case nix::Logger::Field::tString:
-            *$(const char **stringPtr) = strdup(field.s.c_str());
+            *$(const char **stringPtr) = stringdup(field.s);
             return 1;
           default:
             return -1;
diff --git a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
--- a/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
+++ b/hercules-ci-agent-worker/Hercules/Agent/Worker/Build/Prefetched.hs
@@ -58,8 +58,12 @@
 
 C.include "<hercules-ci-cnix/store.hxx>"
 
+C.include "<hercules-ci-cnix/string.hxx>"
+
 C.using "namespace nix"
 
+C.using "namespace hercules_ci_cnix"
+
 data BuildStatus
   = Built
   | Substituted
@@ -172,7 +176,7 @@
           printError(e.msg());
           status = -2;
           success = false;
-          errorMessage = strdup(e.msg().c_str());
+          errorMessage = stringdup(e.msg());
           startTime = 0;
           stopTime = 0;
         }
@@ -236,7 +240,7 @@
         }
         printError(result.errorMsg);
         success = result.success();
-        errorMessage = strdup(result.errorMsg.c_str());
+        errorMessage = stringdup(result.errorMsg);
         startTime = result.startTime;
         stopTime = result.stopTime;
       }
diff --git a/hercules-ci-agent.cabal b/hercules-ci-agent.cabal
--- a/hercules-ci-agent.cabal
+++ b/hercules-ci-agent.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.4
 
 name:           hercules-ci-agent
-version:        0.10.1
+version:        0.10.2
 synopsis:       Runs Continuous Integration tasks on your machines
 category:       Nix, CI, Testing, DevOps
 homepage:       https://docs.hercules-ci.com
@@ -267,7 +267,7 @@
     , filepath
     , hercules-ci-agent
     , hercules-ci-api
-    , hercules-ci-api-core == 0.1.6.0
+    , hercules-ci-api-core == 0.1.7.0
     , hercules-ci-api-agent == 0.5.1.0
     , hostname
     , http-client
diff --git a/hercules-ci-agent/Hercules/Agent/Cachix.hs b/hercules-ci-agent/Hercules/Agent/Cachix.hs
--- a/hercules-ci-agent/Hercules/Agent/Cachix.hs
+++ b/hercules-ci-agent/Hercules/Agent/Cachix.hs
@@ -25,6 +25,9 @@
 import qualified Hercules.Formats.CachixCache as CachixCache
 import Protolude
 import qualified Hercules.CNix as CNix
+#if MIN_VERSION_cachix(1,7,2)
+import qualified Cachix.Client.OptionsParser as Opts
+#endif
 
 push :: CNix.Store -> Text -> [StorePath] -> Int -> App ()
 push nixStore cache paths workers = withNamedContext "cache" cache $ do
@@ -76,6 +79,10 @@
 #endif
 #if MIN_VERSION_cachix(1,6,0)
                       onUncompressedNARStream = \_ _ -> Conduit.awaitForever Conduit.yield,
+#endif
+#if MIN_VERSION_cachix(1,7,2)
+                      chunkSize = Opts.defaultChunkSize,
+                      numConcurrentChunks = Opts.defaultNumConcurrentChunks,
 #endif
                       omitDeriver = False
                     }
diff --git a/hercules-ci-agent/Hercules/Agent/Client.hs b/hercules-ci-agent/Hercules/Agent/Client.hs
--- a/hercules-ci-agent/Hercules/Agent/Client.hs
+++ b/hercules-ci-agent/Hercules/Agent/Client.hs
@@ -20,7 +20,6 @@
 import Hercules.API.Agent.Build (BuildAPI)
 import Hercules.API.Agent.Evaluate (EvalAPI)
 import Hercules.API.Agent.LifeCycle (LifeCycleAPI)
-import Hercules.API.Agent.State (ContentLength)
 import Hercules.API.Agent.Tasks (TasksAPI)
 import Hercules.API.Logs (LogsAPI)
 import Hercules.API.Servant (useApi)
diff --git a/hercules-ci-agent/Hercules/Agent/Config.hs b/hercules-ci-agent/Hercules/Agent/Config.hs
--- a/hercules-ci-agent/Hercules/Agent/Config.hs
+++ b/hercules-ci-agent/Hercules/Agent/Config.hs
@@ -25,7 +25,8 @@
 import Data.Profunctor (Star (Star))
 import GHC.Conc (getNumProcessors)
 import Hercules.Agent.Config.Combined
-import Hercules.Agent.Config.Json as Json
+import Hercules.Agent.Config.Json (GCodec (GCodec), (.=.))
+import Hercules.Agent.Config.Json qualified as Json
 import Hercules.Agent.Config.Toml qualified as Toml
 import Hercules.CNix.Verbosity (Verbosity (..))
 import Hercules.Formats.Mountable (Mountable (Mountable))
@@ -72,7 +73,8 @@
     labels :: Item purpose 'Required (Map Text A.Value),
     allowInsecureBuiltinFetchers :: Item purpose 'Required Bool,
     remotePlatformsWithSameFeatures :: Item purpose 'Optional [Text],
-    effectMountables :: Map Text Mountable
+    effectMountables :: Map Text Mountable,
+    nixSettings :: Map Text Text
   }
   deriving (Generic)
 
@@ -120,6 +122,9 @@
           (Json.tableMap' (forJson mountableCodec) "effectMountables")
       )
       .=. effectMountables
+    <*> optEmpty
+      (tableMap textAtKey "nixSettings")
+      .=. nixSettings
 
 mountableCodec :: Combi' Mountable
 mountableCodec =
@@ -233,5 +238,6 @@
         labels = fromMaybe mempty $ labels input,
         allowInsecureBuiltinFetchers = fromMaybe False $ allowInsecureBuiltinFetchers input,
         remotePlatformsWithSameFeatures = remotePlatformsWithSameFeatures input,
-        effectMountables = effectMountables input
+        effectMountables = effectMountables input,
+        nixSettings = nixSettings input
       }
diff --git a/hercules-ci-agent/Hercules/Agent/Config/Combined.hs b/hercules-ci-agent/Hercules/Agent/Config/Combined.hs
--- a/hercules-ci-agent/Hercules/Agent/Config/Combined.hs
+++ b/hercules-ci-agent/Hercules/Agent/Config/Combined.hs
@@ -46,3 +46,6 @@
 
 enumBoundedAtKey :: (Bounded a, Enum a, Show a) => Key -> Combi' a
 enumBoundedAtKey k = Combi (Data.Bifunctor.Product.Pair (Toml.enumBounded k) (Json.enumBounded k))
+
+tableMap :: (Key -> Combi' a) -> Key -> Combi' (Map Text a)
+tableMap c k = Combi $ Pair (Toml.tableMap Toml._KeyText (forToml . c) k) (Json.tableMap (forJson . c) k)
diff --git a/hercules-ci-agent/Hercules/Agent/Config/Json.hs b/hercules-ci-agent/Hercules/Agent/Config/Json.hs
--- a/hercules-ci-agent/Hercules/Agent/Config/Json.hs
+++ b/hercules-ci-agent/Hercules/Agent/Config/Json.hs
@@ -39,6 +39,7 @@
     dimap,
     first,
     match,
+    tableMap,
     _EnumBounded,
     _Text,
     _TextBy,
@@ -250,12 +251,30 @@
   Key ->
   JsonCodec' (Map Text v)
 tableMap' valCodec key =
+  tableMap
+    ( \k ->
+        GCodec
+          { gRead =
+              local
+                (\v -> fromMaybe (panic "tableMap': key disappeared") (v ^? at' k))
+                (gRead valCodec),
+            gWrite = do
+              panic "tableMap': write not implemented"
+          }
+    )
+    key
+
+tableMap ::
+  (Key -> JsonCodec' v) ->
+  Key ->
+  JsonCodec' (Map Text v)
+tableMap valCodec key =
   let c = match (prismWithError "JSON Object expected" (Aeson.Lens._Object . aesonMap)) key
    in GCodec
         { gRead = do
             x <- gRead c
-            fmap M.fromList $ for (M.toList x) $ \(k, v) -> do
-              v' <- local (const v) $ gRead valCodec
+            fmap M.fromList $ for (M.toList x) $ \(k, _v) -> do
+              v' <- gRead (valCodec (key <> (Key $ Piece k :| [])))
               pure (k, v'),
           gWrite = do
             panic "tableMap': write not implemented"
diff --git a/hercules-ci-agent/Hercules/Agent/Init.hs b/hercules-ci-agent/Hercules/Agent/Init.hs
--- a/hercules-ci-agent/Hercules/Agent/Init.hs
+++ b/hercules-ci-agent/Hercules/Agent/Init.hs
@@ -40,7 +40,7 @@
   concPushes <- newMemo
   concQueries <- newMemo
   withLogging $ Hercules.Agent.Cachix.Init.withEnv config (BC.cachixCaches bcs) \cachix -> liftIO do
-    nix <- Hercules.Agent.Nix.Init.newEnv
+    nix <- Hercules.Agent.Nix.Init.newEnv config
     serviceInfo <- ServiceInfo.newEnv clientEnv
     let env =
           Env
diff --git a/hercules-ci-agent/Hercules/Agent/Nix/Init.hs b/hercules-ci-agent/Hercules/Agent/Nix/Init.hs
--- a/hercules-ci-agent/Hercules/Agent/Nix/Init.hs
+++ b/hercules-ci-agent/Hercules/Agent/Nix/Init.hs
@@ -1,11 +1,19 @@
+{-# LANGUAGE DataKinds #-}
+
 module Hercules.Agent.Nix.Init where
 
+import Data.Map qualified as M
+import Hercules.Agent.Config (Config, Purpose (Final))
+import Hercules.Agent.Config qualified
 import Hercules.Agent.EnvironmentInfo qualified as EnvironmentInfo
 import Hercules.Agent.Nix.Env
+import Hercules.CNix qualified as CNix
 import Protolude
 
-newEnv :: IO Env
-newEnv = do
+newEnv :: Config 'Final -> IO Env
+newEnv config = do
+  for_ (M.toList config.nixSettings) $ \(k, v) -> do
+    CNix.setGlobalOption k v
   nixInfo <- EnvironmentInfo.getNixInfo
   when (EnvironmentInfo.nixNarinfoCacheNegativeTTL nixInfo /= 0) $ do
     putErrText
@@ -33,5 +41,5 @@
   -- extraOptions here.
   pure
     Env
-      { extraOptions = []
+      { extraOptions = M.toList config.nixSettings
       }
diff --git a/test/Hercules/Agent/ConfigSpec.hs b/test/Hercules/Agent/ConfigSpec.hs
--- a/test/Hercules/Agent/ConfigSpec.hs
+++ b/test/Hercules/Agent/ConfigSpec.hs
@@ -45,6 +45,8 @@
                   "workDirectory = \"/var/lib/hercules-ci-agent/work\"",
                   "remotePlatformsWithSameFeatures = [\"aarch64-darwin\"]",
                   "nixVerbosity = \"vomit\"",
+                  "[nixSettings]",
+                  "  substituters = \"https://example.com\"",
                   -- This line should not be needed!
                   "[effectMountables]",
                   "[effectMountables.hosts]",
@@ -91,7 +93,8 @@
                               condition = Hercules.Formats.Secret.Const True
                             }
                         )
-                      ]
+                      ],
+                  nixSettings = M.singleton "substituters" "https://example.com"
                 }
             )
       it "parses empty config" $ do
@@ -119,6 +122,7 @@
                   "\"secretsJsonPath\": \"/var/lib/hercules-ci-agent/secrets/secrets.json\",",
                   "\"logLevel\": \"DebugS\",",
                   "\"nixVerbosity\": \"Vomit\",",
+                  "\"nixSettings\": { \"substituters\": \"https://example.com\" },",
                   "\"remotePlatformsWithSameFeatures\": [\"aarch64-darwin\"],",
                   "\"labels\": {",
                   "  \"agent\": {\"source\": \"flake\"},",
@@ -169,7 +173,8 @@
                             condition = Hercules.Formats.Secret.Const True
                           }
                       )
-                    ]
+                    ],
+                nixSettings = M.singleton "substituters" "https://example.com"
               }
 
       it "handles empty config" $ do
@@ -232,5 +237,6 @@
       labels = Nothing,
       allowInsecureBuiltinFetchers = Nothing,
       remotePlatformsWithSameFeatures = Nothing,
-      effectMountables = mempty
+      effectMountables = mempty,
+      nixSettings = mempty
     }
