A Photograph of the City of London, with St Paul's Cathedral, and construction cranes, the Millenium bridge in the forefront. Picture taken by the author from the SouthBank.

The City of London being reconfigured.

Configuring a public MoneyMachine

money-machine Sep 22, 2025

Every program needs configuration. Code cannot hard-code its paths, environments, or operational parameters if it is meant to run anywhere beyond a single developer’s machine. Configuration is the layer where intent is declared: which machine is being targeted, which environment is in play, and which parameters should govern execution.

When a project grows beyond one person, or when it is intended to be reproducible across time and context, configuration becomes indispensable. But how we manage it matters.

In Money Ex Machina, we introduced mxm-config to solve three core challenges:

1. Building in Public, Running in Private

The Money Machine is designed as a public project. All its architecture, package contracts, and design principles are open for inspection. Anyone should be able to see how it works, learn from it, and even build their own machine with the same parts.

At the same time, the actual deployment of the Money Machine is private. The servers I use, the local overrides I apply, and the secrets I hold cannot and should not be published.

By making configuration, secrets, and runtime metadata into separate, explicit packages, we draw a clean line:

  • Public: the structure, layering, and contracts (mxm-config).
  • Private: the actual values (local.yaml, secret keys, runtime logs).

This separation allows the framework to be open while the instance remains private. You can see the machine, but not the wiring of my personal installation.

2. Preventing Configuration Drift

Without discipline, every project drifts. Developers add ad hoc YAML files, .env variables, and quick local hacks. Soon, it only works on one laptop, under one set of assumptions, and nobody remembers how it was meant to run.

mxm-config enforces a clean layering model. Each layer has a defined purpose, is always applied in a documented order, and never bleeds into another. This means reproducibility: the same context always produces the same resolved config.

3. Multi-User and Multi-Package Collaboration

The Money Machine is not a single script but a system. It will have many packages, many contributors, and many different environments where it is deployed. For such a system, a shared configuration standard is not optional, it is foundational.

With mxm-config, every package follows the same rules for loading, layering, and resolving configuration. New users or contributors immediately know how to set up their environment. New packages integrate smoothly without reinventing config logic.

How mxm-config works

mxm-config does not ship opinionated configs of its own (other than the demo). Instead, it declares a contract: every MXM package or application must provide the same set of configuration layers.

These layers are merged in a fixed hierarchical order:

  1. default.yaml
    The baseline shipped with the package. Always present, ensures the config is valid out of the box.
  2. environment.yaml
    Deployment context (dev, staging, prod). Captures broad operational differences.
  3. machine.yaml
    Host-specific overrides, such as filesystem paths, mount points, or GPU resources.
  4. profile.yaml
    Role or user context (research, production, public). Controls scope and feature availability.
  5. local.yaml
    Local scratchpad for private tweaks, never version controlled.
  6. Explicit overrides
    A dictionary passed at runtime for programmatic modifications.

Each package that uses mxm-config ships its own set of YAMLs under these filenames. mxm-config then layers them in the declared order and freezes the merged result.

Because it is powered by OmegaConf, configs are not only merged but also interpolated: higher-level settings can parameterize lower-level ones. This makes it easy to declare context-dependent paths or values like:

paths:
  output: "${paths.base_output}/${mxm_env}/${mxm_profile}"

which automatically expands into the correct path once all layers are resolved.

In this way, mxm-config is more than a loader — it is a configuration contract: a repeatable, multi-dimensional way to declare, combine, and resolve the operational context of any MXM package.

Design Principles

  • Separation of concerns
    Config ≠ secrets ≠ runtime metadata. Each has its own package and contract.
  • Determinism
    Same context → same resolved config. Always reproducible.
  • Transparency
    Configs are plain YAML files. No hidden state, no magic.
  • Extensibility
    Minimal orthogonal layers, easy to extend without breaking others.

Example

The repository ships with a demo_config package to show layering in action.

from mxm_config.loader import load_config

cfg = load_config("demo", env="dev", profile="research")
print(cfg.paths.output)
print(cfg.parameters.refresh_interval)

Output might look like:

/mnt/wildling/demo_output/dev/research
30min

This shows how machine, environment, and profile combine to produce a reproducible, context-aware configuration.

Roadmap

mxm-config is the foundation, but not the end:

  • Schema validation to enforce contracts.
  • CLI (mxm-config install demo_config).
  • Integration with mxm-runtime for provenance.
  • Config hashing for reproducibility and audit.

Conclusion

The Money Machine is built in public, but run in private.
To make that possible, configuration must be explicit, layered, and reproducible.

mxm-config is the first building block of that philosophy: the contract that ensures every package, every run, and every user speaks the same configuration language.

The package is available on Github.

Tags