Repository: bacalhau-project/bacalhau (language: python)

Issue:
drat: first pass at decoupling the repo and config paths
closes: https://github.com/bacalhau-project/bacalhau/issues/4219

## Background:
At present the bacalhau config contains several fields that allow paths to location on disk to be set, these fields include, but are not limited to:
- KeyPath: https://github.com/bacalhau-project/bacalhau/blob/50831fa55c96660fdc573aab4a4441f10d9f6000/pkg/config/types/config.go#L14
- ExecutorPluginPath: https://github.com/bacalhau-project/bacalhau/blob/50831fa55c96660fdc573aab4a4441f10d9f6000/pkg/config/types/node.go#L21
- ComputeStoragePath: https://github.com/bacalhau-project/bacalhau/blob/50831fa55c96660fdc573aab4a4441f10d9f6000/pkg/config/types/node.go#L24
- StoreDir: https://github.com/bacalhau-project/bacalhau/blob/50831fa55c96660fdc573aab4a4441f10d9f6000/pkg/config/types/node.go#L123

If a user doesn't set a value for these fields in the config, bacalhau will set them to default values under the repo path: 
https://github.com/bacalhau-project/bacalhau/blob/50831fa55c96660fdc573aab4a4441f10d9f6000/pkg/repo/fs.go#L216-L229

This setup tightly couples the repo and config: in order for a config to be correctly populate it must first be modified by the repo to set paths accordingly in the event that are not provided. In order for a repo to be initialized it requires a config. 
This means the vanilla config returned by config.New() isn't actually usable by a bacalhau node until it has been passed to a repo. 


### Proposed Change
This draft removes usage of `*Path` fields defined in the bacalhau configuration structure. Meaning the config file no longer dictates the location on disk of various files and directories. Instead these paths are defined as constants declared with in the config package. When a service such as transport, compute, or requester require a path on disk they may retrieve it from the config package, at which point the value will be created, or returned if it already exists.

Exceptions:
The following `*Path` fields will still remain present in the config:
- All paths in the TLSConfiguration, these values are optional when running bacalhau.
- `Metrics.EventTracerPath` - we currently always set this field to `os.DevNull` - perhaps it would make sense to remove it entirely and its related event tracer since its never used.
- `AuthConfig.AccessPolicy` - bacalhau provides a verity of access policies in the form of .rego files, and users will likely want to fiddle with this value, further its optional.
- `AuthentiatorConfig.PolicyPath` - same story as `AccessPolicy` 
Provide a single config key that may be used to set the ipfs endpoint across publishers, input sources, and downloaders.
> Having different config keys to configure ipfs connect is not the best ux, the same applies to s3 input source and publisher config. Please create an issue to have a quick follow up on this hopefully before 1.5. Lets not try to solve this as part of this PR

-https://github.com/bacalhau-project/bacalhau/pull/4333/files#r1740757960


Discussion / hints:
<!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on this repository.
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai --><!-- tips_start -->

---





<details>
<summary>Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
	- `I pushed a fix in commit <commit_id>.`
	- `Generate unit testing code for this file.`
	- `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
	- `@coderabbitai generate unit testing code for this file.`
	-	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
	- `@coderabbitai generate interesting stats about this repository and render them as a table.`
	- `@coderabbitai show all the console.log statements in this repository.`
	- `@coderabbitai read src/utils.ts and generate unit testing code.`
	- `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
	- `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (invoked as PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.


Additionally, you can add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://coderabbit.ai/docs) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](https://discord.com/invite/GsXnASn26c) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->


Fix patch:
diff --git a/cmd/cli/config/auto.go b/cmd/cli/config/auto.go
deleted file mode 100644
index 91663b6f91..0000000000
--- a/cmd/cli/config/auto.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package config
-
-import (
-	"context"
-	"fmt"
-	"strconv"
-
-	"github.com/BTBurke/k8sresource"
-	"github.com/dustin/go-humanize"
-	"github.com/spf13/cobra"
-	"github.com/spf13/pflag"
-
-	"github.com/bacalhau-project/bacalhau/cmd/util"
-	"github.com/bacalhau-project/bacalhau/cmd/util/hook"
-	"github.com/bacalhau-project/bacalhau/pkg/compute/capacity/system"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-const (
-	defaultTotalPercentage      = 75
-	defaultJobPercentage        = 75
-	defaultDefaultJobPercentage = 75
-	defaultQueuePercentage      = defaultJobPercentage * 2
-
-	oneHundredPercent = 100
-)
-
-type autoSettings struct {
-	TotalPercentage   int
-	JobPercentage     int
-	DefaultPercentage int
-	QueuePercentage   int
-}
-
-func autoFlags(settings *autoSettings) *pflag.FlagSet {
-	flags := pflag.NewFlagSet("Auto configuration setting", pflag.ContinueOnError)
-	flags.IntVar(&settings.TotalPercentage,
-		"total-percentage",
-		defaultTotalPercentage,
-		//nolint:goconst
-		"Percentage expressed as a number from 1 to 100 representing "+
-			"total amount of resource the system can be using at one time in aggregate for all jobs "+
-			"(values over 100 will be rejected)")
-	flags.IntVar(&settings.JobPercentage,
-		"job-percentage",
-		defaultJobPercentage,
-		"Percentage expressed as a number from 1 to 100 representing "+
-			"per job amount of resource the system can be using at one time for a single job "+
-			"(values over 100 will be rejected)")
-	flags.IntVar(&settings.DefaultPercentage,
-		"default-job-percentage",
-		defaultDefaultJobPercentage,
-		"Percentage expressed as a number from 1 to 100 representing "+
-			"default per job amount of resources jobs will get when they don't specify any resource limits themselves "+
-			"(values over 100 will be rejected")
-	flags.IntVar(&settings.QueuePercentage,
-		"queue-job-percentage",
-		defaultQueuePercentage,
-		"Percentage expressed as a number from 1 to 100 representing the total amount of resource the system "+
-			"can queue at one time in aggregate for all jobs (values over 100 are accepted)")
-	return flags
-}
-
-func (a *autoSettings) validate() error {
-	if a.TotalPercentage == 0 {
-		return fmt.Errorf("total-percentage must be greater than 0")
-	}
-	if a.TotalPercentage > oneHundredPercent {
-		return fmt.Errorf("total-percentage cannot exceed 100")
-	}
-	if a.JobPercentage == 0 {
-		return fmt.Errorf("job-percentage must be greater than 0")
-	}
-	if a.JobPercentage > oneHundredPercent {
-		return fmt.Errorf("job-percentage cannot exceed 100")
-	}
-	if a.JobPercentage > a.TotalPercentage {
-		return fmt.Errorf("job-percentage must be less than or equal to total-percentage")
-	}
-	if a.DefaultPercentage == 0 {
-		return fmt.Errorf("default-job-percentage must be greater than 0")
-	}
-	if a.DefaultPercentage > oneHundredPercent {
-		return fmt.Errorf("default-job-percentage cannot exceed 100")
-	}
-	if a.DefaultPercentage > a.TotalPercentage {
-		return fmt.Errorf("default-job-percentage must be less than or equal to total-percentage")
-	}
-	return nil
-}
-
-func newAutoResourceCmd() *cobra.Command {
-	settings := new(autoSettings)
-	autoCmd := &cobra.Command{
-		Use:      "auto-resources [flags]",
-		Short:    "Auto set compute resources values in the config.",
-		Args:     cobra.MinimumNArgs(0),
-		PreRunE:  hook.ClientPreRunHooks,
-		PostRunE: hook.ClientPostRunHooks,
-		RunE: func(cmd *cobra.Command, args []string) error {
-			if err := settings.validate(); err != nil {
-				return err
-			}
-			// initialize a new or open an existing repo merging any config file(s) it contains into cfg.
-			cfg, err := util.SetupRepoConfig(cmd)
-			if err != nil {
-				return fmt.Errorf("failed to setup repo: %w", err)
-			}
-			return autoConfig(cmd.Context(), cfg, settings)
-		},
-	}
-
-	autoCmd.PersistentFlags().AddFlagSet(autoFlags(settings))
-
-	return autoCmd
-}
-
-func autoConfig(ctx context.Context, cfg types.BacalhauConfig, settings *autoSettings) error {
-	executionDir, err := cfg.ExecutionDir()
-	if err != nil {
-		return err
-	}
-	pp := system.NewPhysicalCapacityProvider(executionDir)
-	physicalResources, err := pp.GetTotalCapacity(ctx)
-	if err != nil {
-		return fmt.Errorf("failed to calculate system physical resources: %w", err)
-	}
-
-	if err := setResources(types.NodeComputeCapacityTotalResourceLimits, settings.TotalPercentage, physicalResources); err != nil {
-		return err
-	}
-	if err := setResources(types.NodeComputeCapacityJobResourceLimits, settings.JobPercentage, physicalResources); err != nil {
-		return err
-	}
-	if err := setResources(types.NodeComputeCapacityDefaultJobResourceLimits, settings.DefaultPercentage, physicalResources); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func setResources(key string, percentageValue int, resources models.Resources) error {
-	percentage := float64(percentageValue) * .01
-	if err := setConfig(fmt.Sprintf("%s.CPU", key), k8sresource.NewCPUFromFloat(resources.CPU*percentage).ToString()); err != nil {
-		return err
-	}
-	if err := setConfig(fmt.Sprintf("%s.Memory", key), humanize.Bytes(uint64(float64(resources.Memory)*percentage))); err != nil {
-		return err
-	}
-	if err := setConfig(fmt.Sprintf("%s.Disk", key), humanize.Bytes(uint64(float64(resources.Disk)*percentage))); err != nil {
-		return err
-	}
-	// NB(forrest): we use an int64 to represent number of GPUs on a system, max value is roughly nine quintillion
-	// we are downcasting it to an int with a max value of ~two billion, if there are ever this many GPUs let us
-	// celebrate the panic this will cause.
-	if err := setConfig(fmt.Sprintf("%s.GPU", key), strconv.Itoa(int(resources.GPU))); err != nil {
-		return err
-	}
-	return nil
-}
diff --git a/cmd/cli/config/config.go b/cmd/cli/config/config.go
index a4c02c1484..d49e069d16 100644
--- a/cmd/cli/config/config.go
+++ b/cmd/cli/config/config.go
@@ -13,8 +13,7 @@ func NewCmd() *cobra.Command {
 		PreRunE:  hook.ClientPreRunHooks,
 		PostRunE: hook.ClientPostRunHooks,
 	}
-	configCmd.AddCommand(newListCmd())
 	configCmd.AddCommand(newSetCmd())
-	configCmd.AddCommand(newAutoResourceCmd())
+	configCmd.AddCommand(newListCmd())
 	return configCmd
 }
diff --git a/cmd/cli/config/list.go b/cmd/cli/config/list.go
index b5f97a384a..63af9306af 100644
--- a/cmd/cli/config/list.go
+++ b/cmd/cli/config/list.go
@@ -7,10 +7,10 @@ import (
 	"github.com/jedib0t/go-pretty/v6/text"
 	"github.com/spf13/cobra"
 
-	"github.com/bacalhau-project/bacalhau/cmd/util"
 	"github.com/bacalhau-project/bacalhau/cmd/util/flags/cliflags"
 	"github.com/bacalhau-project/bacalhau/cmd/util/hook"
 	"github.com/bacalhau-project/bacalhau/cmd/util/output"
+	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
@@ -29,12 +29,6 @@ func newListCmd() *cobra.Command {
 		PreRunE:  hook.ClientPreRunHooks,
 		PostRunE: hook.ClientPostRunHooks,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			// initialize a new or open an existing repo. We need to ensure the config
-			// has been initialized so that the current values of it are displayed in the list command.
-			_, err := util.SetupRepoConfig(cmd)
-			if err != nil {
-				return fmt.Errorf("failed to setup repo: %w", err)
-			}
 			return list(cmd, o)
 		},
 	}
@@ -44,6 +38,7 @@ func newListCmd() *cobra.Command {
 
 type configListEntry struct {
 	Key         string
+	EnvVar      string
 	Description string
 }
 
@@ -56,6 +51,7 @@ func list(cmd *cobra.Command, o output.OutputOptions) error {
 	for key, description := range types.ConfigDescriptions {
 		cfgList = append(cfgList, configListEntry{
 			Key:         key,
+			EnvVar:      config.KeyAsEnvVar(key),
 			Description: description,
 		})
 	}
@@ -75,7 +71,13 @@ var listColumns = []output.TableColumn[configListEntry]{
 		},
 	},
 	{
-		ColumnConfig: table.ColumnConfig{Name: "Description", WidthMax: 40, WidthMaxEnforcer: text.WrapHard},
+		ColumnConfig: table.ColumnConfig{Name: "Environment Variable", WidthMax: 80, WidthMaxEnforcer: text.WrapHard},
+		Value: func(v configListEntry) string {
+			return fmt.Sprintf("%v", v.EnvVar)
+		},
+	},
+	{
+		ColumnConfig: table.ColumnConfig{Name: "Description", WidthMax: 80, WidthMaxEnforcer: text.WrapText},
 		Value: func(v configListEntry) string {
 			return fmt.Sprintf("%v", v.Description)
 		},
diff --git a/cmd/cli/config/set.go b/cmd/cli/config/set.go
index d0914507f1..1374ac04d8 100644
--- a/cmd/cli/config/set.go
+++ b/cmd/cli/config/set.go
@@ -4,31 +4,27 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
-	"strconv"
 	"strings"
-	"time"
 
+	"github.com/rs/zerolog/log"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
-	"golang.org/x/exp/slices"
-	"gopkg.in/yaml.v3"
 
 	"github.com/bacalhau-project/bacalhau/cmd/util"
 	"github.com/bacalhau-project/bacalhau/cmd/util/hook"
-	"github.com/bacalhau-project/bacalhau/cmd/util/parse"
 	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
+	util2 "github.com/bacalhau-project/bacalhau/pkg/storage/util"
 )
 
 func newSetCmd() *cobra.Command {
-	showCmd := &cobra.Command{
-		Use:      "set",
-		Args:     cobra.MinimumNArgs(2),
-		Short:    "Set a value in the config.",
-		PreRunE:  hook.ClientPreRunHooks,
-		PostRunE: hook.ClientPostRunHooks,
+	setCmd := &cobra.Command{
+		Use:          "set",
+		Args:         cobra.MinimumNArgs(2),
+		Short:        "Set a value in the config.",
+		PreRunE:      hook.ClientPreRunHooks,
+		PostRunE:     hook.ClientPostRunHooks,
+		SilenceUsage: true,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			// initialize a new or open an existing repo. We need to ensure a repo
 			// exists before we can create or modify a config file in it.
@@ -36,132 +32,63 @@ func newSetCmd() *cobra.Command {
 			if err != nil {
 				return fmt.Errorf("failed to setup repo: %w", err)
 			}
-			return setConfig(args[0], args[1:]...)
+			return setConfig(cmd.PersistentFlags().Lookup("config").Value.String(), args[0], args[1:]...)
 		},
-	}
-	return showCmd
-}
-
-func currentValue(key string) (interface{}, error) {
-	// get the default viper schema
-	viperSchema := NewViperWithDefaultConfig(config.ForEnvironment())
-	// get a list of all valid configuration keys, same list as returned by `config list`
-	liveKeys := viperSchema.AllKeys()
-	if !slices.Contains(liveKeys, key) {
-		return nil, fmt.Errorf("invalid configuration key %q: not found", key)
+		// provide auto completion for arguments to the `set` command
+		ValidArgsFunction: setAutoComplete,
 	}
 
-	// calling `Get` on this instance will return a default value from the config structure that we can type assert on.
-	return viperSchema.Get(key), nil
-}
+	bacalhauCfgDir := "bacalhau"
+	bacalhauCfgFile := config.DefaultFileName
 
-func getWriter(configFile string) (*viper.Viper, error) {
-	viperWriter := viper.New()
-	viperWriter.SetTypeByDefaultValue(true)
-	viperWriter.SetConfigFile(configFile)
-	// the instance has read in a copy of the config file
-	if err := viperWriter.ReadInConfig(); err != nil {
-		if !os.IsNotExist(err) {
-			return nil, err
+	usrCfgDir, err := os.UserConfigDir()
+	if err != nil {
+		log.Warn().Err(err).Msg("Failed to find user-specific configuration directory. Using current directory to write config.")
+	} else {
+		bacalhauCfgDir = filepath.Join(usrCfgDir, bacalhauCfgDir)
+		if err := os.MkdirAll(bacalhauCfgDir, util2.OS_USER_RWX); err != nil {
+			// This means we failed to create a directory either in the current directory, or the user config dir
+			// indicating a some-what serious misconfiguration of the system. We panic here to provide as much
+			// detail as possible.
+			log.Panic().Err(err).Msgf("Failed to create bacalhau configuration directory: %s", bacalhauCfgDir)
 		}
+		bacalhauCfgFile = filepath.Join(bacalhauCfgDir, bacalhauCfgFile)
 	}
-	return viperWriter, nil
-}
 
-func setConfig(key string, values ...string) error {
-	// remove all spaces and make lowercase
-	key = sanitizeKey(key)
+	setCmd.PersistentFlags().String("config", bacalhauCfgFile, "Path to the config file")
+	return setCmd
+}
 
-	// we need special handling for the nodetype since its just a string, but carries implicit requirements in the config.
-	if strings.EqualFold(types.NodeType, key) {
-		if !validNodeTypes(values) {
-			return fmt.Errorf("setting: %q, invalid node type value: %q, must be one of: 'requester' 'compute' 'requester compute'", key, values)
+func setConfig(cfgFilePath, key string, value ...string) error {
+	v := viper.New()
+	v.SetConfigFile(cfgFilePath)
+	if err := v.ReadInConfig(); err != nil {
+		if !os.IsNotExist(err) {
+			return err
 		}
 	}
-
-	curValue, err := currentValue(key)
+	parsed, err := types.CastConfigValueForKey(key, value)
 	if err != nil {
 		return err
 	}
-
-	// there may me a config file present, we'll write to that if it exists.
-	configFile := viper.ConfigFileUsed()
-	if configFile == "" {
-		// if there isn't a config file, we'll assume we add it to the current repo.
-		configFile = filepath.Join(viper.GetString("repo"), "config.yaml")
-	}
-
-	viperWriter, err := getWriter(configFile)
-	if err != nil {
+	v.Set(key, parsed)
+	if err := v.WriteConfigAs(cfgFilePath); err != nil {
 		return err
 	}
 
-	switch curValue.(type) {
-	case []string:
-		viperWriter.Set(key, values)
-	case map[string]string:
-		sts, err := parse.StringSliceToMap(values)
-		if err != nil {
-			return err
-		}
-		viperWriter.Set(key, sts)
-	case map[string]types.AuthenticatorConfig:
-		cfg := struct {
-			Method string                    `yaml:"Method"`
-			Policy types.AuthenticatorConfig `yaml:"Policy"`
-		}{}
-		if err := yaml.Unmarshal([]byte(values[0]), &cfg); err != nil {
-			return err
-		}
-		methodNamePath := fmt.Sprintf("%s.%s", types.AuthMethods, cfg.Method)
-		viperWriter.Set(methodNamePath, cfg.Policy)
-	}
-
-	parser, err := getParser(curValue, key)
-	if parser == nil || err != nil {
-		return viperWriter.WriteConfig()
-	}
-
-	value, err := singleValueOrError(values...)
-	if err != nil {
-		return fmt.Errorf("setting %q: %w", key, err)
-	}
-
-	configValue, err := parser(value)
-	if err != nil {
-		return fmt.Errorf("setting %q: %w", key, err)
-	}
-	viperWriter.Set(key, configValue)
-	return viperWriter.WriteConfig()
+	return nil
 }
 
-type parserFunc func(string) (any, error)
-
-func getParser(curValue interface{}, key string) (parserFunc, error) {
-	var parser parserFunc
+func setAutoComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	var completions []string
 
-	switch curValue.(type) {
-	case string:
-		parser = func(s string) (any, error) { return s, nil } // identity by default
-	case bool:
-		parser = func(s string) (any, error) { return strconv.ParseBool(s) }
-	case int, int8, int16, int32, int64:
-		parser = func(s string) (any, error) { return strconv.ParseInt(s, 10, 64) }
-	case uint, uint8, uint16, uint32, uint64:
-		parser = func(s string) (any, error) { return strconv.ParseUint(s, 10, 64) }
-	case float32, float64:
-		parser = func(s string) (any, error) { return strconv.ParseFloat(s, 64) }
-	case types.Duration, time.Duration:
-		parser = func(s string) (any, error) { return time.ParseDuration(s) }
-	case models.JobSelectionDataLocality:
-		parser = func(s string) (any, error) { return models.ParseJobSelectionDataLocality(s) }
-	case logger.LogMode:
-		parser = func(s string) (any, error) { return logger.ParseLogMode(s) }
-	case types.StorageType:
-		parser = func(s string) (any, error) { return types.ParseStorageType(s) }
-	default:
-		return nil, fmt.Errorf("unsupported type %T for key: %q", curValue, key)
+	// Iterate over the ConfigDescriptions map to find matching keys
+	for key, description := range types.ConfigDescriptions {
+		if strings.HasPrefix(key, toComplete) {
+			completion := fmt.Sprintf("%s\t%s", key, description)
+			completions = append(completions, completion)
+		}
 	}
 
-	return parser, nil
+	return completions, cobra.ShellCompDirectiveNoSpace
 }
diff --git a/cmd/cli/config/util.go b/cmd/cli/config/util.go
deleted file mode 100644
index 664905d099..0000000000
--- a/cmd/cli/config/util.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package config
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/spf13/viper"
-
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-)
-
-// NewViperWithDefaultConfig create a viper instance to serve as a schema and load in the default configuration
-// to our viper schema instance. This method is useful for inspecting default config values.
-func NewViperWithDefaultConfig(cfg types.BacalhauConfig) *viper.Viper {
-	viperSchema := viper.New()
-	types.SetDefaults(cfg, types.WithViper(viperSchema))
-	return viperSchema
-}
-
-func singleValueOrError(v ...string) (string, error) {
-	if len(v) != 1 {
-		return "", fmt.Errorf("expected single value got %d from %q", len(v), v)
-	}
-	return v[0], nil
-}
-
-// validNodeTypes returns true of the slice params contains strictly valid node types, false otherwise.
-func validNodeTypes(slice []string) bool {
-	// if nothing not valid
-	if len(slice) == 0 {
-		return false
-	}
-	// if there are more than 2 things its wrong
-	if len(slice) > 2 {
-		return false
-	}
-	// if there is only one thing it must be a compute or requester
-	if len(slice) == 1 {
-		if slice[0] != "compute" && slice[0] != "requester" {
-			return false
-		}
-		return true
-	}
-	// there must be two things, one must be requester and the other must be compute
-	return validNodeType(slice[0]) && validNodeType(slice[1])
-}
-
-// validNodeType returns true if t is requester or compute false otherwise.
-func validNodeType(t string) bool {
-	if t != "compute" && t != "requester" {
-		return false
-	}
-	return true
-}
-
-// sanitizeKey transforms the provider keys by:
-// 1. Converting to lower case to make the matching case in-sensitive
-// 2. Trim spaces
-func sanitizeKey(key string) string {
-	s := strings.TrimSpace(key)
-	s = strings.ToLower(s)
-	return s
-}
diff --git a/cmd/cli/devstack/devstack.go b/cmd/cli/devstack/devstack.go
index 9e78f2b9f4..2dac65d703 100644
--- a/cmd/cli/devstack/devstack.go
+++ b/cmd/cli/devstack/devstack.go
@@ -10,8 +10,8 @@ import (
 	"k8s.io/kubectl/pkg/util/i18n"
 
 	"github.com/bacalhau-project/bacalhau/cmd/util/flags/configflags"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	baccrypto "github.com/bacalhau-project/bacalhau/pkg/lib/crypto"
 	"github.com/bacalhau-project/bacalhau/pkg/node"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
@@ -64,12 +64,9 @@ func NewCmd() *cobra.Command {
 	ODs := newDevStackOptions()
 	IsNoop := false
 	devstackFlags := map[string][]configflags.Definition{
-		"publishing":            configflags.PublishingFlags,
-		"requester-tls":         configflags.RequesterTLSFlags,
 		"job-selection":         configflags.JobSelectionFlags,
 		"disable-features":      configflags.DisabledFeatureFlags,
 		"capacity":              configflags.CapacityFlags,
-		"job-timeouts":          configflags.ComputeTimeoutFlags,
 		"translations":          configflags.JobTranslationFlags,
 		"docker-cache-manifest": configflags.DockerManifestCacheFlags,
 	}
@@ -103,15 +100,11 @@ func NewCmd() *cobra.Command {
 			if err != nil {
 				return fmt.Errorf("setting up config: %w", err)
 			}
-			fsr, err := setup.SetupBacalhauRepo(repoPath, cfg)
+			fsr, err := setup.SetupBacalhauRepo(cfg)
 			if err != nil {
 				return fmt.Errorf("failed to reconcile repo: %w", err)
 			}
-			bcfg, err := cfg.Current()
-			if err != nil {
-				return fmt.Errorf("failed to load config: %w", err)
-			}
-			return runDevstack(cmd, bcfg, fsr, ODs, IsNoop)
+			return runDevstack(cmd, cfg, fsr, ODs, IsNoop)
 		},
 	}
 
@@ -171,13 +164,13 @@ func NewCmd() *cobra.Command {
 }
 
 //nolint:gocyclo,funlen
-func runDevstack(cmd *cobra.Command, cfg types.BacalhauConfig, fsr *repo.FsRepo, ODs *devstack.DevStackOptions, IsNoop bool) error {
+func runDevstack(cmd *cobra.Command, cfg types.Bacalhau, fsr *repo.FsRepo, ODs *devstack.DevStackOptions, IsNoop bool) error {
 	ctx := cmd.Context()
 
 	cm := util.GetCleanupManager(ctx)
 	cm.RegisterCallback(telemetry.Cleanup)
 
-	config.DevstackSetShouldPrintInfo()
+	config_legacy.DevstackSetShouldPrintInfo()
 
 	portFileName := filepath.Join(os.TempDir(), "bacalhau-devstack.port")
 	pidFileName := filepath.Join(os.TempDir(), "bacalhau-devstack.pid")
@@ -198,7 +191,7 @@ func runDevstack(cmd *cobra.Command, cfg types.BacalhauConfig, fsr *repo.FsRepo,
 		return err
 	}
 
-	requesterConfig, err := serve.GetRequesterConfig(ctx, cfg, true)
+	requesterConfig, err := serve.GetRequesterConfig(cfg, true)
 	if err != nil {
 		return err
 	}
@@ -238,8 +231,8 @@ func runDevstack(cmd *cobra.Command, cfg types.BacalhauConfig, fsr *repo.FsRepo,
 
 	// Get any certificate settings for devstack and use them if we have a certificate (possibly self-signed).
 	options = append(options, devstack.WithSelfSignedCertificate(
-		cfg.Node.ServerAPI.TLS.ServerCertificate,
-		cfg.Node.ServerAPI.TLS.ServerKey,
+		cfg.API.TLS.CertFile,
+		cfg.API.TLS.KeyFile,
 	))
 
 	stack, err := devstack.Setup(ctx, cfg, cm, fsr, options...)
diff --git a/cmd/cli/job/get.go b/cmd/cli/job/get.go
index cf1f7a8c47..411b5bcd4d 100644
--- a/cmd/cli/job/get.go
+++ b/cmd/cli/job/get.go
@@ -81,7 +81,7 @@ func NewGetCmd() *cobra.Command {
 	return getCmd
 }
 
-func get(cmd *cobra.Command, cmdArgs []string, api client.API, cfg types.BacalhauConfig, OG *GetOptions) error {
+func get(cmd *cobra.Command, cmdArgs []string, api client.API, cfg types.Bacalhau, OG *GetOptions) error {
 	ctx := cmd.Context()
 
 	jobID := cmdArgs[0]
diff --git a/cmd/cli/root.go b/cmd/cli/root.go
index 37a4fbe342..8a6c0b9da3 100644
--- a/cmd/cli/root.go
+++ b/cmd/cli/root.go
@@ -24,7 +24,6 @@ import (
 	"github.com/bacalhau-project/bacalhau/cmd/util"
 	"github.com/bacalhau-project/bacalhau/cmd/util/flags/cliflags"
 	"github.com/bacalhau-project/bacalhau/cmd/util/flags/configflags"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
 )
 
@@ -41,21 +40,13 @@ func NewRootCmd() *cobra.Command {
 		util.Fatal(RootCmd, err, 1)
 	}
 
-	RootCmd.PersistentFlags().VarP(cliflags.NewRepoFlag(), "repo", "r", "filesystem path to bacalhau repo")
-	// Bind the repo flag to viper for access by child commands
-	if err := viper.BindPFlag("repo", RootCmd.PersistentFlags().Lookup("repo")); err != nil {
-		util.Fatal(RootCmd, err, 1)
-	}
-	if err := viper.BindEnv("repo", "BACALHAU_DIR"); err != nil {
-		util.Fatal(RootCmd, err, 1)
-	}
-
 	// flag definitions with a corresponding field in the config file.
 	// when these flags are provided their value will be used instead of the value present in the config file.
 	// If no flg is provided, and the config file doesn't have a value defined then the default value will be used.
 	rootFlags := map[string][]configflags.Definition{
 		"api":     configflags.ClientAPIFlags,
 		"logging": configflags.LogFlags,
+		"repo":    configflags.DataDirFlag,
 	}
 	// register the flags on the command.
 	if err := configflags.RegisterFlags(RootCmd, rootFlags); err != nil {
@@ -78,10 +69,6 @@ func NewRootCmd() *cobra.Command {
 			return err
 		}
 
-		// TODO [fixme] this value is a constant and never read from the flag
-		// TODO make persistent flag allowing child commands to operate at different logs levels based on user input
-		logger.ConfigureLogging(util.LoggingMode)
-
 		return nil
 	}
 
diff --git a/cmd/cli/serve/serve.go b/cmd/cli/serve/serve.go
index 017810733f..9b10c5547a 100644
--- a/cmd/cli/serve/serve.go
+++ b/cmd/cli/serve/serve.go
@@ -6,6 +6,7 @@ import (
 	"net"
 	"net/url"
 	"os"
+	"strconv"
 	"strings"
 
 	"github.com/pkg/errors"
@@ -19,6 +20,7 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/crypto"
+	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/node"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
@@ -28,8 +30,6 @@ import (
 	"github.com/bacalhau-project/bacalhau/webui"
 )
 
-const DefaultPeerConnect = "none"
-
 var (
 	serveLong = templates.LongDesc(i18n.T(`
 		Start a bacalhau node.
@@ -39,18 +39,14 @@ var (
 		# Start a private bacalhau requester node
 		bacalhau serve
 		# or
-		bacalhau serve --node-type requester
+		bacalhau serve --config Orchestrator.Enabled
 
 		# Start a private bacalhau hybrid node that acts as both compute and requester
-		bacalhau serve --node-type compute --node-type requester
+		bacalhau serve --config Orchestrator.Enabled --config Compute.Enabled
 		# or
-		bacalhau serve --node-type compute,requester
-
-		# Start a public bacalhau requester node
-		bacalhau serve --peer env 
 
-		# Start a public bacalhau node with the WebUI on port 3000 (default:8483)
-		bacalhau serve --web-ui --web-ui-port=3000
+		# Start a public bacalhau node with the WebUI on port 3000 (default:0.0.0.0:8483)
+		bacalhau serve --config WebUI.Enabled --config WebUI.Listen=0.0.0.0:3000
 `))
 )
 
@@ -76,6 +72,7 @@ func NewCmd() *cobra.Command {
 		"node-name":             configflags.NodeNameFlags,
 		"translations":          configflags.JobTranslationFlags,
 		"docker-cache-manifest": configflags.DockerManifestCacheFlags,
+		"compute":               configflags.ComputeFlags,
 	}
 	serveCmd := &cobra.Command{
 		Use:     "serve",
@@ -86,27 +83,17 @@ func NewCmd() *cobra.Command {
 			return configflags.BindFlags(viper.GetViper(), serveFlags)
 		},
 		RunE: func(cmd *cobra.Command, _ []string) error {
-			// get the global viper instance
-			v := viper.GetViper()
-			// get the repo path set in the root command.
-			repoPath := v.GetString("repo")
-			if repoPath == "" {
-				return fmt.Errorf("repo path not set")
-			}
 			cfg, err := util.SetupConfig(cmd)
 			if err != nil {
 				return fmt.Errorf("failed to setup config: %w", err)
 			}
 			// create or open the bacalhau repo and load the config
-			fsr, err := setup.SetupBacalhauRepo(repoPath, cfg)
+			fsr, err := setup.SetupBacalhauRepo(cfg)
 			if err != nil {
 				return fmt.Errorf("failed to reconcile repo: %w", err)
 			}
-			bcfg, err := cfg.Current()
-			if err != nil {
-				return fmt.Errorf("failed to load config: %w", err)
-			}
-			return serve(cmd, bcfg, fsr)
+
+			return serve(cmd, cfg, fsr)
 		},
 	}
 
@@ -117,33 +104,21 @@ func NewCmd() *cobra.Command {
 }
 
 //nolint:funlen,gocyclo
-func serve(cmd *cobra.Command, cfg types.BacalhauConfig, fsRepo *repo.FsRepo) error {
+func serve(cmd *cobra.Command, cfg types.Bacalhau, fsRepo *repo.FsRepo) error {
 	ctx := cmd.Context()
 	cm := util.GetCleanupManager(ctx)
 
-	var nodeName string
-	var err error
-
-	if cfg.Node.Name == "" {
-		nodeName, err = getNodeID(ctx, cfg.Node.NameProvider)
-		if err != nil {
-			return err
-		}
-		cfg.Node.Name = nodeName
+	nodeName, err := fsRepo.ReadNodeName()
+	if err != nil {
+		return fmt.Errorf("failed to get node name: %w", err)
 	}
 	ctx = logger.ContextWithNodeIDLogger(ctx, nodeName)
 
 	// configure node type
-	isRequesterNode, isComputeNode, err := getNodeType(cfg)
-	if err != nil {
-		return err
-	}
+	isRequesterNode := cfg.Orchestrator.Enabled
+	isComputeNode := cfg.Compute.Enabled
 
-	transportPath, err := cfg.NetworkTransportDir()
-	if err != nil {
-		return err
-	}
-	networkConfig, err := getNetworkConfig(transportPath, cfg.Node.Network)
+	networkConfig, err := getNetworkConfig(cfg)
 	if err != nil {
 		return err
 	}
@@ -153,41 +128,45 @@ func serve(cmd *cobra.Command, cfg types.BacalhauConfig, fsRepo *repo.FsRepo) er
 		return errors.Wrapf(err, "failed to configure compute node")
 	}
 
-	requesterConfig, err := GetRequesterConfig(ctx, cfg, isRequesterNode)
+	requesterConfig, err := GetRequesterConfig(cfg, isRequesterNode)
 	if err != nil {
 		return errors.Wrapf(err, "failed to configure requester node")
 	}
 
 	// Create node config from cmd arguments
-	hostAddress, err := parseServerAPIHost(cfg.Node.ServerAPI.Host)
+	hostAddress, err := parseServerAPIHost(cfg.API.Host)
 	if err != nil {
 		return err
 	}
 	nodeConfig := node.NodeConfig{
-		NodeID:                cfg.Node.Name,
-		CleanupManager:        cm,
-		DisabledFeatures:      node.FeatureConfig(cfg.Node.DisabledFeatures),
+		NodeID:         nodeName,
+		CleanupManager: cm,
+		DisabledFeatures: node.FeatureConfig{
+			Engines:    cfg.Engines.Disabled,
+			Publishers: cfg.Publishers.Disabled,
+			Storages:   cfg.InputSources.Disabled,
+		},
 		HostAddress:           hostAddress,
-		APIPort:               uint16(cfg.Node.ServerAPI.Port),
+		APIPort:               uint16(cfg.API.Port),
 		ComputeConfig:         computeConfig,
 		RequesterNodeConfig:   requesterConfig,
-		AuthConfig:            cfg.Auth,
+		AuthConfig:            cfg.API.Auth,
 		IsComputeNode:         isComputeNode,
 		IsRequesterNode:       isRequesterNode,
-		RequesterSelfSign:     cfg.Node.ServerAPI.TLS.SelfSigned,
-		Labels:                cfg.Node.Labels,
-		AllowListedLocalPaths: cfg.Node.AllowListedLocalPaths,
+		RequesterSelfSign:     cfg.API.TLS.SelfSigned,
+		Labels:                cfg.Compute.Labels,
+		AllowListedLocalPaths: cfg.Compute.AllowListedLocalPaths,
 		NetworkConfig:         networkConfig,
 	}
 	if isRequesterNode {
 		// We only want auto TLS for the requester node, but this info doesn't fit well
 		// with the other data in the requesterConfig.
-		nodeConfig.RequesterAutoCert = cfg.Node.ServerAPI.TLS.AutoCert
-		nodeConfig.RequesterAutoCertCache = cfg.Node.ServerAPI.TLS.AutoCertCachePath
+		nodeConfig.RequesterAutoCert = cfg.API.TLS.AutoCert
+		nodeConfig.RequesterAutoCertCache = cfg.API.TLS.AutoCertCachePath
 		// If there are configuration values for autocert we should return and let autocert
 		// do what it does later on in the setup.
 		if nodeConfig.RequesterAutoCert == "" {
-			cert, key, err := GetTLSCertificate(ctx, cfg, &nodeConfig, fsRepo)
+			cert, key, err := GetTLSCertificate(ctx, cfg, &nodeConfig)
 			if err != nil {
 				return err
 			}
@@ -196,135 +175,89 @@ func serve(cmd *cobra.Command, cfg types.BacalhauConfig, fsRepo *repo.FsRepo) er
 		}
 	}
 	// Create node
+	log.Info().Msg("starting bacalhau...")
 	standardNode, err := node.NewNode(ctx, cfg, nodeConfig, fsRepo)
 	if err != nil {
 		return fmt.Errorf("error creating node: %w", err)
 	}
 
-	// Persist the node config after the node is created and its config is valid.
-	repoDir, err := fsRepo.Path()
-	if err != nil {
-		return err
-	}
-	if err = persistConfigs(repoDir, cfg); err != nil {
-		return fmt.Errorf("error persisting configs: %w", err)
-	}
-
 	// Start node
 	if err := standardNode.Start(ctx); err != nil {
 		return fmt.Errorf("error starting node: %w", err)
 	}
 
 	// Start up Dashboard - default: 8483
-	if cfg.Node.WebUI.Enabled {
+	if cfg.WebUI.Enabled {
 		apiURL := standardNode.APIServer.GetURI().JoinPath("api", "v1")
+		host, portStr, err := net.SplitHostPort(cfg.WebUI.Listen)
+		if err != nil {
+			return err
+		}
+		webuiPort, err := strconv.ParseInt(portStr, 10, 64)
+		if err != nil {
+			return err
+		}
 		go func() {
 			// Specifically leave the host blank. The app will just use whatever
 			// host it is served on and replace the port and path.
 			apiPort := apiURL.Port()
 			apiPath := apiURL.Path
 
-			err := webui.ListenAndServe(ctx, "", apiPort, apiPath, cfg.Node.WebUI.Port)
+			err := webui.ListenAndServe(ctx, host, apiPort, apiPath, int(webuiPort))
 			if err != nil {
 				cmd.PrintErrln(err)
 			}
 		}()
 	}
 
-	connectCmd, err := buildConnectCommand(ctx, &nodeConfig)
-	if err != nil {
-		return err
+	startupLog := log.Info().
+		Str("name", nodeName).
+		Str("address", fmt.Sprintf("%s:%d", hostAddress, cfg.API.Port)).
+		Bool("compute_enabled", cfg.Compute.Enabled).
+		Bool("orchestrator_enabled", cfg.Orchestrator.Enabled).
+		Bool("webui_enabled", cfg.WebUI.Enabled)
+	if cfg.Compute.Enabled {
+		capacity := standardNode.ComputeNode.Capacity.GetMaxCapacity(ctx)
+		startupLog.
+			Strs("engines", standardNode.ComputeNode.Executors.Keys(ctx)).
+			Strs("publishers", standardNode.ComputeNode.Publishers.Keys(ctx)).
+			Strs("storages", standardNode.ComputeNode.Storages.Keys(ctx)).
+			Strs("orchestrators", cfg.Compute.Orchestrators).
+			Str("capacity", capacity.String())
+
+		if len(cfg.Compute.AllowListedLocalPaths) > 0 {
+			startupLog.Strs("volumes", cfg.Compute.AllowListedLocalPaths)
+		}
+
+	}
+	if cfg.Orchestrator.Enabled {
+		startupLog.Str("orchestrator_address",
+			fmt.Sprintf("%s:%d", cfg.Orchestrator.Host, cfg.Orchestrator.Port))
 	}
+	startupLog.Msg("bacalhau node running")
+
+	envvars := buildEnvVariables(cfg)
 	cmd.Println()
-	cmd.Println(connectCmd)
+	cmd.Println("To connect to this node from the local client, run the following commands in your shell:")
+	cmd.Println(envvars)
 
-	envVars, err := buildEnvVariables(ctx, cfg, &nodeConfig)
+	riPath, err := fsRepo.WriteRunInfo(ctx, envvars)
 	if err != nil {
 		return err
 	}
 	cmd.Println()
-	cmd.Println("To connect to this node from the client, run the following commands in your shell:")
-	cmd.Println(envVars)
+	cmd.Println()
+	cmd.Printf("A copy of these variables have been written to: %s\n", riPath)
+	defer os.Remove(riPath)
 
-	ripath, err := fsRepo.WriteRunInfo(ctx, envVars)
-	if err != nil {
-		return fmt.Errorf("writing run info to repo: %w", err)
-	} else {
-		cmd.Printf("A copy of these variables have been written to: %s\n", ripath)
-	}
-	cm.RegisterCallback(func() error {
-		return os.Remove(ripath)
-	})
 	<-ctx.Done() // block until killed
+	log.Info().Msg("bacalhau node shutting down...")
 	return nil
 }
 
-func buildConnectCommand(ctx context.Context, nodeConfig *node.NodeConfig) (string, error) {
-	headerB := strings.Builder{}
-	cmdB := strings.Builder{}
-	if nodeConfig.IsRequesterNode {
-		cmdB.WriteString(fmt.Sprintf("%s serve ", os.Args[0]))
-		// other nodes can be just compute nodes
-		// no need to spawn 1+ requester nodes
-		cmdB.WriteString(fmt.Sprintf("%s=compute ",
-			configflags.FlagNameForKey(types.NodeType, configflags.NodeTypeFlags...)))
-
-		advertisedAddr := getPublicNATSOrchestratorURL(nodeConfig)
-		headerB.WriteString("To connect a compute node to this orchestrator, run the following command in your shell:\n")
-		cmdB.WriteString(fmt.Sprintf("%s=%s ",
-			configflags.FlagNameForKey(types.NodeNetworkOrchestrators, configflags.NetworkFlags...),
-			advertisedAddr.String(),
-		))
-	}
-
-	return headerB.String() + cmdB.String(), nil
-}
-
-func buildEnvVariables(
-	ctx context.Context,
-	cfg types.BacalhauConfig,
-	nodeConfig *node.NodeConfig,
-) (string, error) {
-	// build shell variables to connect to this node
-	envVarBuilder := strings.Builder{}
-	envVarBuilder.WriteString(fmt.Sprintf(
-		"export %s=%s\n",
-		config.KeyAsEnvVar(types.NodeClientAPIHost),
-		cfg.Node.ServerAPI.Host,
-	))
-	envVarBuilder.WriteString(fmt.Sprintf(
-		"export %s=%d\n",
-		config.KeyAsEnvVar(types.NodeClientAPIPort),
-		cfg.Node.ServerAPI.Port,
-	))
-
-	if nodeConfig.IsRequesterNode {
-		envVarBuilder.WriteString(fmt.Sprintf(
-			"export %s=%s\n",
-			config.KeyAsEnvVar(types.NodeNetworkOrchestrators),
-			getPublicNATSOrchestratorURL(nodeConfig).String(),
-		))
-	}
-
-	return envVarBuilder.String(), nil
-}
-
-func getPublicNATSOrchestratorURL(nodeConfig *node.NodeConfig) *url.URL {
-	orchestrator := &url.URL{
-		Scheme: "nats",
-		Host:   nodeConfig.NetworkConfig.AdvertisedAddress,
-	}
-
-	if nodeConfig.NetworkConfig.AdvertisedAddress == "" {
-		orchestrator.Host = fmt.Sprintf("127.0.0.1:%d", nodeConfig.NetworkConfig.Port)
-	}
-
-	return orchestrator
-}
-
-func GetTLSCertificate(ctx context.Context, cfg types.BacalhauConfig, nodeConfig *node.NodeConfig, r *repo.FsRepo) (string, string, error) {
-	cert := cfg.Node.ServerAPI.TLS.ServerCertificate
-	key := cfg.Node.ServerAPI.TLS.ServerKey
+func GetTLSCertificate(ctx context.Context, cfg types.Bacalhau, nodeConfig *node.NodeConfig) (string, string, error) {
+	cert := cfg.API.TLS.CertFile
+	key := cfg.API.TLS.KeyFile
 	if cert != "" && key != "" {
 		return cert, key, nil
 	}
@@ -367,3 +300,64 @@ func GetTLSCertificate(ctx context.Context, cfg types.BacalhauConfig, nodeConfig
 	cert = certFile.Name()
 	return cert, key, nil
 }
+
+func parseServerAPIHost(host string) (string, error) {
+	if net.ParseIP(host) == nil {
+		// We should check that the value gives us an address type
+		// we can use to get our IP address. If it doesn't, we should
+		// panic.
+		atype, ok := network.AddressTypeFromString(host)
+		if !ok {
+			return "", fmt.Errorf("invalid address type in Server API Host config: %s", host)
+		}
+
+		addr, err := network.GetNetworkAddress(atype, network.AllAddresses)
+		if err != nil {
+			return "", fmt.Errorf("failed to get network address for Server API Host: %s: %w", host, err)
+		}
+
+		if len(addr) == 0 {
+			return "", fmt.Errorf("no %s addresses found for Server API Host", host)
+		}
+
+		// Use the first address
+		host = addr[0]
+	}
+
+	return host, nil
+}
+
+func buildEnvVariables(
+	cfg types.Bacalhau,
+) string {
+	// build shell variables to connect to this node
+	var envvars strings.Builder
+	envvars.WriteString(fmt.Sprintf("export %s=%s\n", config.KeyAsEnvVar(types.APIHostKey), getAPIURL(cfg.API)))
+	envvars.WriteString(fmt.Sprintf("export %s=%d\n", config.KeyAsEnvVar(types.APIPortKey), cfg.API.Port))
+	if cfg.Orchestrator.Enabled {
+		envvars.WriteString(fmt.Sprintf("export %s=%s\n",
+			config.KeyAsEnvVar(types.ComputeOrchestratorsKey), getPublicNATSOrchestratorURL(cfg.Orchestrator)))
+	}
+	return envvars.String()
+}
+
+func getAPIURL(cfg types.API) string {
+	if cfg.Host == "0.0.0.0" {
+		return "127.0.0.1"
+	} else {
+		return cfg.Host
+	}
+}
+
+func getPublicNATSOrchestratorURL(cfg types.Orchestrator) *url.URL {
+	orchestrator := &url.URL{
+		Scheme: "nats",
+		Host:   cfg.Advertise,
+	}
+
+	if cfg.Advertise == "" {
+		orchestrator.Host = fmt.Sprintf("127.0.0.1:%d", cfg.Port)
+	}
+
+	return orchestrator
+}
diff --git a/cmd/cli/serve/util.go b/cmd/cli/serve/util.go
index e3bea07e57..644f5200f7 100644
--- a/cmd/cli/serve/util.go
+++ b/cmd/cli/serve/util.go
@@ -2,44 +2,27 @@ package serve
 
 import (
 	"context"
-	"errors"
 	"fmt"
-	"net"
-	"path/filepath"
 	"time"
 
 	pkgerrors "github.com/pkg/errors"
-	"github.com/rs/zerolog/log"
-	"github.com/samber/lo"
 
+	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
+	"github.com/bacalhau-project/bacalhau/pkg/compute/capacity/system"
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store"
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store/boltdb"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/jobstore"
 	boltjobstore "github.com/bacalhau-project/bacalhau/pkg/jobstore/boltdb"
-	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
-	"github.com/bacalhau-project/bacalhau/pkg/util/idgen"
-
-	"github.com/bacalhau-project/bacalhau/pkg/orchestrator/transformer"
-
-	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/node"
 )
 
 func GetComputeConfig(
 	ctx context.Context,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	createExecutionStore bool,
 ) (node.ComputeConfig, error) {
-	totalResources, totalErr := cfg.Node.Compute.Capacity.TotalResourceLimits.ToResources()
-	jobResources, jobErr := cfg.Node.Compute.Capacity.JobResourceLimits.ToResources()
-	defaultResources, defaultErr := cfg.Node.Compute.Capacity.DefaultJobResourceLimits.ToResources()
-	if err := errors.Join(totalErr, jobErr, defaultErr); err != nil {
-		return node.ComputeConfig{}, err
-	}
-
 	var executionStore store.ExecutionStore
 	if createExecutionStore {
 		var err error
@@ -47,42 +30,63 @@ func GetComputeConfig(
 		if err != nil {
 			return node.ComputeConfig{}, err
 		}
-		executionStore, err = getExecutionStore(ctx, cfg.Node.Compute.ExecutionStore, executionStoreDBPath)
-		if err != nil {
-			return node.ComputeConfig{}, pkgerrors.Wrapf(err, "failed to create execution store")
-		}
+		executionStore, err = boltdb.NewStore(ctx, executionStoreDBPath)
 	}
 
 	executionsPath, err := cfg.ExecutionDir()
 	if err != nil {
 		return node.ComputeConfig{}, err
 	}
+	systemCapacity, err := system.NewPhysicalCapacityProvider(executionsPath).GetTotalCapacity(ctx)
+	if err != nil {
+		return node.ComputeConfig{}, fmt.Errorf("failed to determine total system capacity: %w", err)
+	}
+	allocatedResources, err := scaleCapacityByAllocation(systemCapacity, cfg.Compute.AllocatedCapacity)
+	if err != nil {
+		return node.ComputeConfig{}, err
+	}
 
-	return node.NewComputeConfigWith(executionsPath, node.ComputeConfigParams{
-		TotalResourceLimits:                   *totalResources,
-		JobResourceLimits:                     *jobResources,
-		DefaultJobResourceLimits:              *defaultResources,
-		IgnorePhysicalResourceLimits:          cfg.Node.Compute.Capacity.IgnorePhysicalResourceLimits,
-		JobNegotiationTimeout:                 time.Duration(cfg.Node.Compute.JobTimeouts.JobNegotiationTimeout),
-		MinJobExecutionTimeout:                time.Duration(cfg.Node.Compute.JobTimeouts.MinJobExecutionTimeout),
-		MaxJobExecutionTimeout:                time.Duration(cfg.Node.Compute.JobTimeouts.MaxJobExecutionTimeout),
-		DefaultJobExecutionTimeout:            time.Duration(cfg.Node.Compute.JobTimeouts.DefaultJobExecutionTimeout),
-		JobExecutionTimeoutClientIDBypassList: cfg.Node.Compute.JobTimeouts.JobExecutionTimeoutClientIDBypassList,
+	params := node.ComputeConfigParams{
+		TotalResourceLimits:      allocatedResources,
+		JobResourceLimits:        allocatedResources,
+		DefaultJobResourceLimits: allocatedResources,
+		ExecutionStore:           executionStore,
 		JobSelectionPolicy: node.JobSelectionPolicy{
-			Locality:            semantic.JobSelectionDataLocality(cfg.Node.Compute.JobSelection.Locality),
-			RejectStatelessJobs: cfg.Node.Compute.JobSelection.RejectStatelessJobs,
-			AcceptNetworkedJobs: cfg.Node.Compute.JobSelection.AcceptNetworkedJobs,
-			ProbeHTTP:           cfg.Node.Compute.JobSelection.ProbeHTTP,
-			ProbeExec:           cfg.Node.Compute.JobSelection.ProbeExec,
+			Locality:            semantic.Anywhere,
+			RejectStatelessJobs: cfg.JobAdmissionControl.RejectStatelessJobs,
+			AcceptNetworkedJobs: cfg.JobAdmissionControl.AcceptNetworkedJobs,
+			ProbeHTTP:           cfg.JobAdmissionControl.ProbeHTTP,
+			ProbeExec:           cfg.JobAdmissionControl.ProbeExec,
 		},
-		LogRunningExecutionsInterval: time.Duration(cfg.Node.Compute.Logging.LogRunningExecutionsInterval),
-		LogStreamBufferSize:          cfg.Node.Compute.LogStreamConfig.ChannelBufferSize,
-		ExecutionStore:               executionStore,
-		LocalPublisher:               cfg.Node.Compute.LocalPublisher,
-	})
+	}
+
+	// if the local publisher is enabled and installed, populate params.
+	// Otherwise, a default set of values will be used which are defined in NewComputeConfigWith.
+	if cfg.Publishers.IsNotDisabled(models.PublisherLocal) {
+		// use the defaults, and override any values provided by the user.
+		address := params.LocalPublisher.Address
+		port := params.LocalPublisher.Port
+		directory := params.LocalPublisher.Directory
+		if cfg.Publishers.Types.Local.Address != "" {
+			address = cfg.Publishers.Types.Local.Address
+		}
+		if cfg.Publishers.Types.Local.Port != 0 {
+			port = cfg.Publishers.Types.Local.Port
+		}
+		if cfg.Publishers.Types.Local.Directory != "" {
+			directory = cfg.Publishers.Types.Local.Directory
+		}
+		params.LocalPublisher = types.LocalPublisher{
+			Address:   address,
+			Port:      port,
+			Directory: directory,
+		}
+	}
+
+	return node.NewComputeConfigWith(executionsPath, params)
 }
 
-func GetRequesterConfig(ctx context.Context, cfg types.BacalhauConfig, createJobStore bool) (node.RequesterConfig, error) {
+func GetRequesterConfig(cfg types.Bacalhau, createJobStore bool) (node.RequesterConfig, error) {
 	var err error
 	var jobStore jobstore.Store
 	if createJobStore {
@@ -90,172 +94,80 @@ func GetRequesterConfig(ctx context.Context, cfg types.BacalhauConfig, createJob
 		if err != nil {
 			return node.RequesterConfig{}, err
 		}
-		jobStore, err = getJobStore(ctx, cfg.Node.Requester.JobStore, jobStoreDBPath)
+		jobStore, err = boltjobstore.NewBoltJobStore(jobStoreDBPath)
 		if err != nil {
 			return node.RequesterConfig{}, pkgerrors.Wrapf(err, "failed to create job store")
 		}
 	}
-
-	requesterConfig, err := node.NewRequesterConfigWith(node.RequesterConfigParams{
-		JobDefaults: transformer.JobDefaults{
-			TotalTimeout:     time.Duration(cfg.Node.Requester.JobDefaults.TotalTimeout),
-			ExecutionTimeout: time.Duration(cfg.Node.Requester.JobDefaults.ExecutionTimeout),
-			QueueTimeout:     time.Duration(cfg.Node.Requester.JobDefaults.QueueTimeout),
-		},
-		HousekeepingBackgroundTaskInterval: time.Duration(cfg.Node.Requester.HousekeepingBackgroundTaskInterval),
-		NodeRankRandomnessRange:            cfg.Node.Requester.NodeRankRandomnessRange,
-		OverAskForBidsFactor:               cfg.Node.Requester.OverAskForBidsFactor,
+	params := node.RequesterConfigParams{
+		JobDefaults:                        cfg.JobDefaults,
+		HousekeepingBackgroundTaskInterval: time.Duration(cfg.Orchestrator.Scheduler.HousekeepingInterval),
+		HousekeepingTimeoutBuffer:          time.Duration(cfg.Orchestrator.Scheduler.HousekeepingTimeout),
 		JobSelectionPolicy: node.JobSelectionPolicy{
-			Locality:            semantic.JobSelectionDataLocality(cfg.Node.Requester.JobSelectionPolicy.Locality),
-			RejectStatelessJobs: cfg.Node.Requester.JobSelectionPolicy.RejectStatelessJobs,
-			AcceptNetworkedJobs: cfg.Node.Requester.JobSelectionPolicy.AcceptNetworkedJobs,
-			ProbeHTTP:           cfg.Node.Requester.JobSelectionPolicy.ProbeHTTP,
-			ProbeExec:           cfg.Node.Requester.JobSelectionPolicy.ProbeExec,
+			Locality:            semantic.Anywhere,
+			RejectStatelessJobs: cfg.JobAdmissionControl.RejectStatelessJobs,
+			AcceptNetworkedJobs: cfg.JobAdmissionControl.AcceptNetworkedJobs,
+			ProbeHTTP:           cfg.JobAdmissionControl.ProbeHTTP,
+			ProbeExec:           cfg.JobAdmissionControl.ProbeExec,
 		},
-		FailureInjectionConfig:         cfg.Node.Requester.FailureInjectionConfig,
-		EvalBrokerVisibilityTimeout:    time.Duration(cfg.Node.Requester.EvaluationBroker.EvalBrokerVisibilityTimeout),
-		EvalBrokerInitialRetryDelay:    time.Duration(cfg.Node.Requester.EvaluationBroker.EvalBrokerInitialRetryDelay),
-		EvalBrokerSubsequentRetryDelay: time.Duration(cfg.Node.Requester.EvaluationBroker.EvalBrokerSubsequentRetryDelay),
-		EvalBrokerMaxRetryCount:        cfg.Node.Requester.EvaluationBroker.EvalBrokerMaxRetryCount,
-		WorkerCount:                    cfg.Node.Requester.Worker.WorkerCount,
-		NodeOverSubscriptionFactor:     cfg.Node.Requester.Scheduler.NodeOverSubscriptionFactor,
-		WorkerEvalDequeueTimeout:       time.Duration(cfg.Node.Requester.Worker.WorkerEvalDequeueTimeout),
-		WorkerEvalDequeueBaseBackoff:   time.Duration(cfg.Node.Requester.Worker.WorkerEvalDequeueBaseBackoff),
-		WorkerEvalDequeueMaxBackoff:    time.Duration(cfg.Node.Requester.Worker.WorkerEvalDequeueMaxBackoff),
-		SchedulerQueueBackoff:          time.Duration(cfg.Node.Requester.Scheduler.QueueBackoff),
-		S3PreSignedURLExpiration:       time.Duration(cfg.Node.Requester.StorageProvider.S3.PreSignedURLExpiration),
-		S3PreSignedURLDisabled:         cfg.Node.Requester.StorageProvider.S3.PreSignedURLDisabled,
-		TranslationEnabled:             cfg.Node.Requester.TranslationEnabled,
-		JobStore:                       jobStore,
-		DefaultPublisher:               cfg.Node.Requester.DefaultPublisher,
-		NodeInfoStoreTTL:               time.Duration(cfg.Node.Requester.NodeInfoStoreTTL),
-	})
+		EvalBrokerVisibilityTimeout: time.Duration(cfg.Orchestrator.EvaluationBroker.VisibilityTimeout),
+		EvalBrokerMaxRetryCount:     cfg.Orchestrator.EvaluationBroker.MaxRetryCount,
+		WorkerCount:                 cfg.Orchestrator.Scheduler.WorkerCount,
+		TranslationEnabled:          cfg.FeatureFlags.ExecTranslation,
+		JobStore:                    jobStore,
+	}
+
+	if cfg.Publishers.IsNotDisabled(models.StorageSourceS3) {
+		params.S3PreSignedURLExpiration = time.Duration(cfg.Publishers.Types.S3.PreSignedURLExpiration)
+		params.S3PreSignedURLDisabled = cfg.Publishers.Types.S3.PreSignedURLDisabled
+	}
+
+	requesterConfig, err := node.NewRequesterConfigWith(params)
 	if err != nil {
 		return node.RequesterConfig{}, err
 	}
 
-	if cfg.Node.Requester.ManualNodeApproval {
+	requesterConfig.DefaultApprovalState = models.NodeMembership.APPROVED
+	if cfg.Orchestrator.NodeManager.ManualApproval {
 		requesterConfig.DefaultApprovalState = models.NodeMembership.PENDING
-	} else {
-		requesterConfig.DefaultApprovalState = models.NodeMembership.APPROVED
 	}
 
 	return requesterConfig, nil
 }
 
-func getNodeType(cfg types.BacalhauConfig) (requester, compute bool, err error) {
-	requester = false
-	compute = false
-	err = nil
-
-	for _, nodeType := range cfg.Node.Type {
-		if nodeType == "compute" {
-			compute = true
-		} else if nodeType == "requester" {
-			requester = true
-		} else {
-			err = fmt.Errorf("invalid node type %s. Only compute and requester values are supported", nodeType)
-		}
+func getNetworkConfig(cfg types.Bacalhau) (node.NetworkConfig, error) {
+	storeDir, err := cfg.NetworkTransportDir()
+	if err != nil {
+		return node.NetworkConfig{}, err
 	}
-	return
-}
-
-func getNetworkConfig(networkStorePath string, cfg types.NetworkConfig) (node.NetworkConfig, error) {
 	return node.NetworkConfig{
-		Port:                     cfg.Port,
-		AdvertisedAddress:        cfg.AdvertisedAddress,
-		Orchestrators:            cfg.Orchestrators,
-		StoreDir:                 networkStorePath,
-		AuthSecret:               cfg.AuthSecret,
-		ClusterName:              cfg.Cluster.Name,
-		ClusterPort:              cfg.Cluster.Port,
-		ClusterAdvertisedAddress: cfg.Cluster.AdvertisedAddress,
-		ClusterPeers:             cfg.Cluster.Peers,
+		Port:                     cfg.Orchestrator.Port,
+		AdvertisedAddress:        cfg.Orchestrator.Advertise,
+		Orchestrators:            cfg.Compute.Orchestrators,
+		StoreDir:                 storeDir,
+		AuthSecret:               cfg.Orchestrator.AuthSecret,
+		ClusterName:              cfg.Orchestrator.Cluster.Name,
+		ClusterPort:              cfg.Orchestrator.Cluster.Port,
+		ClusterAdvertisedAddress: cfg.Orchestrator.Cluster.Advertise,
+		ClusterPeers:             cfg.Orchestrator.Cluster.Peers,
 	}, nil
 }
-
-func getExecutionStore(ctx context.Context, storeCfg types.JobStoreConfig, path string) (store.ExecutionStore, error) {
-	if err := storeCfg.Validate(); err != nil {
-		return nil, err
+func scaleCapacityByAllocation(systemCapacity models.Resources, scaler types.ResourceScaler) (models.Resources, error) {
+	// if the system capacity is zero we should fail as it means the compute node will be unable to accept any work.
+	if systemCapacity.IsZero() {
+		return models.Resources{}, fmt.Errorf("system capacity is zero")
 	}
 
-	switch storeCfg.Type {
-	case types.BoltDB:
-		return boltdb.NewStore(ctx, path)
-	default:
-		return nil, fmt.Errorf("unknown JobStore type: %s", storeCfg.Type)
-	}
-}
-
-func getJobStore(ctx context.Context, storeCfg types.JobStoreConfig, path string) (jobstore.Store, error) {
-	if err := storeCfg.Validate(); err != nil {
-		return nil, err
-	}
-
-	switch storeCfg.Type {
-	case types.BoltDB:
-		log.Ctx(ctx).Debug().Str("Path", path).Msg("creating boltdb backed jobstore")
-		return boltjobstore.NewBoltJobStore(path)
-	default:
-		return nil, fmt.Errorf("unknown JobStore type: %s", storeCfg.Type)
-	}
-}
-
-func getNodeID(ctx context.Context, nodeNameProviderType string) (string, error) {
-	nodeNameProviders := map[string]idgen.NodeNameProvider{
-		"hostname": idgen.HostnameProvider{},
-		"aws":      idgen.NewAWSNodeNameProvider(),
-		"gcp":      idgen.NewGCPNodeNameProvider(),
-		"uuid":     idgen.UUIDNodeNameProvider{},
-		"puuid":    idgen.PUUIDNodeNameProvider{},
-	}
-	nodeNameProvider, ok := nodeNameProviders[nodeNameProviderType]
-	if !ok {
-		return "", fmt.Errorf(
-			"unknown node name provider: %s. Supported providers are: %s", nodeNameProviderType, lo.Keys(nodeNameProviders))
+	// if allocated capacity scaler is zero, return the system capacity
+	if scaler.IsZero() {
+		return systemCapacity, nil
 	}
 
-	nodeName, err := nodeNameProvider.GenerateNodeName(ctx)
+	// scale the system resources based on the allocation
+	allocatedCapacity, err := scaler.ToResource(systemCapacity)
 	if err != nil {
-		return "", err
-	}
-
-	return nodeName, nil
-}
-
-// persistConfigs writes the resolved config to the persisted config file.
-// this will only write values that must not change between invocations,
-// such as the job store path and node name,
-// and only if they are not already set in the config file.
-func persistConfigs(repoPath string, cfg types.BacalhauConfig) error {
-	if err := config.WritePersistedConfigs(filepath.Join(repoPath, config.FileName), cfg); err != nil {
-		return fmt.Errorf("error writing persisted config: %w", err)
-	}
-	return nil
-}
-
-func parseServerAPIHost(host string) (string, error) {
-	if net.ParseIP(host) == nil {
-		// We should check that the value gives us an address type
-		// we can use to get our IP address. If it doesn't, we should
-		// panic.
-		atype, ok := network.AddressTypeFromString(host)
-		if !ok {
-			return "", fmt.Errorf("invalid address type in Server API Host config: %s", host)
-		}
-
-		addr, err := network.GetNetworkAddress(atype, network.AllAddresses)
-		if err != nil {
-			return "", fmt.Errorf("failed to get network address for Server API Host: %s: %w", host, err)
-		}
-
-		if len(addr) == 0 {
-			return "", fmt.Errorf("no %s addresses found for Server API Host", host)
-		}
-
-		// Use the first address
-		host = addr[0]
+		return models.Resources{}, fmt.Errorf("allocating system capacity: %w", err)
 	}
 
-	return host, nil
+	return *allocatedCapacity, nil
 }
diff --git a/cmd/cli/version/version.go b/cmd/cli/version/version.go
index 05d9a6c773..26e8b1e277 100644
--- a/cmd/cli/version/version.go
+++ b/cmd/cli/version/version.go
@@ -26,6 +26,7 @@ import (
 
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
+	"github.com/bacalhau-project/bacalhau/pkg/repo"
 	"github.com/bacalhau-project/bacalhau/pkg/version"
 
 	"github.com/bacalhau-project/bacalhau/cmd/util"
@@ -54,7 +55,11 @@ func NewCmd() *cobra.Command {
 		PreRun: hook.ApplyPorcelainLogLevel,
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			// initialize a new or open an existing repo merging any config file(s) it contains into cfg.
-			cfg, err := util.SetupRepoConfig(cmd)
+			cfg, err := util.SetupConfig(cmd)
+			if err != nil {
+				return fmt.Errorf("failed to setup config: %w", err)
+			}
+			r, err := util.SetupRepo(cfg)
 			if err != nil {
 				return fmt.Errorf("failed to setup repo: %w", err)
 			}
@@ -63,7 +68,7 @@ func NewCmd() *cobra.Command {
 			if err != nil {
 				return fmt.Errorf("failed to create api client: %w", err)
 			}
-			return runVersion(cmd, cfg, api, oV)
+			return runVersion(cmd, cfg, r, api, oV)
 		},
 	}
 	versionCmd.Flags().BoolVar(&oV.ClientOnly, "client", oV.ClientOnly, "If true, shows client version only (no server required).")
@@ -72,10 +77,10 @@ func NewCmd() *cobra.Command {
 	return versionCmd
 }
 
-func runVersion(cmd *cobra.Command, cfg types.BacalhauConfig, api clientv2.API, oV *VersionOptions) error {
+func runVersion(cmd *cobra.Command, cfg types.Bacalhau, r *repo.FsRepo, api clientv2.API, oV *VersionOptions) error {
 	ctx := cmd.Context()
 
-	err := oV.Run(ctx, cmd, cfg, api)
+	err := oV.Run(ctx, cmd, cfg, r, api)
 	if err != nil {
 		return fmt.Errorf("error running version: %w", err)
 	}
@@ -106,7 +111,8 @@ var updateMessageColumn = output.TableColumn[util.Versions]{
 func (oV *VersionOptions) Run(
 	ctx context.Context,
 	cmd *cobra.Command,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
+	r *repo.FsRepo,
 	api clientv2.API,
 ) error {
 	var (
@@ -122,7 +128,7 @@ func (oV *VersionOptions) Run(
 		vctx, cancel := context.WithTimeout(ctx, time.Second*3)
 		defer cancel()
 		var err error
-		versions, err = util.GetAllVersions(vctx, cfg, api)
+		versions, err = util.GetAllVersions(vctx, cfg, api, r)
 		if err != nil {
 			// No error on fail of version check. Just print as much as we can.
 			log.Ctx(ctx).Warn().Err(err).Msg("failed to get updated versions")
diff --git a/cmd/util/api.go b/cmd/util/api.go
index 6945b1a997..9c6aed43df 100644
--- a/cmd/util/api.go
+++ b/cmd/util/api.go
@@ -15,16 +15,16 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/version"
 )
 
-func GetAPIClientV2(cmd *cobra.Command, cfg types.BacalhauConfig) (clientv2.API, error) {
-	tlsCfg := cfg.Node.ClientAPI.ClientTLS
-	apiHost := cfg.Node.ClientAPI.Host
-	apiPort := cfg.Node.ClientAPI.Port
+func GetAPIClientV2(cmd *cobra.Command, cfg types.Bacalhau) (clientv2.API, error) {
+	tlsCfg := cfg.API.TLS
+	apiHost := cfg.API.Host
+	apiPort := cfg.API.Port
 
-	if tlsCfg.CACert != "" {
-		if _, err := os.Stat(tlsCfg.CACert); os.IsNotExist(err) {
-			return nil, fmt.Errorf("CA certificate file %q does not exists", tlsCfg.CACert)
+	if tlsCfg.CAFile != "" {
+		if _, err := os.Stat(tlsCfg.CAFile); os.IsNotExist(err) {
+			return nil, fmt.Errorf("CA certificate file %q does not exists", tlsCfg.CAFile)
 		} else if err != nil {
-			return nil, fmt.Errorf("CA certificate file %q cannot be read: %w", tlsCfg.CACert, err)
+			return nil, fmt.Errorf("CA certificate file %q cannot be read: %w", tlsCfg.CAFile, err)
 		}
 	}
 
@@ -44,7 +44,7 @@ func GetAPIClientV2(cmd *cobra.Command, cfg types.BacalhauConfig) (clientv2.API,
 	}
 
 	opts := []clientv2.OptionFn{
-		clientv2.WithCACertificate(tlsCfg.CACert),
+		clientv2.WithCACertificate(tlsCfg.CAFile),
 		clientv2.WithInsecureTLS(tlsCfg.Insecure),
 		clientv2.WithTLS(tlsCfg.UseTLS),
 		clientv2.WithHeaders(headers),
diff --git a/cmd/util/auth/auth.go b/cmd/util/auth/auth.go
index 49627a885d..6e90f495e0 100644
--- a/cmd/util/auth/auth.go
+++ b/cmd/util/auth/auth.go
@@ -15,7 +15,7 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/authn"
 	"github.com/bacalhau-project/bacalhau/pkg/authn/ask"
 	"github.com/bacalhau-project/bacalhau/pkg/authn/challenge"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
@@ -31,7 +31,7 @@ func RunAuthenticationFlow(
 	auth *client.Auth,
 	clientKeyPath string,
 ) (*apimodels.HTTPCredential, error) {
-	sk, err := config.GetClientPrivateKey(clientKeyPath)
+	sk, err := config_legacy.GetClientPrivateKey(clientKeyPath)
 	if err != nil {
 		return nil, err
 	}
diff --git a/cmd/util/download.go b/cmd/util/download.go
index c1b1504f59..804cedcbc6 100644
--- a/cmd/util/download.go
+++ b/cmd/util/download.go
@@ -22,7 +22,7 @@ import (
 func DownloadResultsHandler(
 	ctx context.Context,
 	cmd *cobra.Command,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	apiV2 clientv2.API,
 	jobID string,
 	downloadSettings *cliflags.DownloaderSettings,
@@ -43,8 +43,7 @@ func DownloadResultsHandler(
 		cmd.Printf("\n  bacalhau job logs %s\n", jobID)
 		return nil
 	}
-
-	downloaderProvider, err := util.NewStandardDownloaders(ctx, cfg.Node.IPFS.Connect)
+	downloaderProvider, err := util.NewStandardDownloaders(ctx, cfg.ResultDownloaders)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/util/flags/cliflags/config.go b/cmd/util/flags/cliflags/config.go
index 0f7bcd5496..e37aa629c2 100644
--- a/cmd/util/flags/cliflags/config.go
+++ b/cmd/util/flags/cliflags/config.go
@@ -19,7 +19,7 @@ func ConfigAutoComplete(cmd *cobra.Command, args []string, toComplete string) ([
 	// Iterate over the ConfigDescriptions map to find matching keys
 	for key, description := range types.ConfigDescriptions {
 		if strings.HasPrefix(key, toComplete) {
-			completion := fmt.Sprintf("%s\t%s", key, description)
+			completion := fmt.Sprintf("%s=\t%s", key, description)
 			completions = append(completions, completion)
 		}
 	}
@@ -93,14 +93,20 @@ func (cf *ConfigFlag) Parse() error {
 }
 
 func setIfValid(v *viper.Viper, key string, value any) error {
-	if _, ok := types.ConfigDescriptions[strings.ToLower(key)]; !ok {
+	key = strings.ToLower(key)
+	_, ok := types.AllKeys()[key]
+	if !ok {
 		if _, err := os.Stat(key); err == nil {
 			return fmt.Errorf("config files must end in suffix '.yaml' or '.yml'")
 		}
 		return fmt.Errorf("no config key matching %q run 'bacalhau config list' for a list of valid keys", key)
 	}
+	parsed, err := types.CastConfigValueForKey(key, value)
+	if err != nil {
+		return err
+	}
 	configMap := v.GetStringMap(RootCommandConfigValues)
-	configMap[key] = value
+	configMap[key] = parsed
 	v.Set(RootCommandConfigValues, configMap)
 	return nil
 }
diff --git a/cmd/util/flags/cliflags/repo.go b/cmd/util/flags/cliflags/repo.go
deleted file mode 100644
index df92e06555..0000000000
--- a/cmd/util/flags/cliflags/repo.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package cliflags
-
-import (
-	"os"
-	"path/filepath"
-
-	"github.com/rs/zerolog/log"
-)
-
-const defaultBacalhauDir = ".bacalhau"
-
-// getDefaultRepo determines the appropriate default directory for storing repository data.
-// Priority order:
-// 1. If the environment variable BACALHAU_DIR is set and non-empty, use it.
-// 2. If the environment variable FIL_WALLET_ADDRESS is set, it tries to use ROOT_DIR.
-// 3. User's home directory with .bacalhau appended.
-// 4. User-specific configuration directory with .bacalhau appended.
-// 5. If all above fail, use .bacalhau in the current directory.
-// The function logs any errors encountered during the process and always returns a usable path.
-func getDefaultRepo() string {
-	if repoDir, set := os.LookupEnv("BACALHAU_DIR"); set && repoDir != "" {
-		return repoDir
-	}
-
-	if userHome, err := os.UserHomeDir(); err == nil {
-		return filepath.Join(userHome, defaultBacalhauDir)
-	}
-
-	if userDir, err := os.UserConfigDir(); err == nil {
-		return filepath.Join(userDir, defaultBacalhauDir)
-	}
-
-	log.Error().Msg("Failed to determine default repo path. Using current directory.")
-	return defaultBacalhauDir
-}
-
-type RepoFlag struct {
-	Value string
-}
-
-// NewRepoFlag creates a new RepoFlag with the default value set
-func NewRepoFlag() *RepoFlag {
-	return &RepoFlag{Value: getDefaultRepo()}
-}
-
-func (rf *RepoFlag) String() string {
-	return rf.Value
-}
-
-func (rf *RepoFlag) Set(value string) error {
-	rf.Value = value
-	return nil
-}
-
-func (rf *RepoFlag) Type() string {
-	return "string"
-}
diff --git a/cmd/util/flags/configflags/allow_local_paths.go b/cmd/util/flags/configflags/allow_local_paths.go
index 1ed6bba94a..651b2ded76 100644
--- a/cmd/util/flags/configflags/allow_local_paths.go
+++ b/cmd/util/flags/configflags/allow_local_paths.go
@@ -1,12 +1,16 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var AllowListLocalPathsFlags = []Definition{
 	{
-		FlagName:     "allow-listed-local-paths",
-		ConfigPath:   types.NodeAllowListedLocalPaths,
-		DefaultValue: Default.Node.AllowListedLocalPaths,
-		Description:  "Local paths that are allowed to be mounted into jobs",
+		FlagName:          "allow-listed-local-paths",
+		ConfigPath:        types.ComputeAllowListedLocalPathsKey,
+		DefaultValue:      types.Default.Compute.AllowListedLocalPaths,
+		Description:       "Local paths that are allowed to be mounted into jobs",
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeAllowListedLocalPathsKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/api.go b/cmd/util/flags/configflags/api.go
index 1936ac8451..11970e398e 100644
--- a/cmd/util/flags/configflags/api.go
+++ b/cmd/util/flags/configflags/api.go
@@ -1,93 +1,113 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var ClientAPIFlags = []Definition{
 	{
 		FlagName:     "api-host",
-		DefaultValue: Default.Node.ClientAPI.Host,
-		ConfigPath:   types.NodeClientAPIHost,
+		DefaultValue: types.Default.API.Host,
+		ConfigPath:   types.APIHostKey,
 		Description: `The host for the client and server to communicate on (via REST).
 Ignored if BACALHAU_API_HOST environment variable is set.`,
 		EnvironmentVariables: []string{"BACALHAU_API_HOST"},
 	},
 	{
 		FlagName:     "api-port",
-		DefaultValue: Default.Node.ClientAPI.Port,
-		ConfigPath:   types.NodeClientAPIPort,
+		DefaultValue: types.Default.API.Port,
+		ConfigPath:   types.APIPortKey,
 		Description: `The port for the client and server to communicate on (via REST).
 Ignored if BACALHAU_API_PORT environment variable is set.`,
 		EnvironmentVariables: []string{"BACALHAU_API_PORT"},
 	},
 	{
 		FlagName:             "tls",
-		DefaultValue:         Default.Node.ClientAPI.ClientTLS.UseTLS,
-		ConfigPath:           types.NodeClientAPIClientTLSUseTLS,
+		DefaultValue:         types.Default.API.TLS.UseTLS,
+		ConfigPath:           types.APITLSUseTLSKey,
 		Description:          `Instructs the client to use TLS`,
 		EnvironmentVariables: []string{"BACALHAU_API_TLS"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSUseTLSKey),
 	},
 	{
 		FlagName:     "cacert",
-		DefaultValue: Default.Node.ClientAPI.ClientTLS.CACert,
-		ConfigPath:   types.NodeClientAPIClientTLSCACert,
+		DefaultValue: types.Default.API.TLS.CAFile,
+		ConfigPath:   types.APITLSCAFileKey,
 		Description: `The location of a CA certificate file when self-signed certificates
 	are used by the server`,
 		EnvironmentVariables: []string{"BACALHAU_API_CACERT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSCAFileKey),
 	},
 	{
 		FlagName:             "insecure",
-		DefaultValue:         Default.Node.ClientAPI.ClientTLS.Insecure,
-		ConfigPath:           types.NodeClientAPIClientTLSInsecure,
+		DefaultValue:         types.Default.API.TLS.Insecure,
+		ConfigPath:           types.APITLSInsecureKey,
 		Description:          `Enables TLS but does not verify certificates`,
 		EnvironmentVariables: []string{"BACALHAU_API_INSECURE"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSInsecureKey),
 	},
 }
 
 var ServerAPIFlags = []Definition{
 	{
 		FlagName:             "port",
-		DefaultValue:         Default.Node.ServerAPI.Port,
-		ConfigPath:           types.NodeServerAPIPort,
+		DefaultValue:         types.Default.API.Port,
+		ConfigPath:           types.APIPortKey,
 		Description:          `The port to server on.`,
 		EnvironmentVariables: []string{"BACALHAU_SERVER_PORT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APIPortKey),
 	},
 	{
 		FlagName:             "host",
-		DefaultValue:         Default.Node.ServerAPI.Host,
-		ConfigPath:           types.NodeServerAPIHost,
+		DefaultValue:         types.Default.API.Host,
+		ConfigPath:           types.APIHostKey,
 		Description:          `The host to serve on.`,
 		EnvironmentVariables: []string{"BACALHAU_SERVER_HOST"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APIHostKey),
 	},
 }
 
 var RequesterTLSFlags = []Definition{
 	{
 		FlagName:     "autocert",
-		DefaultValue: Default.Node.ServerAPI.TLS.AutoCert,
-		ConfigPath:   types.NodeServerAPITLSAutoCert,
+		DefaultValue: types.Default.API.TLS.AutoCert,
+		ConfigPath:   types.APITLSAutoCertKey,
 		Description: `Specifies a host name for which ACME is used to obtain a TLS Certificate.
 Using this option results in the API serving over HTTPS`,
 		EnvironmentVariables: []string{"BACALHAU_AUTO_TLS"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSAutoCertKey),
 	},
 	{
 		FlagName:             "tlscert",
-		DefaultValue:         Default.Node.ServerAPI.TLS.ServerCertificate,
-		ConfigPath:           types.NodeServerAPITLSServerCertificate,
+		DefaultValue:         types.Default.API.TLS.CertFile,
+		ConfigPath:           types.APITLSCertFileKey,
 		Description:          `Specifies a TLS certificate file to be used by the requester node`,
 		EnvironmentVariables: []string{"BACALHAU_TLS_CERT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSCertFileKey),
 	},
 	{
 		FlagName:             "tlskey",
-		DefaultValue:         Default.Node.ServerAPI.TLS.ServerKey,
-		ConfigPath:           types.NodeServerAPITLSServerKey,
+		DefaultValue:         types.Default.API.TLS.KeyFile,
+		ConfigPath:           types.APITLSKeyFileKey,
 		Description:          `Specifies a TLS key file matching the certificate to be used by the requester node`,
 		EnvironmentVariables: []string{"BACALHAU_TLS_KEY"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSKeyFileKey),
 	},
 	{
 		FlagName:             "self-signed",
-		DefaultValue:         Default.Node.ServerAPI.TLS.SelfSigned,
-		ConfigPath:           types.NodeServerAPITLSSelfSigned,
+		DefaultValue:         types.Default.API.TLS.SelfSigned,
+		ConfigPath:           types.APITLSSelfSignedKey,
 		Description:          `Specifies whether to auto-generate a self-signed certificate for the requester node`,
 		EnvironmentVariables: []string{"BACALHAU_TLS_SELFSIGNED"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.APITLSSelfSignedKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/capacity.go b/cmd/util/flags/configflags/capacity.go
index f55224f2dd..f347c82fb3 100644
--- a/cmd/util/flags/configflags/capacity.go
+++ b/cmd/util/flags/configflags/capacity.go
@@ -1,49 +1,72 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var CapacityFlags = []Definition{
+	// deprecated, with message pointing to corresponding --config flag.
 	{
-		FlagName:             "ignore-physical-resource-limits",
-		ConfigPath:           types.NodeComputeCapacityIgnorePhysicalResourceLimits,
-		DefaultValue:         Default.Node.Compute.Capacity.IgnorePhysicalResourceLimits,
-		Description:          `When set the compute node will ignore is physical resource limits`,
-		EnvironmentVariables: []string{"BACALHAU_CAPACITY_MANAGER_OVER_COMMIT"},
+		FlagName:          "limit-total-cpu",
+		ConfigPath:        types.ComputeAllocatedCapacityCPUKey,
+		DefaultValue:      types.Default.Compute.AllocatedCapacity.CPU,
+		Description:       `Total CPU core limit to run all jobs (e.g. 500m, 2, 8, 80%, 10%).`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeAllocatedCapacityCPUKey),
 	},
 	{
-		FlagName:     "limit-total-cpu",
-		ConfigPath:   types.NodeComputeCapacityTotalResourceLimitsCPU,
-		DefaultValue: Default.Node.Compute.Capacity.TotalResourceLimits.CPU,
-		Description:  `Total CPU core limit to run all jobs (e.g. 500m, 2, 8).`,
+		FlagName:          "limit-total-memory",
+		ConfigPath:        types.ComputeAllocatedCapacityMemoryKey,
+		DefaultValue:      types.Default.Compute.AllocatedCapacity.Memory,
+		Description:       `Total Memory limit to run all jobs  (e.g. 500Mb, 2Gb, 8Gb, 80%, 10%).`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeAllocatedCapacityMemoryKey),
 	},
 	{
-		FlagName:     "limit-total-memory",
-		ConfigPath:   types.NodeComputeCapacityTotalResourceLimitsMemory,
-		DefaultValue: Default.Node.Compute.Capacity.TotalResourceLimits.Memory,
-		Description:  `Total Memory limit to run all jobs  (e.g. 500Mb, 2Gb, 8Gb).`,
+		FlagName:          "limit-total-gpu",
+		ConfigPath:        types.ComputeAllocatedCapacityGPUKey,
+		DefaultValue:      types.Default.Compute.AllocatedCapacity.GPU,
+		Description:       `Total GPU limit to run all jobs (e.g. 1, 2, 80%, 10%).`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeAllocatedCapacityGPUKey),
+	},
+
+	// deprecated, the feature is no longer supported
+	{
+		FlagName:             "ignore-physical-resource-limits",
+		ConfigPath:           "ignore.physical.resource.limits.deprecated",
+		Description:          `When set the compute node will ignore is physical resource limits`,
+		EnvironmentVariables: []string{"BACALHAU_CAPACITY_MANAGER_OVER_COMMIT"},
+		DefaultValue:         "",
+		Deprecated:           true,
+		DeprecatedMessage:    FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "limit-total-gpu",
-		ConfigPath:   types.NodeComputeCapacityTotalResourceLimitsGPU,
-		DefaultValue: Default.Node.Compute.Capacity.TotalResourceLimits.GPU,
-		Description:  `Total GPU limit to run all jobs (e.g. 1, 2, or 8).`,
+		FlagName:          "limit-job-cpu",
+		ConfigPath:        "limit.job.cpu.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "limit-job-cpu",
-		ConfigPath:   types.NodeComputeCapacityJobResourceLimitsCPU,
-		DefaultValue: Default.Node.Compute.Capacity.JobResourceLimits.CPU,
-		Description:  `Job CPU core limit to run all jobs (e.g. 500m, 2, 8).`,
+		FlagName:          "limit-job-memory",
+		ConfigPath:        "limit.job.memory.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "limit-job-memory",
-		ConfigPath:   types.NodeComputeCapacityDefaultJobResourceLimitsMemory,
-		DefaultValue: Default.Node.Compute.Capacity.JobResourceLimits.Memory,
-		Description:  `Job Memory limit to run all jobs  (e.g. 500Mb, 2Gb, 8Gb).`,
+		FlagName:          "limit-job-disk",
+		ConfigPath:        "limit.job.disk.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "limit-job-gpu",
-		ConfigPath:   types.NodeComputeCapacityJobResourceLimitsGPU,
-		DefaultValue: Default.Node.Compute.Capacity.JobResourceLimits.GPU,
-		Description:  `Job GPU limit to run all jobs (e.g. 1, 2, or 8).`,
+		FlagName:          "limit-job-gpu",
+		ConfigPath:        "limit.job.gpu.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 }
diff --git a/cmd/util/flags/configflags/compute.go b/cmd/util/flags/configflags/compute.go
new file mode 100644
index 0000000000..c70c7b0863
--- /dev/null
+++ b/cmd/util/flags/configflags/compute.go
@@ -0,0 +1,14 @@
+package configflags
+
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
+
+var ComputeFlags = []Definition{
+	{
+		FlagName:     "compute",
+		ConfigPath:   types.ComputeEnabledKey,
+		DefaultValue: types.Default.Compute.Enabled,
+		Description:  "When true the compute service will be enabled.",
+	},
+}
diff --git a/cmd/util/flags/configflags/compute_storage.go b/cmd/util/flags/configflags/compute_storage.go
index 464e02cb90..53a1dd39cf 100644
--- a/cmd/util/flags/configflags/compute_storage.go
+++ b/cmd/util/flags/configflags/compute_storage.go
@@ -1,20 +1,19 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
-
+// deprecated
 var ComputeStorageFlags = []Definition{
 	{
-		FlagName:             "compute-execution-store-type",
-		ConfigPath:           types.NodeComputeExecutionStoreType,
-		DefaultValue:         Default.Node.Compute.ExecutionStore.Type,
-		Description:          "The type of store used by the compute node (BoltDB)",
-		EnvironmentVariables: []string{"BACALHAU_COMPUTE_STORE_TYPE"},
+		FlagName:          "compute-execution-store-type",
+		ConfigPath:        "compute.execution.store.type.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: "type is no longer configurable. bacalhau uses BoltDB",
 	},
 	{
-		FlagName:             "compute-execution-store-path",
-		ConfigPath:           types.NodeComputeExecutionStorePath,
-		DefaultValue:         Default.Node.Compute.ExecutionStore.Path,
-		Description:          "The path used for the compute execution store when using BoltDB",
-		EnvironmentVariables: []string{"BACALHAU_COMPUTE_STORE_PATH"},
+		FlagName:          "compute-execution-store-path",
+		ConfigPath:        "compute.execution.store.path.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: "path is no longer configurable. location $BACALHAU_DIR/compute/state_boltdb.db",
 	},
 }
diff --git a/cmd/util/flags/configflags/datadir.go b/cmd/util/flags/configflags/datadir.go
new file mode 100644
index 0000000000..5440a56943
--- /dev/null
+++ b/cmd/util/flags/configflags/datadir.go
@@ -0,0 +1,24 @@
+package configflags
+
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
+
+var DataDirFlag = []Definition{
+	{
+		FlagName:             "repo",
+		ConfigPath:           types.DataDirKey,
+		DefaultValue:         types.Default.DataDir,
+		Description:          "The filesystem path bacalhau inits or opens a repo in",
+		EnvironmentVariables: []string{"BACALHAU_DIR"},
+		Deprecated:           true,
+		DeprecatedMessage:    "Use --data-dir=<path> to set this configuration",
+	},
+	{
+		FlagName:             "data-dir",
+		ConfigPath:           types.DataDirKey,
+		DefaultValue:         types.Default.DataDir,
+		Description:          "The filesystem path bacalhau inits or opens a repo in",
+		EnvironmentVariables: []string{"BACALHAU_DIR"},
+	},
+}
diff --git a/cmd/util/flags/configflags/defaults.go b/cmd/util/flags/configflags/defaults.go
deleted file mode 100644
index 5b09ea6ec1..0000000000
--- a/cmd/util/flags/configflags/defaults.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package configflags
-
-import (
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
-)
-
-// Default is the default value used by flags. It will be overridden by any values in the config file.
-// We can configure the default flag values by setting `Default` to a different config environment.
-var Default = configenv.Production
diff --git a/cmd/util/flags/configflags/deprecation.go b/cmd/util/flags/configflags/deprecation.go
new file mode 100644
index 0000000000..4b583cc7c2
--- /dev/null
+++ b/cmd/util/flags/configflags/deprecation.go
@@ -0,0 +1,15 @@
+package configflags
+
+import (
+	"fmt"
+)
+
+const FeatureDeprecatedMessage = "This feature has been deprecated and is no longer functional. The flag has no effect and can be safely removed."
+
+func makeDeprecationMessage(key string) string {
+	return fmt.Sprintf("Use %s to set this configuration", makeConfigFlagDeprecationCommand(key))
+}
+
+func makeConfigFlagDeprecationCommand(key string) string {
+	return fmt.Sprintf("--config %s=<value>", key)
+}
diff --git a/cmd/util/flags/configflags/disabled_features.go b/cmd/util/flags/configflags/disabled_features.go
index 9bced1de23..124306b1ca 100644
--- a/cmd/util/flags/configflags/disabled_features.go
+++ b/cmd/util/flags/configflags/disabled_features.go
@@ -1,24 +1,32 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var DisabledFeatureFlags = []Definition{
 	{
-		FlagName:     "disable-engine",
-		ConfigPath:   types.NodeDisabledFeaturesEngines,
-		DefaultValue: Default.Node.DisabledFeatures.Engines,
-		Description:  "Engine types to disable",
+		FlagName:          "disable-engine",
+		ConfigPath:        types.EnginesDisabledKey,
+		DefaultValue:      types.Default.Engines.Disabled,
+		Description:       "Engine types to disable",
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.EnginesDisabledKey),
 	},
 	{
-		FlagName:     "disabled-publisher",
-		ConfigPath:   types.NodeDisabledFeaturesPublishers,
-		DefaultValue: Default.Node.DisabledFeatures.Publishers,
-		Description:  "Publisher types to disable",
+		FlagName:          "disabled-publisher",
+		ConfigPath:        types.PublishersDisabledKey,
+		DefaultValue:      types.Default.Publishers.Disabled,
+		Description:       "Publisher types to disable",
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.PublishersDisabledKey),
 	},
 	{
-		FlagName:     "disable-storage",
-		ConfigPath:   types.NodeDisabledFeaturesStorages,
-		DefaultValue: Default.Node.DisabledFeatures.Storages,
-		Description:  "Storage types to disable",
+		FlagName:          "disable-storage",
+		ConfigPath:        types.InputSourcesDisabledKey,
+		DefaultValue:      types.Default.InputSources.Disabled,
+		Description:       "Storage types to disable",
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.InputSourcesDisabledKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/docker_cache.go b/cmd/util/flags/configflags/docker_cache.go
index 0dcbb5a84f..4dffad477d 100644
--- a/cmd/util/flags/configflags/docker_cache.go
+++ b/cmd/util/flags/configflags/docker_cache.go
@@ -1,27 +1,35 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var DockerManifestCacheFlags = []Definition{
 	{
 		FlagName:             "docker-manifest-cache-size",
-		ConfigPath:           types.NodeComputeManifestCacheSize,
-		DefaultValue:         Default.Node.Compute.ManifestCache.Size,
+		ConfigPath:           types.EnginesTypesDockerManifestCacheSizeKey,
+		DefaultValue:         types.Default.Engines.Types.Docker.ManifestCache.Size,
 		Description:          `Specifies the number of items that can be held in the manifest cache`,
 		EnvironmentVariables: []string{"BACALHAU_DOCKER_MANIFEST_CACHE_SIZE"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.EnginesTypesDockerManifestCacheSizeKey),
 	},
 	{
 		FlagName:             "docker-manifest-cache-duration",
-		ConfigPath:           types.NodeComputeManifestCacheDuration,
-		DefaultValue:         Default.Node.Compute.ManifestCache.Duration,
+		ConfigPath:           types.EnginesTypesDockerManifestCacheTTLKey,
+		DefaultValue:         types.Default.Engines.Types.Docker.ManifestCache.TTL,
 		Description:          `The default time-to-live for each record in the manifest cache`,
 		EnvironmentVariables: []string{"BACALHAU_DOCKER_MANIFEST_CACHE_DURATION"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.EnginesTypesDockerManifestCacheTTLKey),
 	},
 	{
 		FlagName:             "docker-manifest-cache-frequency",
-		ConfigPath:           types.NodeComputeManifestCacheFrequency,
-		DefaultValue:         Default.Node.Compute.ManifestCache.Frequency,
+		ConfigPath:           types.EnginesTypesDockerManifestCacheRefreshKey,
+		DefaultValue:         types.Default.Engines.Types.Docker.ManifestCache.Refresh,
 		Description:          `The frequency that the checks for stale records is performed`,
 		EnvironmentVariables: []string{"BACALHAU_DOCKER_MANIFEST_CACHE_FREQUENCY"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.EnginesTypesDockerManifestCacheRefreshKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/ipfs.go b/cmd/util/flags/configflags/ipfs.go
index aaf6da9662..d247a11e4d 100644
--- a/cmd/util/flags/configflags/ipfs.go
+++ b/cmd/util/flags/configflags/ipfs.go
@@ -1,12 +1,48 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"fmt"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var IPFSFlags = []Definition{
 	{
 		FlagName:     "ipfs-connect",
-		ConfigPath:   types.NodeIPFSConnect,
-		DefaultValue: Default.Node.IPFS.Connect,
-		Description:  "The ipfs host multiaddress to connect to, otherwise an in-process IPFS node will be created if not set.",
+		ConfigPath:   "ipfs.connect.deprecated",
+		DefaultValue: "",
+		Deprecated:   true,
+		DeprecatedMessage: fmt.Sprintf("Use one or more of the following options, all are accepted %s, %s, %s",
+			makeConfigFlagDeprecationCommand(types.InputSourcesTypesIPFSEndpointKey),
+			makeConfigFlagDeprecationCommand(types.PublishersTypesIPFSEndpointKey),
+			makeConfigFlagDeprecationCommand(types.ResultDownloadersTypesIPFSEndpointKey),
+		),
+	},
+	{
+		FlagName:             "ipfs-connect-storage",
+		ConfigPath:           types.InputSourcesTypesIPFSEndpointKey,
+		DefaultValue:         types.Default.InputSources.Types.IPFS.Endpoint,
+		Description:          "The ipfs host multiaddress to connect to for inputs, otherwise an in-process IPFS node will be created if not set.",
+		EnvironmentVariables: []string{"BACALHAU_NODE_IPFS_CONNECT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.InputSourcesTypesIPFSEndpointKey),
+	},
+	{
+		FlagName:             "ipfs-connect-publisher",
+		ConfigPath:           types.PublishersTypesIPFSEndpointKey,
+		DefaultValue:         types.Default.Publishers.Types.IPFS.Endpoint,
+		Description:          "The ipfs host multiaddress to connect to for publishing, otherwise an in-process IPFS node will be created if not set.",
+		EnvironmentVariables: []string{"BACALHAU_NODE_IPFS_CONNECT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.PublishersTypesIPFSEndpointKey),
+	},
+	{
+		FlagName:             "ipfs-connect-downloader",
+		ConfigPath:           types.ResultDownloadersTypesIPFSEndpointKey,
+		DefaultValue:         types.Default.ResultDownloaders.Types.IPFS.Endpoint,
+		Description:          "The ipfs host multiaddress to connect to for downloading, otherwise an in-process IPFS node will be created if not set.",
+		EnvironmentVariables: []string{"BACALHAU_NODE_IPFS_CONNECT"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.ResultDownloadersTypesIPFSEndpointKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/job_selection.go b/cmd/util/flags/configflags/job_selection.go
index 6f80a7b342..d6fd9846d9 100644
--- a/cmd/util/flags/configflags/job_selection.go
+++ b/cmd/util/flags/configflags/job_selection.go
@@ -1,43 +1,47 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
-
-//
-// Requester Job Selection Policy
-//
-// TODO: https://github.com/bacalhau-project/bacalhau/issues/2929
-// The flags are currently settable on the requester, however the requester does not support a JobSelectionPolicy
-// setting the flags is a noop until the above issue is fixed.
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var JobSelectionFlags = []Definition{
 	{
-		FlagName:     "job-selection-data-locality",
-		ConfigPath:   types.NodeComputeJobSelectionLocality,
-		DefaultValue: Default.Node.Compute.JobSelection.Locality,
-		Description:  `Only accept jobs that reference data we have locally ("local") or anywhere ("anywhere").`,
+		FlagName:          "job-selection-data-locality",
+		ConfigPath:        "job.selection.data.locality.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "job-selection-reject-stateless",
-		ConfigPath:   types.NodeComputeJobSelectionRejectStatelessJobs,
-		DefaultValue: Default.Node.Compute.JobSelection.RejectStatelessJobs,
-		Description:  `Reject jobs that don't specify any data.`,
+		FlagName:          "job-selection-reject-stateless",
+		ConfigPath:        types.JobAdmissionControlRejectStatelessJobsKey,
+		DefaultValue:      types.Default.JobAdmissionControl.RejectStatelessJobs,
+		Description:       `Reject jobs that don't specify any data.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.JobAdmissionControlRejectStatelessJobsKey),
 	},
 	{
-		FlagName:     "job-selection-accept-networked",
-		ConfigPath:   types.NodeComputeJobSelectionAcceptNetworkedJobs,
-		DefaultValue: Default.Node.Compute.JobSelection.AcceptNetworkedJobs,
-		Description:  `Accept jobs that require network access.`,
+		FlagName:          "job-selection-accept-networked",
+		ConfigPath:        types.JobAdmissionControlAcceptNetworkedJobsKey,
+		DefaultValue:      types.Default.JobAdmissionControl.AcceptNetworkedJobs,
+		Description:       `Accept jobs that require network access.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.JobAdmissionControlAcceptNetworkedJobsKey),
 	},
 	{
-		FlagName:     "job-selection-probe-http",
-		ConfigPath:   types.NodeComputeJobSelectionProbeHTTP,
-		DefaultValue: Default.Node.Compute.JobSelection.ProbeHTTP,
-		Description:  `Use the result of a HTTP POST to decide if we should take on the job.`,
+		FlagName:          "job-selection-probe-http",
+		ConfigPath:        types.JobAdmissionControlProbeHTTPKey,
+		DefaultValue:      types.Default.JobAdmissionControl.ProbeHTTP,
+		Description:       `Use the result of a HTTP POST to decide if we should take on the job.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.JobAdmissionControlProbeHTTPKey),
 	},
 	{
-		FlagName:     "job-selection-probe-exec",
-		ConfigPath:   types.NodeComputeJobSelectionProbeExec,
-		DefaultValue: Default.Node.Compute.JobSelection.ProbeExec,
-		Description:  `Use the result of a exec an external program to decide if we should take on the job.`,
+		FlagName:          "job-selection-probe-exec",
+		ConfigPath:        types.JobAdmissionControlProbeExecKey,
+		DefaultValue:      types.Default.JobAdmissionControl.ProbeExec,
+		Description:       `Use the result of a exec an external program to decide if we should take on the job.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.JobAdmissionControlProbeExecKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/job_storage.go b/cmd/util/flags/configflags/job_storage.go
index 40980fc228..04115ce000 100644
--- a/cmd/util/flags/configflags/job_storage.go
+++ b/cmd/util/flags/configflags/job_storage.go
@@ -1,20 +1,19 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
-
+// deprecated
 var RequesterJobStorageFlags = []Definition{
 	{
-		FlagName:             "requester-job-store-type",
-		ConfigPath:           types.NodeRequesterJobStoreType,
-		DefaultValue:         Default.Node.Requester.JobStore.Type,
-		Description:          "The type of job store used by the requester node (BoltDB)",
-		EnvironmentVariables: []string{"BACALHAU_JOB_STORE_TYPE"},
+		FlagName:          "requester-job-store-type",
+		ConfigPath:        "requester.job.store.type.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: "type is no longer configurable. bacalhau uses BoltDB",
 	},
 	{
-		FlagName:             "requester-job-store-path",
-		ConfigPath:           types.NodeRequesterJobStorePath,
-		DefaultValue:         Default.Node.Requester.JobStore.Path,
-		Description:          "The path used for the requester job store store when using BoltDB",
-		EnvironmentVariables: []string{"BACALHAU_JOB_STORE_PATH"},
+		FlagName:          "requester-job-store-path",
+		ConfigPath:        "requester.job.store.path.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: "path is no longer configurable. location $BACALHAU_DIR/orchestrator/state_boltdb.db",
 	},
 }
diff --git a/cmd/util/flags/configflags/job_translation.go b/cmd/util/flags/configflags/job_translation.go
index 0817ce4b45..cecaf674db 100644
--- a/cmd/util/flags/configflags/job_translation.go
+++ b/cmd/util/flags/configflags/job_translation.go
@@ -1,12 +1,16 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var JobTranslationFlags = []Definition{
 	{
-		FlagName:     "requester-job-translation-enabled",
-		DefaultValue: Default.Node.Requester.TranslationEnabled,
-		ConfigPath:   types.NodeRequesterTranslationEnabled,
-		Description:  `Whether jobs should be translated at the requester node or not. Default: false`,
+		FlagName:          "requester-job-translation-enabled",
+		ConfigPath:        types.FeatureFlagsExecTranslationKey,
+		DefaultValue:      types.Default.FeatureFlags.ExecTranslation,
+		Description:       `Whether jobs should be translated at the requester node or not. Default: false`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.FeatureFlagsExecTranslationKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/labels.go b/cmd/util/flags/configflags/labels.go
index 3987fcdaf8..90dcf5d772 100644
--- a/cmd/util/flags/configflags/labels.go
+++ b/cmd/util/flags/configflags/labels.go
@@ -1,13 +1,17 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var LabelFlags = []Definition{
 	{
 		FlagName:     "labels",
-		ConfigPath:   types.NodeLabels,
-		DefaultValue: Default.Node.Labels,
+		ConfigPath:   types.ComputeLabelsKey,
+		DefaultValue: types.Default.Compute.Labels,
 		//nolint:lll
-		Description: `Labels to be associated with the node that can be used for node selection and filtering. (e.g. --labels key1=value1,key2=value2)`,
+		Description:       `Labels to be associated with the compute node that can be used for node selection and filtering. (e.g. --labels key1=value1,key2=value2)`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeLabelsKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/local_publisher.go b/cmd/util/flags/configflags/local_publisher.go
index 0bf7a59e8e..f1432cacc6 100644
--- a/cmd/util/flags/configflags/local_publisher.go
+++ b/cmd/util/flags/configflags/local_publisher.go
@@ -1,24 +1,32 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var LocalPublisherFlags = []Definition{
 	{
-		FlagName:     "local-publisher-address",
-		DefaultValue: Default.Node.Compute.LocalPublisher.Address,
-		ConfigPath:   types.NodeComputeLocalPublisherAddress,
-		Description:  `The address for the local publisher's server to bind to`,
+		FlagName:          "local-publisher-address",
+		DefaultValue:      types.Default.Publishers.Types.Local.Address,
+		ConfigPath:        types.PublishersTypesLocalAddressKey,
+		Description:       `The address for the local publisher's server to bind to.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.PublishersTypesLocalAddressKey),
 	},
 	{
-		FlagName:     "local-publisher-port",
-		DefaultValue: Default.Node.Compute.LocalPublisher.Port,
-		ConfigPath:   types.NodeComputeLocalPublisherPort,
-		Description:  `The port for the local publisher's server to bind to (default: 6001)`,
+		FlagName:          "local-publisher-port",
+		DefaultValue:      types.Default.Publishers.Types.Local.Port,
+		ConfigPath:        types.PublishersTypesLocalPortKey,
+		Description:       `The port for the local publisher's server to bind to.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.PublishersTypesLocalPortKey),
 	},
 	{
-		FlagName:     "local-publisher-directory",
-		DefaultValue: Default.Node.Compute.LocalPublisher.Directory,
-		ConfigPath:   types.NodeComputeLocalPublisherDirectory,
-		Description:  `The directory where the local publisher will store content`,
+		FlagName:          "local-publisher-directory",
+		DefaultValue:      types.Default.Publishers.Types.Local.Directory,
+		ConfigPath:        types.PublishersTypesLocalDirectoryKey,
+		Description:       `The directory where the local publisher will store content.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.PublishersTypesLocalDirectoryKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/logging.go b/cmd/util/flags/configflags/logging.go
index 2da4dea7da..152770e721 100644
--- a/cmd/util/flags/configflags/logging.go
+++ b/cmd/util/flags/configflags/logging.go
@@ -2,14 +2,24 @@ package configflags
 
 import (
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
 )
 
 var LogFlags = []Definition{
 	{
-		FlagName:     "log-mode",
-		DefaultValue: logger.LogModeDefault,
-		ConfigPath:   types.NodeLoggingMode,
-		Description:  `Log format: 'default','station','json','combined','event'`,
+		FlagName:          "log-mode",
+		DefaultValue:      types.Default.Logging.Mode,
+		ConfigPath:        types.LoggingModeKey,
+		Description:       `Log format: 'default','station','json','combined','event'`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.LoggingModeKey),
+	},
+	{
+		FlagName:             "log-level",
+		DefaultValue:         types.Default.Logging.Level,
+		ConfigPath:           types.LoggingLevelKey,
+		Description:          `Log level: 'trace', 'debug', 'info', 'warn', 'error', 'fatal', 'panic'`,
+		EnvironmentVariables: []string{"LOG_LEVEL"},
+		Deprecated:           true,
+		DeprecatedMessage:    makeDeprecationMessage(types.LoggingLevelKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/names.go b/cmd/util/flags/configflags/names.go
deleted file mode 100644
index bfb2a7ff50..0000000000
--- a/cmd/util/flags/configflags/names.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package configflags
-
-import (
-	"fmt"
-
-	"github.com/samber/lo"
-)
-
-// FlagDefForKey accepts a configuration key and slice of Definition's containing the key.
-// It returns the Definition for the specific key or panics if the key is not part of the definition.
-func FlagDefForKey(key string, def ...Definition) Definition {
-	f, found := lo.Find(def, func(item Definition) bool {
-		return item.ConfigPath == key
-	})
-	if !found {
-		// represents a developer error to call this method with invalid key and definition pair.
-		panic(fmt.Sprintf("Key: %s not found in Definition: %+v", key, def))
-	}
-
-	return f
-}
-
-// FlagNameForKey accepts a configuration key and slice of Definition's containing the key.
-// It returns the name of the flag corresponding to the key prefixed with `--`, or panics if the key
-// is not part of the definition.
-func FlagNameForKey(key string, def ...Definition) string {
-	return "--" + FlagDefForKey(key, def...).FlagName
-}
diff --git a/cmd/util/flags/configflags/network.go b/cmd/util/flags/configflags/network.go
index 9f0bda6110..85cecc282b 100644
--- a/cmd/util/flags/configflags/network.go
+++ b/cmd/util/flags/configflags/network.go
@@ -1,54 +1,103 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var NetworkFlags = []Definition{
 	{
-		FlagName:     "network-port",
-		ConfigPath:   types.NodeNetworkPort,
-		DefaultValue: Default.Node.Network.Port,
-		Description:  `Port to listen for connections from other nodes. Applies to orchestrator nodes.`,
+		FlagName:     "orchestrator",
+		ConfigPath:   types.OrchestratorEnabledKey,
+		DefaultValue: types.Default.Orchestrator.Enabled,
+		Description:  "When true the orchestrator service will be enabled.",
 	},
 	{
-		FlagName:     "network-store-dir",
-		ConfigPath:   types.NodeNetworkStoreDir,
-		DefaultValue: Default.Node.Network.StoreDir,
-		Description:  `Directory that network can use for storage`,
+		FlagName:          "requester",
+		ConfigPath:        types.OrchestratorEnabledKey,
+		DefaultValue:      types.Default.Orchestrator.Enabled,
+		Description:       "When true the orchestrator service will be enabled.",
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorEnabledKey),
 	},
 	{
-		FlagName:     "orchestrators",
-		ConfigPath:   types.NodeNetworkOrchestrators,
-		DefaultValue: Default.Node.Network.Orchestrators,
-		Description:  `Comma-separated list of orchestrators to connect to. Applies to compute nodes.`,
+		FlagName:          "network-host",
+		ConfigPath:        types.OrchestratorHostKey,
+		DefaultValue:      types.Default.Orchestrator.Host,
+		Description:       `Host to listen for connections from other nodes. Applies to orchestrator nodes.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorHostKey),
 	},
 	{
-		FlagName:     "advertised-address",
-		ConfigPath:   types.NodeNetworkAdvertisedAddress,
-		DefaultValue: Default.Node.Network.AdvertisedAddress,
-		Description:  `Address to advertise to compute nodes to connect to.`,
+		FlagName:          "network-port",
+		ConfigPath:        types.OrchestratorPortKey,
+		DefaultValue:      types.Default.Orchestrator.Port,
+		Description:       `Port to listen for connections from other nodes. Applies to orchestrator nodes.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorPortKey),
 	},
 	{
-		FlagName:     "cluster-name",
-		ConfigPath:   types.NodeNetworkClusterName,
-		DefaultValue: Default.Node.Network.Cluster.Name,
-		Description:  `Name of the cluster to join.`,
+		FlagName:          "orchestrators",
+		ConfigPath:        types.ComputeOrchestratorsKey,
+		DefaultValue:      types.Default.Compute.Orchestrators,
+		Description:       `Comma-separated list of orchestrators to connect to. Applies to compute nodes.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.ComputeOrchestratorsKey),
 	},
 	{
-		FlagName:     "cluster-port",
-		ConfigPath:   types.NodeNetworkClusterPort,
-		DefaultValue: Default.Node.Network.Cluster.Port,
-		Description:  `Port to listen for connections from other orchestrators to form a cluster.`,
+		FlagName:          "advertised-address",
+		ConfigPath:        types.OrchestratorAdvertiseKey,
+		DefaultValue:      types.Default.Orchestrator.Advertise,
+		Description:       `Address to advertise to compute nodes to connect to.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorAdvertiseKey),
 	},
 	{
-		FlagName:     "cluster-advertised-address",
-		ConfigPath:   types.NodeNetworkClusterAdvertisedAddress,
-		DefaultValue: Default.Node.Network.Cluster.AdvertisedAddress,
-		Description:  `Address to advertise to other orchestrators to connect to.`,
+		FlagName:          "cluster-name",
+		ConfigPath:        types.OrchestratorClusterNameKey,
+		DefaultValue:      types.Default.Orchestrator.Cluster.Name,
+		Description:       `Name of the cluster to join.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorClusterNameKey),
 	},
 	{
-		FlagName:     "cluster-peers",
-		ConfigPath:   types.NodeNetworkClusterPeers,
-		DefaultValue: Default.Node.Network.Cluster.Peers,
-		Description:  `Comma-separated list of other orchestrators to connect to to form a cluster.`,
+		FlagName:          "cluster-host",
+		ConfigPath:        types.OrchestratorClusterHostKey,
+		DefaultValue:      types.Default.Orchestrator.Cluster.Host,
+		Description:       `Address to listen for connections from other orchestrators to form a cluster.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorClusterHostKey),
+	},
+	{
+		FlagName:          "cluster-port",
+		ConfigPath:        types.OrchestratorClusterPortKey,
+		DefaultValue:      types.Default.Orchestrator.Cluster.Port,
+		Description:       `Port to listen for connections from other orchestrators to form a cluster.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorClusterPortKey),
+	},
+	{
+		FlagName:          "cluster-advertised-address",
+		ConfigPath:        types.OrchestratorClusterAdvertiseKey,
+		DefaultValue:      types.Default.Orchestrator.Cluster.Advertise,
+		Description:       `Address to advertise to other orchestrators to connect to.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorClusterAdvertiseKey),
+	},
+	{
+		FlagName:          "cluster-peers",
+		ConfigPath:        types.OrchestratorClusterPeersKey,
+		DefaultValue:      types.Default.Orchestrator.Cluster.Peers,
+		Description:       `Comma-separated list of other orchestrators to connect to to form a cluster.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.OrchestratorClusterPeersKey),
+	},
+	// deprecated.
+	{
+		FlagName:          "network-store-dir",
+		ConfigPath:        "network.store.deprecated",
+		DefaultValue:      "",
+		Description:       `Directory that network can use for storage`,
+		Deprecated:        true,
+		DeprecatedMessage: "network path is no longer configurable, location: $BACALHAU_DIR/orchestrator/nats-store",
 	},
 }
diff --git a/cmd/util/flags/configflags/node_info_store.go b/cmd/util/flags/configflags/node_info_store.go
index c863eb6f81..4e80c51dd7 100644
--- a/cmd/util/flags/configflags/node_info_store.go
+++ b/cmd/util/flags/configflags/node_info_store.go
@@ -1,15 +1,12 @@
 package configflags
 
-import (
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-)
-
+// deprecated
 var NodeInfoStoreFlags = []Definition{
 	{
-		FlagName:     "node-info-store-ttl",
-		ConfigPath:   types.NodeRequesterNodeInfoStoreTTL,
-		DefaultValue: Default.Node.Requester.NodeInfoStoreTTL,
-		Description: `Sets the duration for which node information is retained in the node info store after which it
-is automatically removed from the store.`,
+		FlagName:          "node-info-store-ttl",
+		ConfigPath:        "node.info.store.ttl.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 }
diff --git a/cmd/util/flags/configflags/node_name.go b/cmd/util/flags/configflags/node_name.go
index 22a3cb69df..6943f8086d 100644
--- a/cmd/util/flags/configflags/node_name.go
+++ b/cmd/util/flags/configflags/node_name.go
@@ -1,18 +1,16 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var NodeNameFlags = []Definition{
 	{
-		FlagName:     "name",
-		ConfigPath:   types.NodeName,
-		DefaultValue: "",
-		Description:  `The name of the node. If not set, the node name will be generated automatically based on the chosen name provider.`,
-	},
-	{
-		FlagName:     "name-provider",
-		ConfigPath:   types.NodeNameProvider,
-		DefaultValue: Default.Node.NameProvider,
-		Description:  `The name provider to use to generate the node name, if no name is set.`,
+		FlagName:          "name-provider",
+		ConfigPath:        types.NameProviderKey,
+		DefaultValue:      types.Default.NameProvider,
+		Description:       `The name provider to use to generate the node name when the node initializes.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.NameProviderKey),
 	},
 }
diff --git a/cmd/util/flags/configflags/node_type.go b/cmd/util/flags/configflags/node_type.go
index 9781bf14b0..2b0541c4c1 100644
--- a/cmd/util/flags/configflags/node_type.go
+++ b/cmd/util/flags/configflags/node_type.go
@@ -1,12 +1,12 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
-
+// deprecated
 var NodeTypeFlags = []Definition{
 	{
-		FlagName:     "node-type",
-		ConfigPath:   types.NodeType,
-		DefaultValue: Default.Node.Type,
-		Description:  `Whether the node is a compute, requester or both.`,
+		FlagName:          "node-type",
+		ConfigPath:        "node.type.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: "Use --orchestrator and/or --compute to set the node type.",
 	},
 }
diff --git a/cmd/util/flags/configflags/publishing.go b/cmd/util/flags/configflags/publishing.go
index 2066caec13..e6668160a1 100644
--- a/cmd/util/flags/configflags/publishing.go
+++ b/cmd/util/flags/configflags/publishing.go
@@ -1,12 +1,21 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"fmt"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
+
+// deprecated
 var PublishingFlags = []Definition{
 	{
 		FlagName:     "default-publisher",
-		DefaultValue: Default.Node.Requester.DefaultPublisher,
-		ConfigPath:   types.NodeRequesterDefaultPublisher,
-		Description:  `A default publisher to apply to all jobs without a publisher`,
+		ConfigPath:   "default.publisher.deprecated",
+		DefaultValue: "",
+		Deprecated:   true,
+		DeprecatedMessage: fmt.Sprintf("Use one or more of the following options, all are accepted %s, %s",
+			makeConfigFlagDeprecationCommand(types.JobDefaultsBatchTaskPublisherConfigTypeKey),
+			makeConfigFlagDeprecationCommand(types.JobDefaultsOpsTaskPublisherConfigParamsKey),
+		),
 	},
 }
diff --git a/cmd/util/flags/configflags/register.go b/cmd/util/flags/configflags/register.go
index 8b2a7c9337..662cef0a07 100644
--- a/cmd/util/flags/configflags/register.go
+++ b/cmd/util/flags/configflags/register.go
@@ -46,11 +46,13 @@ func BindFlags(v *viper.Viper, register map[string][]Definition) error {
 	for _, defs := range register {
 		for _, def := range defs {
 			// sanity check to ensure we are not binding a config key on more than one flag.
-			if dup, ok := seen[def.ConfigPath]; ok {
+			if dup, ok := seen[def.ConfigPath]; ok && !def.Deprecated {
 				return fmt.Errorf("DEVELOPER ERROR: duplicate regsistration of config key %s for flag %s"+
 					" previously registered on on flag %s", def.ConfigPath, def.FlagName, dup.FlagName)
 			}
-			seen[def.ConfigPath] = def
+			if !def.Deprecated {
+				seen[def.ConfigPath] = def
+			}
 			flagDefs := viper.Get(cliflags.RootCommandConfigFlags)
 			if flagDefs == nil {
 				flagDefs = make([]Definition, 0)
@@ -102,8 +104,8 @@ func RegisterFlags(cmd *cobra.Command, register map[string][]Definition) error {
 				fset.DurationVar(&v, def.FlagName, v, def.Description)
 			case types.Duration:
 				fset.DurationVar((*time.Duration)(&v), def.FlagName, time.Duration(v), def.Description)
-			case types.StorageType:
-				fset.Var(flags.StorageTypeFlag(&v), def.FlagName, def.Description)
+			case types.ResourceType:
+				fset.String(def.FlagName, string(v), def.Description)
 			default:
 				return fmt.Errorf("unhandled type: %T for flag %s", v, def.FlagName)
 			}
@@ -111,6 +113,7 @@ func RegisterFlags(cmd *cobra.Command, register map[string][]Definition) error {
 			if def.Deprecated {
 				flag := fset.Lookup(def.FlagName)
 				flag.Deprecated = def.DeprecatedMessage
+				flag.Hidden = true
 			}
 		}
 		cmd.PersistentFlags().AddFlagSet(fset)
diff --git a/cmd/util/flags/configflags/timeouts.go b/cmd/util/flags/configflags/timeouts.go
index e831a6ffa3..fc181c41b2 100644
--- a/cmd/util/flags/configflags/timeouts.go
+++ b/cmd/util/flags/configflags/timeouts.go
@@ -1,36 +1,49 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"fmt"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
+
+// deprecated
 var ComputeTimeoutFlags = []Definition{
 	{
-		FlagName:     "job-execution-timeout-bypass-client-id",
-		ConfigPath:   types.NodeComputeJobTimeoutsJobExecutionTimeoutClientIDBypassList,
-		DefaultValue: Default.Node.Compute.JobTimeouts.JobExecutionTimeoutClientIDBypassList,
-		Description:  `List of IDs of clients that are allowed to bypass the job execution timeout check`,
+		FlagName:          "job-execution-timeout-bypass-client-id",
+		ConfigPath:        "job.execution.timeout.bypass.client.id.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "job-negotiation-timeout",
-		ConfigPath:   types.NodeComputeJobTimeoutsJobNegotiationTimeout,
-		DefaultValue: Default.Node.Compute.JobTimeouts.JobNegotiationTimeout,
-		Description:  `Timeout value to hold a bid for a job.`,
+		FlagName:          "job-negotiation-timeout",
+		ConfigPath:        "job.negotiation.timeout.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "min-job-execution-timeout",
-		ConfigPath:   types.NodeComputeJobTimeoutsMinJobExecutionTimeout,
-		DefaultValue: Default.Node.Compute.JobTimeouts.MinJobExecutionTimeout,
-		Description:  `The minimum execution timeout this compute node supports. Jobs with lower timeout requirements will not be bid on.`,
+		FlagName:          "min-job-execution-timeout",
+		ConfigPath:        "min.job.execution.timeout.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
-		FlagName:     "max-job-execution-timeout",
-		ConfigPath:   types.NodeComputeJobTimeoutsMaxJobExecutionTimeout,
-		DefaultValue: Default.Node.Compute.JobTimeouts.MaxJobExecutionTimeout,
-		Description:  `The maximum execution timeout this compute node supports. Jobs with higher timeout requirements will not be bid on.`,
+		FlagName:          "max-job-execution-timeout",
+		ConfigPath:        "max.job.execution.timeout.deprecated",
+		DefaultValue:      "",
+		Deprecated:        true,
+		DeprecatedMessage: FeatureDeprecatedMessage,
 	},
 	{
 		FlagName:     "default-job-execution-timeout",
-		ConfigPath:   types.NodeComputeJobTimeoutsDefaultJobExecutionTimeout,
-		DefaultValue: Default.Node.Compute.JobTimeouts.DefaultJobExecutionTimeout,
-		Description:  `default value for the execution timeout this compute node will assign to jobs with no timeout requirement defined.`,
+		ConfigPath:   "default.job.execution.timeout.deprecated",
+		DefaultValue: "",
+		Deprecated:   true,
+		DeprecatedMessage: fmt.Sprintf("Use one or more of the following options, all are accepted %s, %s",
+			makeConfigFlagDeprecationCommand(types.JobDefaultsBatchTaskTimeoutsExecutionTimeoutKey),
+			makeConfigFlagDeprecationCommand(types.JobDefaultsOpsTaskTimeoutsExecutionTimeoutKey),
+		),
 	},
 }
diff --git a/cmd/util/flags/configflags/web_ui.go b/cmd/util/flags/configflags/web_ui.go
index fd5bcf9a25..3ef20e4011 100644
--- a/cmd/util/flags/configflags/web_ui.go
+++ b/cmd/util/flags/configflags/web_ui.go
@@ -1,18 +1,24 @@
 package configflags
 
-import "github.com/bacalhau-project/bacalhau/pkg/config/types"
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 var WebUIFlags = []Definition{
 	{
-		FlagName:     "web-ui",
-		ConfigPath:   types.NodeWebUIEnabled,
-		DefaultValue: Default.Node.WebUI.Enabled,
-		Description:  `Whether to start the web UI alongside the bacalhau node.`,
+		FlagName:          "web-ui",
+		ConfigPath:        types.WebUIEnabledKey,
+		DefaultValue:      types.Default.WebUI.Enabled,
+		Description:       `Whether to start the web UI alongside the bacalhau node.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.WebUIEnabledKey),
 	},
 	{
-		FlagName:     "web-ui-port",
-		ConfigPath:   types.NodeWebUIPort,
-		DefaultValue: Default.Node.WebUI.Port,
-		Description:  `The port number to listen on for web-ui connections.`,
+		FlagName:          "web-ui-listen",
+		ConfigPath:        types.WebUIListenKey,
+		DefaultValue:      types.Default.WebUI.Listen,
+		Description:       `The address to listen on for web-ui connections.`,
+		Deprecated:        true,
+		DeprecatedMessage: makeDeprecationMessage(types.WebUIListenKey),
 	},
 }
diff --git a/cmd/util/flags/types.go b/cmd/util/flags/types.go
index ca1a54f213..64dc5bfca6 100644
--- a/cmd/util/flags/types.go
+++ b/cmd/util/flags/types.go
@@ -8,7 +8,6 @@ import (
 	"golang.org/x/exp/slices"
 
 	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	storage_ipfs "github.com/bacalhau-project/bacalhau/pkg/storage/ipfs"
 
@@ -280,15 +279,6 @@ func LoggingFlag(value *logger.LogMode) *ValueFlag[logger.LogMode] {
 	}
 }
 
-func StorageTypeFlag(value *types.StorageType) *ValueFlag[types.StorageType] {
-	return &ValueFlag[types.StorageType]{
-		value:    value,
-		parser:   types.ParseStorageType,
-		stringer: func(p *types.StorageType) string { return p.String() },
-		typeStr:  "storage-type",
-	}
-}
-
 func OutputFormatFlag(value *output.OutputFormat) *ValueFlag[output.OutputFormat] {
 	return &ValueFlag[output.OutputFormat]{
 		value: value,
diff --git a/cmd/util/hook/version.go b/cmd/util/hook/version.go
index 2a5144872d..250a17a9dc 100644
--- a/cmd/util/hook/version.go
+++ b/cmd/util/hook/version.go
@@ -16,7 +16,7 @@ var printMessage *string = nil
 // StartUpdateCheck is a Cobra pre run hook to run an update check in the
 // background. There should be no output if the check fails or the context is
 // cancelled before the check can complete.
-func StartUpdateCheck(cmd *cobra.Command, cfg types.BacalhauConfig, store version.UpdateStore) {
+func StartUpdateCheck(cmd *cobra.Command, cfg types.Bacalhau, store version.UpdateStore) {
 	version.RunUpdateChecker(
 		cmd.Context(),
 		cfg,
diff --git a/cmd/util/repo.go b/cmd/util/repo.go
index f3542f36e1..088022d84b 100644
--- a/cmd/util/repo.go
+++ b/cmd/util/repo.go
@@ -14,70 +14,68 @@ import (
 	"github.com/bacalhau-project/bacalhau/cmd/util/hook"
 	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 	"github.com/bacalhau-project/bacalhau/pkg/setup"
 )
 
-func SetupRepoConfig(cmd *cobra.Command) (types.BacalhauConfig, error) {
+func SetupRepoConfig(cmd *cobra.Command) (types.Bacalhau, error) {
 	cfg, err := SetupConfig(cmd)
 	if err != nil {
-		return types.BacalhauConfig{}, err
+		return types.Bacalhau{}, err
 	}
 	// create or open the bacalhau repo and load the config
 	r, err := SetupRepo(cfg)
 	if err != nil {
-		return types.BacalhauConfig{}, fmt.Errorf("failed to reconcile repo: %w", err)
+		return types.Bacalhau{}, fmt.Errorf("failed to reconcile repo: %w", err)
 	}
 
-	bacalhauCfg, err := cfg.Current()
-	if err != nil {
-		return types.BacalhauConfig{}, fmt.Errorf("failed to load config: %w", err)
-	}
-
-	hook.StartUpdateCheck(cmd, bacalhauCfg, r)
+	// TODO(forrest): we need to start this hook somewhere else as not all CLI methods call this parent method.
+	hook.StartUpdateCheck(cmd, cfg, r)
 
-	return bacalhauCfg, nil
+	return cfg, nil
 }
 
-func SetupRepo(cfg config.ReadWriter) (*repo.FsRepo, error) {
-	// get the global viper instance
-	v := viper.GetViper()
-	// get the repo path set in the root command, and ensure it's set (it will always be set unless dev error)
-	repoPath := v.GetString("repo")
-	if repoPath == "" {
-		return nil, fmt.Errorf("repo path not set")
-	}
+func SetupRepo(cfg types.Bacalhau) (*repo.FsRepo, error) {
 	// create or open the bacalhau repo and load the config
-	r, err := setup.SetupBacalhauRepo(repoPath, cfg)
+	r, err := setup.SetupBacalhauRepo(cfg)
 	if err != nil {
 		return nil, fmt.Errorf("failed to reconcile repo: %w", err)
 	}
 	return r, nil
 }
 
-func SetupConfig(cmd *cobra.Command) (config.ReadWriter, error) {
-	// get the global viper instance
+func SetupConfig(cmd *cobra.Command) (types.Bacalhau, error) {
+	var opts []config.Option
 	v := viper.GetViper()
-
-	// get the repo path set in the root command, and ensure it's set (it will always be set unless dev error)
-	repoPath := v.GetString("repo")
-	if repoPath == "" {
-		return nil, fmt.Errorf("repo path not set")
-	}
-
-	opts := []config.Option{config.WithDefault(config.ForEnvironment())}
-
 	// check if the user specified config files via the --config flag
-	configFiles, err := getConfigFiles(v, repoPath)
-	if err != nil {
-		return nil, err
+	configFiles := getConfigFiles(v)
+
+	// if none were provided look in $XDG_CONFIG_HOME/bacalhau/config.yaml
+	if len(configFiles) == 0 {
+		xdgPath, err := os.UserConfigDir()
+		if err == nil {
+			path := filepath.Join(xdgPath, "bacalhau", config_legacy.FileName)
+			if _, err := os.Stat(path); err != nil {
+				// if the file exists and could not be read, return an error
+				if !os.IsNotExist(err) {
+					return types.Bacalhau{}, fmt.Errorf("loading config file at %q: %w", path, err)
+				}
+			} else {
+				// the file exists, use it.
+				configFiles = append(configFiles, path)
+			}
+		}
 	}
 	// if a config file is present, apply it to the config
 	if len(configFiles) > 0 {
 		opts = append(opts, config.WithPaths(configFiles...))
 	}
 
-	configFlags := getConfigFlags(v, cmd)
+	configFlags, err := getConfigFlags(v, cmd)
+	if err != nil {
+		return types.Bacalhau{}, err
+	}
 	if len(configFlags) > 0 {
 		opts = append(opts, config.WithFlags(configFlags))
 	}
@@ -94,27 +92,31 @@ func SetupConfig(cmd *cobra.Command) (config.ReadWriter, error) {
 
 	cfg, err := config.New(opts...)
 	if err != nil {
-		return nil, err
+		return types.Bacalhau{}, err
 	}
 
-	return cfg, nil
+	var out types.Bacalhau
+	if err := cfg.Unmarshal(&out); err != nil {
+		return types.Bacalhau{}, err
+	}
+	return out, nil
 }
 
 func getConfigValues(v *viper.Viper) map[string]any {
 	return v.GetStringMap(cliflags.RootCommandConfigValues)
 }
 
-func getConfigFlags(v *viper.Viper, cmd *cobra.Command) map[string]*pflag.Flag {
+func getConfigFlags(v *viper.Viper, cmd *cobra.Command) (map[string][]*pflag.Flag, error) {
 	flagDefs := v.Get(cliflags.RootCommandConfigFlags)
 	if flagDefs == nil {
-		return nil
+		return nil, nil
 	}
 	flagsConfigs := flagDefs.([]configflags.Definition)
-	out := make(map[string]*pflag.Flag)
+	out := make(map[string][]*pflag.Flag)
 	for _, flag := range flagsConfigs {
-		out[flag.ConfigPath] = cmd.Flags().Lookup(flag.FlagName)
+		out[flag.ConfigPath] = append(out[flag.ConfigPath], cmd.Flags().Lookup(flag.FlagName))
 	}
-	return out
+	return out, nil
 }
 
 func getConfigEnvVars(v *viper.Viper) map[string][]string {
@@ -130,45 +132,7 @@ func getConfigEnvVars(v *viper.Viper) map[string][]string {
 	return out
 }
 
-func getConfigFiles(v *viper.Viper, repoPath string) ([]string, error) {
+func getConfigFiles(v *viper.Viper) []string {
 	// check if the user specified config files via the --config/-c flag
-	configFiles := v.GetStringSlice(cliflags.RootCommandConfigFiles)
-	if len(configFiles) > 0 {
-		return configFiles, nil
-	}
-
-	// check if a config file is present at $XDG_CONFIG_HOME/bacalhau/config.yaml
-	{
-		xdgPath, err := os.UserConfigDir()
-		if err == nil {
-			path := filepath.Join(xdgPath, config.FileName)
-			if _, err := os.Stat(path); err != nil {
-				// if the file exists and could not be read, return an error
-				if !os.IsNotExist(err) {
-					return nil, fmt.Errorf("loading xdg config file at %q: %w", path, err)
-				}
-			} else {
-				// the file exists, use it.
-				return []string{path}, nil
-			}
-		}
-	}
-
-	// if no config files were provided by the users, and we failed to find a config in
-	// $XDG_CONFIG_HOME/bacalhau/config.yaml fall back to the repo
-	{
-		path := filepath.Join(repoPath, config.FileName)
-		if _, err := os.Stat(path); err != nil {
-			// if the file exists and could not be read, return an error
-			if !os.IsNotExist(err) {
-				return nil, fmt.Errorf("loading xdg config file at %q: %w", path, err)
-			}
-		} else {
-			// the file exists, use it.
-			return []string{path}, nil
-		}
-	}
-
-	// no config file exists, this is fine bacalhau will use defaults and values from flags and env vars.
-	return []string{}, nil
+	return v.GetStringSlice(cliflags.RootCommandConfigFiles)
 }
diff --git a/cmd/util/version.go b/cmd/util/version.go
index e518049743..8a54eaa6fd 100644
--- a/cmd/util/version.go
+++ b/cmd/util/version.go
@@ -12,6 +12,7 @@ import (
 	baccrypto "github.com/bacalhau-project/bacalhau/pkg/lib/crypto"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
+	"github.com/bacalhau-project/bacalhau/pkg/repo"
 	"github.com/bacalhau-project/bacalhau/pkg/version"
 )
 
@@ -22,7 +23,7 @@ type Versions struct {
 	UpdateMessage string                   `json:"updateMessage,omitempty"`
 }
 
-func GetAllVersions(ctx context.Context, cfg types.BacalhauConfig, api clientv2.API) (Versions, error) {
+func GetAllVersions(ctx context.Context, cfg types.Bacalhau, api clientv2.API, r *repo.FsRepo) (Versions, error) {
 	var err error
 	versions := Versions{ClientVersion: version.Get()}
 
@@ -49,7 +50,12 @@ func GetAllVersions(ctx context.Context, cfg types.BacalhauConfig, api clientv2.
 		return versions, fmt.Errorf("loading user key: %w", err)
 	}
 
-	if cfg.User.InstallationID == "" {
+	installationID, err := r.ReadInstallationID()
+	if err != nil {
+		return versions, fmt.Errorf("reading installationID: %w", err)
+	}
+
+	if installationID == "" {
 		return versions, errors.Wrap(err, "Installation ID not set")
 	}
 
@@ -58,7 +64,7 @@ func GetAllVersions(ctx context.Context, cfg types.BacalhauConfig, api clientv2.
 		versions.ClientVersion,
 		versions.ServerVersion,
 		userKey.ClientID(),
-		cfg.User.InstallationID,
+		installationID,
 	)
 	if err != nil {
 		return versions, errors.Wrap(err, "failed to get latest version")
diff --git a/main.go b/main.go
index ced8a984ab..ce4a9a0268 100644
--- a/main.go
+++ b/main.go
@@ -6,12 +6,13 @@ import (
 	"os"
 	"os/signal"
 
+	"github.com/joho/godotenv"
+	"github.com/rs/zerolog/log"
+
 	"github.com/bacalhau-project/bacalhau/cmd/cli"
 	"github.com/bacalhau-project/bacalhau/cmd/util"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	_ "github.com/bacalhau-project/bacalhau/pkg/version"
-	"github.com/joho/godotenv"
-	"github.com/rs/zerolog/log"
 
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
 )
@@ -77,7 +78,7 @@ func main() {
 
 	_ = godotenv.Load()
 
-	devstackEnvFile := config.DevstackEnvFile()
+	devstackEnvFile := config_legacy.DevstackEnvFile()
 	if _, err := os.Stat(devstackEnvFile); err == nil {
 		log.Debug().Msgf("Loading environment from %s", devstackEnvFile)
 		_ = godotenv.Overload(devstackEnvFile)
diff --git a/ops/terraform/remote_files/scripts/start-bacalhau.sh b/ops/terraform/remote_files/scripts/start-bacalhau.sh
index 549201f8d9..318faefd82 100644
--- a/ops/terraform/remote_files/scripts/start-bacalhau.sh
+++ b/ops/terraform/remote_files/scripts/start-bacalhau.sh
@@ -26,6 +26,7 @@ TRUSTED_CLIENT_IDS="\
 b43517b5449d383ab00ca1d2b1c558d710ba79f51c800fbf4c35ed4d0198aec5"
 
   # nats related config as set as env vars in main.tf and no need to pass them to serve command
+  # TODO these flags will need to be adjusted to match the new config
 bacalhau serve \
   --node-type "${BACALHAU_NODE_TYPE}" \
   --job-selection-data-locality anywhere \
@@ -39,5 +40,8 @@ bacalhau serve \
   --web-ui-port 80 \
   --labels owner=bacalhau \
   --requester-job-translation-enabled \
-  --default-publisher local \
+  --config Job.Defaults.Batch.Task.Publisher.Type=local \
+  --config Job.Defaults.Ops.Task.Publisher.Type=local \
+  --config Job.Defaults.Service.Task.Publisher.Type=local \
+  --config Job.Defaults.Daemon.Task.Publisher.Type=local \
   --local-publisher-address "${BACALHAU_LOCAL_PUBLISHER_ADDRESS}"
diff --git a/pkg/compute/management_client.go b/pkg/compute/management_client.go
index 7eac09e509..5d7ff378d8 100644
--- a/pkg/compute/management_client.go
+++ b/pkg/compute/management_client.go
@@ -9,7 +9,7 @@ import (
 	"github.com/rs/zerolog/log"
 
 	"github.com/bacalhau-project/bacalhau/pkg/compute/capacity"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/models/requests"
 	"github.com/bacalhau-project/bacalhau/pkg/node/heartbeat"
@@ -24,7 +24,7 @@ type ManagementClientParams struct {
 	QueueUsageTracker        capacity.UsageTracker
 	RegistrationFilePath     string
 	HeartbeatClient          heartbeat.Client
-	ControlPlaneSettings     types.ComputeControlPlaneConfig
+	ControlPlaneSettings     legacy_types.ComputeControlPlaneConfig
 }
 
 // ManagementClient is used to call management functions with
@@ -41,7 +41,7 @@ type ManagementClient struct {
 	queueUsageTracker        capacity.UsageTracker
 	registrationFile         *RegistrationFile
 	heartbeatClient          heartbeat.Client
-	settings                 types.ComputeControlPlaneConfig
+	settings                 legacy_types.ComputeControlPlaneConfig
 }
 
 func NewManagementClient(params *ManagementClientParams) *ManagementClient {
diff --git a/pkg/compute/node_info_decorator.go b/pkg/compute/node_info_decorator.go
index cd6c066d18..8b4c2ce1a4 100644
--- a/pkg/compute/node_info_decorator.go
+++ b/pkg/compute/node_info_decorator.go
@@ -43,6 +43,8 @@ func NewNodeInfoDecorator(params NodeInfoDecoratorParams) *NodeInfoDecorator {
 }
 
 func (n *NodeInfoDecorator) DecorateNodeInfo(ctx context.Context, nodeInfo models.NodeInfo) models.NodeInfo {
+	// TODO(forrest): this method takes 10 seconds to run: https://github.com/bacalhau-project/bacalhau/issues/4153
+	// because the Keys() methods are slow when s3 is considered since we need to check for credentials.
 	nodeInfo.NodeType = models.NodeTypeCompute
 	nodeInfo.ComputeNodeInfo = &models.ComputeNodeInfo{
 		ExecutionEngines:   n.executors.Keys(ctx),
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 9b5eae800e..0778d098b2 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -3,8 +3,6 @@ package config
 import (
 	"fmt"
 	"os"
-	"path/filepath"
-	"reflect"
 	"strings"
 
 	"github.com/mitchellh/mapstructure"
@@ -12,70 +10,31 @@ import (
 	"github.com/spf13/pflag"
 	"github.com/spf13/viper"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
-type ReadWriter interface {
-	Reader
-	Writer
-}
-
-var _ Reader = (*config)(nil)
-
-type Reader interface {
-	Current() (types.BacalhauConfig, error)
-}
-
-var _ Writer = (*config)(nil)
-
-type Writer interface {
-	Set(key string, value interface{})
-	SetIfAbsent(key string, value interface{})
-}
-
 const (
-	FileName = "config.yaml"
-
 	environmentVariablePrefix = "BACALHAU"
 	inferConfigTypes          = true
-
-	// user key files
-	UserPrivateKeyFileName = "user_id.pem"
-
-	// compute paths
-	ComputeStoragesPath = "executor_storages"
-	ComputeStorePath    = "compute_store"
-	PluginsPath         = "plugins"
-
-	// orchestrator paths
-	OrchestratorStorePath = "orchestrator_store"
-	AutoCertCachePath     = "autocert-cache"
-	NetworkTransportStore = "nats-store"
-
-	// auth paths
-	TokensPath = "tokens.json"
+	DefaultFileName           = "config.yaml"
 )
 
 var (
-	ComputeExecutionsStorePath = filepath.Join(ComputeStorePath, "executions.db")
-	OrchestratorJobStorePath   = filepath.Join(OrchestratorStorePath, "jobs.db")
-
 	environmentVariableReplace = strings.NewReplacer(".", "_")
 	DecoderHook                = viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())
 )
 
-type config struct {
+type Config struct {
 	// viper instance for holding user provided configuration.
 	base *viper.Viper
 	// the default configuration values to initialize with.
-	defaultCfg types.BacalhauConfig
+	defaultCfg interface{}
 
 	// paths to configuration files merged from [0] to [N]
 	// e.g. file at index 1 overrides index 0, index 2 overrides index 1 and 0, etc.
 	paths []string
 
-	flags map[string]*pflag.Flag
+	flags map[string][]*pflag.Flag
 
 	environmentVariables map[string][]string
 
@@ -83,11 +42,11 @@ type config struct {
 	values map[string]any
 }
 
-type Option = func(s *config)
+type Option = func(s *Config)
 
 // WithDefault sets the default config to be used when no values are provided.
-func WithDefault(cfg types.BacalhauConfig) Option {
-	return func(c *config) {
+func WithDefault(cfg interface{}) Option {
+	return func(c *Config) {
 		c.defaultCfg = cfg
 	}
 }
@@ -96,49 +55,59 @@ func WithDefault(cfg types.BacalhauConfig) Option {
 // paths to configuration files merged from [0] to [N]
 // e.g. file at index 1 overrides index 0, index 2 overrides index 1 and 0, etc.
 func WithPaths(path ...string) Option {
-	return func(c *config) {
+	return func(c *Config) {
 		c.paths = append(c.paths, path...)
 	}
 }
 
-func WithFlags(flags map[string]*pflag.Flag) Option {
-	return func(s *config) {
+func WithFlags(flags map[string][]*pflag.Flag) Option {
+	return func(s *Config) {
 		s.flags = flags
 	}
 }
 
 func WithEnvironmentVariables(ev map[string][]string) Option {
-	return func(s *config) {
+	return func(s *Config) {
 		s.environmentVariables = ev
 	}
 }
 
 // WithValues sets values to be injected into the config, taking precedence over all other options.
 func WithValues(values map[string]any) Option {
-	return func(c *config) {
+	return func(c *Config) {
 		c.values = values
 	}
 }
 
 // New returns a configuration with the provided options applied. If no options are provided, the returned config
 // contains only the default values.
-func New(opts ...Option) (*config, error) {
+func New(opts ...Option) (*Config, error) {
 	base := viper.New()
 	base.SetEnvPrefix(environmentVariablePrefix)
 	base.SetTypeByDefaultValue(inferConfigTypes)
 	base.AutomaticEnv()
 	base.SetEnvKeyReplacer(environmentVariableReplace)
 
-	c := &config{
-		base:       base,
-		defaultCfg: configenv.Production,
-		paths:      make([]string, 0),
+	c := &Config{
+		base:                 base,
+		defaultCfg:           types.Default,
+		paths:                make([]string, 0),
+		values:               make(map[string]any),
+		environmentVariables: make(map[string][]string),
 	}
 	for _, opt := range opts {
 		opt(c)
 	}
 
-	c.setDefault(c.defaultCfg)
+	var defaultMap map[string]interface{}
+	err := mapstructure.Decode(c.defaultCfg, &defaultMap)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := c.base.MergeConfigMap(defaultMap); err != nil {
+		return nil, err
+	}
 
 	// merge the config files in the order they were passed.
 	for _, path := range c.paths {
@@ -156,9 +125,58 @@ func New(opts ...Option) (*config, error) {
 		}
 	}
 
-	for name, flag := range c.flags {
-		if err := c.base.BindPFlag(name, flag); err != nil {
-			return nil, fmt.Errorf("binding flag %q to config: %w", name, err)
+	for name, flags := range c.flags {
+		for _, flag := range flags {
+			// only if the flag has been set do we want to bind to it, this allows multiple flags
+			// to bind to the same config key.
+			if flag.Changed {
+				switch name {
+				case "ipfs.connect.deprecated":
+					// allow the deprecated --ipfs-connect flag to bind to related fields in the config.
+					for _, key := range []string{
+						// config keys we wish to bind --ipfs-connect flag to.
+						types.ResultDownloadersTypesIPFSEndpointKey,
+						types.InputSourcesTypesIPFSEndpointKey,
+						types.PublishersTypesIPFSEndpointKey,
+					} {
+						if err := c.base.BindPFlag(key, flag); err != nil {
+							return nil, fmt.Errorf("binding flag %q to config: %w", name, err)
+						}
+					}
+				case "node.type.deprecated":
+					// continuing to support the deprecated --node-type flag
+					// iff config values were not provided set them accordingly
+					orchestrator, compute, err := getNodeType(flag.Value.String())
+					if err != nil {
+						return nil, err
+					}
+					if orchestrator {
+						if _, ok := c.values[types.OrchestratorEnabledKey]; !ok {
+							c.values[types.OrchestratorEnabledKey] = true
+						}
+					}
+					if compute {
+						if _, ok := c.values[types.ComputeEnabledKey]; !ok {
+							c.values[types.ComputeEnabledKey] = true
+						}
+					}
+				case "default.publisher.deprecated":
+					// allow the deprecated --default-publisher flag to bind to related fields in the config.
+					for _, key := range []string{
+						// config keys we wish to bind --default-publisher flag to.
+						types.JobDefaultsBatchTaskPublisherConfigTypeKey,
+						types.JobDefaultsOpsTaskPublisherConfigTypeKey,
+					} {
+						if err := c.base.BindPFlag(key, flag); err != nil {
+							return nil, fmt.Errorf("binding flag %q to config: %w", name, err)
+						}
+					}
+				default:
+					if err := c.base.BindPFlag(name, flag); err != nil {
+						return nil, fmt.Errorf("binding flag %q to config: %w", name, err)
+					}
+				}
+			}
 		}
 	}
 
@@ -170,10 +188,34 @@ func New(opts ...Option) (*config, error) {
 	return c, nil
 }
 
+func getNodeType(input string) (requester, compute bool, err error) {
+	requester = false
+	compute = false
+	err = nil
+
+	// Split the string by commas, lowercase it, and clean up any extra spaces
+	tokens := strings.Split(input, ",")
+	for i, token := range tokens {
+		tokens[i] = strings.ToLower(strings.TrimSpace(token))
+	}
+
+	for _, nodeType := range tokens {
+		if nodeType == "compute" {
+			compute = true
+		} else if nodeType == "requester" {
+			requester = true
+		} else {
+			err = fmt.Errorf("invalid node type %s. Only compute and requester values are supported", nodeType)
+		}
+	}
+	return
+}
+
 // Load reads in the configuration file specified by `path` overriding any previously set configuration with the values
 // from the read config file.
 // Load returns an error if the file cannot be read.
-func (c *config) Load(path string) error {
+func (c *Config) Load(path string) error {
+	log.Debug().Msgf("loading config file: %q", path)
 	c.base.SetConfigFile(path)
 	if err := c.base.ReadInConfig(); err != nil {
 		return err
@@ -181,7 +223,10 @@ func (c *config) Load(path string) error {
 	return nil
 }
 
-func (c *config) Merge(path string) error {
+// Merge merges a new configuration file specified by `path` with the existing config.
+// Merge returns an error if the file cannot be read
+func (c *Config) Merge(path string) error {
+	log.Debug().Msgf("merging config file: %q", path)
 	c.base.SetConfigFile(path)
 	if err := c.base.MergeInConfig(); err != nil {
 		return err
@@ -189,85 +234,18 @@ func (c *config) Merge(path string) error {
 	return nil
 }
 
-// Write persists the current configuration to `path`.
-// Write returns an error if:
-//   - the path cannot be accessed
-//   - the current configuration cannot be marshaled.
-func (c *config) Write(path string) error {
-	return c.base.WriteConfigAs(path)
-}
-
-// Current returns the current configuration.
-// Current returns an error if the configuration cannot be unmarshalled.
-func (c *config) Current() (types.BacalhauConfig, error) {
-	out := new(types.BacalhauConfig)
+// Unmarshal returns the current configuration.
+// Unmarshal returns an error if the configuration cannot be unmarshalled.
+func (c *Config) Unmarshal(out interface{}) error {
 	if err := c.base.Unmarshal(&out, DecoderHook); err != nil {
-		return types.BacalhauConfig{}, err
-	}
-	return *out, nil
-}
-
-// Set sets the configuration value.
-// This value won't be persisted in the config file.
-// Will be used instead of values obtained via flags, config file, ENV, default.
-func (c *config) Set(key string, value interface{}) {
-	c.base.Set(key, value)
-}
-
-func (c *config) SetIfAbsent(key string, value interface{}) {
-	if !c.base.IsSet(key) || reflect.ValueOf(c.base.Get(key)).IsZero() {
-		c.Set(key, value)
-	}
-}
-
-// setDefault sets the default value for the configuration.
-// Default only used when no value is provided by the user via an explicit call to Set, flag, config file or ENV.
-func (c *config) setDefault(config types.BacalhauConfig) {
-	types.SetDefaults(config, types.WithViper(c.base))
-}
-
-// WritePersistedConfigs will write certain values from the resolved config to the persisted config.
-// These include fields for configurations that must not change between version updates, such as the
-// execution store and job store paths, in case we change their default values in future updates.
-func WritePersistedConfigs(configFilePath string, cfg types.BacalhauConfig) error {
-	// a viper config instance that is only based on the config file.
-	viperWriter := viper.New()
-	viperWriter.SetTypeByDefaultValue(true)
-	viperWriter.SetConfigFile(configFilePath)
-
-	// read existing config if it exists.
-	if err := viperWriter.ReadInConfig(); err != nil {
-		if !os.IsNotExist(err) {
-			return err
-		}
-	}
-
-	var fileCfg types.BacalhauConfig
-	if err := viperWriter.Unmarshal(&fileCfg, DecoderHook); err != nil {
 		return err
 	}
-
-	// check if any of the values that we want to write are not set in the config file.
-	var doWrite bool
-	var logMessage strings.Builder
-	set := func(key string, value interface{}) {
-		viperWriter.Set(key, value)
-		logMessage.WriteString(fmt.Sprintf("\n%s:\t%v", key, value))
-		doWrite = true
-	}
-	emptyStoreConfig := types.JobStoreConfig{}
-	if fileCfg.Node.Compute.ExecutionStore == emptyStoreConfig {
-		set(types.NodeComputeExecutionStore, cfg.Node.Compute.ExecutionStore)
-	}
-	if fileCfg.Node.Requester.JobStore == emptyStoreConfig {
-		set(types.NodeRequesterJobStore, cfg.Node.Requester.JobStore)
-	}
-	if fileCfg.Node.Name == "" && cfg.Node.Name != "" {
-		set(types.NodeName, cfg.Node.Name)
-	}
-	if doWrite {
-		log.Info().Msgf("Writing to config file %s:%s", configFilePath, logMessage.String())
-		return viperWriter.WriteConfig()
-	}
 	return nil
 }
+
+// KeyAsEnvVar returns the environment variable corresponding to a config key
+func KeyAsEnvVar(key string) string {
+	return strings.ToUpper(
+		fmt.Sprintf("%s_%s", environmentVariablePrefix, environmentVariableReplace.Replace(key)),
+	)
+}
diff --git a/pkg/config/configenv/dev.go b/pkg/config/configenv/dev.go
deleted file mode 100644
index c58887113e..0000000000
--- a/pkg/config/configenv/dev.go
+++ /dev/null
@@ -1,180 +0,0 @@
-//nolint:gomnd
-package configenv
-
-import (
-	"os"
-	"runtime"
-	"time"
-
-	"github.com/bacalhau-project/bacalhau/pkg/authn"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-var Development = types.BacalhauConfig{
-	Metrics: types.MetricsConfig{
-		EventTracerPath: os.DevNull,
-	},
-	Update: types.UpdateConfig{
-		SkipChecks: true,
-	},
-	Auth: types.AuthConfig{
-		Methods: map[string]types.AuthenticatorConfig{
-			"ClientKey": {
-				Type: authn.MethodTypeChallenge,
-			},
-		},
-	},
-	Node: types.NodeConfig{
-		NameProvider: "puuid",
-		ClientAPI: types.APIConfig{
-			Host: "bootstrap.development.bacalhau.org",
-			Port: 1234,
-		},
-		ServerAPI: types.APIConfig{
-			Host: "0.0.0.0",
-			Port: 1234,
-			TLS:  types.TLSConfiguration{},
-		},
-		Network: types.NetworkConfig{
-			Port: 4222,
-		},
-		DownloadURLRequestTimeout: types.Duration(300 * time.Second),
-		VolumeSizeRequestTimeout:  types.Duration(2 * time.Minute),
-		DownloadURLRequestRetries: 3,
-		LoggingMode:               logger.LogModeDefault,
-		Type:                      []string{"requester"},
-		AllowListedLocalPaths:     []string{},
-		Labels:                    map[string]string{},
-		DisabledFeatures: types.FeatureConfig{
-			Engines:    []string{},
-			Publishers: []string{},
-			Storages:   []string{},
-		},
-		IPFS: types.IpfsConfig{
-			Connect: "",
-		},
-		Compute:   DevelopmentComputeConfig,
-		Requester: DevelopmentRequesterConfig,
-		WebUI: types.WebUIConfig{
-			Enabled: false,
-			Port:    8483,
-		},
-		StrictVersionMatch: false,
-	},
-}
-
-var DevelopmentComputeConfig = types.ComputeConfig{
-	Capacity: types.CapacityConfig{
-		IgnorePhysicalResourceLimits: false,
-		TotalResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		JobResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		DefaultJobResourceLimits: models.ResourcesConfig{
-			CPU:    "500m",
-			Memory: "1Gb",
-			Disk:   "",
-			GPU:    "",
-		},
-	},
-	ExecutionStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	JobTimeouts: types.JobTimeoutConfig{
-		JobExecutionTimeoutClientIDBypassList: []string{},
-		JobNegotiationTimeout:                 types.Duration(3 * time.Minute),
-		MinJobExecutionTimeout:                types.Duration(500 * time.Millisecond),
-		MaxJobExecutionTimeout:                types.Duration(models.NoTimeout),
-		DefaultJobExecutionTimeout:            types.Duration(10 * time.Minute),
-	},
-	JobSelection: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	Logging: types.LoggingConfig{
-		LogRunningExecutionsInterval: types.Duration(10 * time.Second),
-	},
-	ManifestCache: types.DockerCacheConfig{
-		Size:      1000,
-		Duration:  types.Duration(1 * time.Hour),
-		Frequency: types.Duration(1 * time.Hour),
-	},
-	LogStreamConfig: types.LogStreamConfig{
-		ChannelBufferSize: 10,
-	},
-	LocalPublisher: types.LocalPublisherConfig{
-		Address: "127.0.0.1",
-		Port:    6001,
-	},
-	ControlPlaneSettings: types.ComputeControlPlaneConfig{
-		InfoUpdateFrequency:     types.Duration(60 * time.Second),
-		ResourceUpdateFrequency: types.Duration(30 * time.Second),
-		HeartbeatFrequency:      types.Duration(15 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-	},
-}
-
-var DevelopmentRequesterConfig = types.RequesterConfig{
-	ExternalVerifierHook: "",
-	JobSelectionPolicy: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	JobStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	HousekeepingBackgroundTaskInterval: types.Duration(30 * time.Second),
-	NodeRankRandomnessRange:            5,
-	OverAskForBidsFactor:               3,
-	FailureInjectionConfig: models.FailureInjectionRequesterConfig{
-		IsBadActor: false,
-	},
-	EvaluationBroker: types.EvaluationBrokerConfig{
-		EvalBrokerVisibilityTimeout:    types.Duration(60 * time.Second),
-		EvalBrokerInitialRetryDelay:    types.Duration(1 * time.Second),
-		EvalBrokerSubsequentRetryDelay: types.Duration(30 * time.Second),
-		EvalBrokerMaxRetryCount:        10,
-	},
-	Worker: types.WorkerConfig{
-		WorkerCount:                  runtime.NumCPU(),
-		WorkerEvalDequeueTimeout:     types.Duration(5 * time.Second),
-		WorkerEvalDequeueBaseBackoff: types.Duration(1 * time.Second),
-		WorkerEvalDequeueMaxBackoff:  types.Duration(30 * time.Second),
-	},
-	Scheduler: types.SchedulerConfig{
-		QueueBackoff:               types.Duration(30 * time.Second),
-		NodeOverSubscriptionFactor: 1.5,
-	},
-	JobDefaults: types.JobDefaults{
-		TotalTimeout: types.Duration(30 * time.Minute),
-	},
-	StorageProvider: types.StorageProviderConfig{
-		S3: types.S3StorageProviderConfig{
-			PreSignedURLExpiration: types.Duration(30 * time.Minute),
-		},
-	},
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second),
-	},
-	NodeInfoStoreTTL: types.Duration(10 * time.Minute),
-}
diff --git a/pkg/config/configenv/local.go b/pkg/config/configenv/local.go
deleted file mode 100644
index a6f2faf96d..0000000000
--- a/pkg/config/configenv/local.go
+++ /dev/null
@@ -1,180 +0,0 @@
-//nolint:gomnd
-package configenv
-
-import (
-	"os"
-	"runtime"
-	"time"
-
-	"github.com/bacalhau-project/bacalhau/pkg/authn"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-var Local = types.BacalhauConfig{
-	Metrics: types.MetricsConfig{
-		EventTracerPath: os.DevNull,
-	},
-	Update: types.UpdateConfig{
-		SkipChecks: true,
-	},
-	Auth: types.AuthConfig{
-		Methods: map[string]types.AuthenticatorConfig{
-			"ClientKey": {
-				Type: authn.MethodTypeChallenge,
-			},
-		},
-	},
-	Node: types.NodeConfig{
-		NameProvider: "puuid",
-		ClientAPI: types.APIConfig{
-			Host: "0.0.0.0",
-			Port: 1234,
-		},
-		ServerAPI: types.APIConfig{
-			Host: "0.0.0.0",
-			Port: 1234,
-			TLS:  types.TLSConfiguration{},
-		},
-		Network: types.NetworkConfig{
-			Port: 4222,
-		},
-		DownloadURLRequestTimeout: types.Duration(300 * time.Second),
-		VolumeSizeRequestTimeout:  types.Duration(2 * time.Minute),
-		DownloadURLRequestRetries: 3,
-		LoggingMode:               logger.LogModeDefault,
-		Type:                      []string{"requester"},
-		AllowListedLocalPaths:     []string{},
-		Labels:                    map[string]string{},
-		DisabledFeatures: types.FeatureConfig{
-			Engines:    []string{},
-			Publishers: []string{},
-			Storages:   []string{},
-		},
-		IPFS: types.IpfsConfig{
-			Connect: "",
-		},
-		Compute:   LocalComputeConfig,
-		Requester: LocalRequesterConfig,
-		WebUI: types.WebUIConfig{
-			Enabled: false,
-			Port:    8483,
-		},
-		StrictVersionMatch: false,
-	},
-}
-
-var LocalComputeConfig = types.ComputeConfig{
-	Capacity: types.CapacityConfig{
-		IgnorePhysicalResourceLimits: false,
-		TotalResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		JobResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		DefaultJobResourceLimits: models.ResourcesConfig{
-			CPU:    "500m",
-			Memory: "1Gb",
-			Disk:   "",
-			GPU:    "",
-		},
-	},
-	ExecutionStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	JobTimeouts: types.JobTimeoutConfig{
-		JobExecutionTimeoutClientIDBypassList: []string{},
-		JobNegotiationTimeout:                 types.Duration(3 * time.Minute),
-		MinJobExecutionTimeout:                types.Duration(500 * time.Millisecond),
-		MaxJobExecutionTimeout:                types.Duration(models.NoTimeout),
-		DefaultJobExecutionTimeout:            types.Duration(10 * time.Minute),
-	},
-	JobSelection: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	Logging: types.LoggingConfig{
-		LogRunningExecutionsInterval: types.Duration(10 * time.Second),
-	},
-	ManifestCache: types.DockerCacheConfig{
-		Size:      1000,
-		Duration:  types.Duration(1 * time.Hour),
-		Frequency: types.Duration(1 * time.Hour),
-	},
-	LogStreamConfig: types.LogStreamConfig{
-		ChannelBufferSize: 10,
-	},
-	LocalPublisher: types.LocalPublisherConfig{
-		Address: "127.0.0.1",
-		Port:    6001,
-	},
-	ControlPlaneSettings: types.ComputeControlPlaneConfig{
-		InfoUpdateFrequency:     types.Duration(60 * time.Second),
-		ResourceUpdateFrequency: types.Duration(30 * time.Second),
-		HeartbeatFrequency:      types.Duration(15 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-	},
-}
-
-var LocalRequesterConfig = types.RequesterConfig{
-	ExternalVerifierHook: "",
-	JobSelectionPolicy: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	JobStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	HousekeepingBackgroundTaskInterval: types.Duration(30 * time.Second),
-	NodeRankRandomnessRange:            5,
-	OverAskForBidsFactor:               3,
-	FailureInjectionConfig: models.FailureInjectionRequesterConfig{
-		IsBadActor: false,
-	},
-	EvaluationBroker: types.EvaluationBrokerConfig{
-		EvalBrokerVisibilityTimeout:    types.Duration(60 * time.Second),
-		EvalBrokerInitialRetryDelay:    types.Duration(1 * time.Second),
-		EvalBrokerSubsequentRetryDelay: types.Duration(30 * time.Second),
-		EvalBrokerMaxRetryCount:        10,
-	},
-	Worker: types.WorkerConfig{
-		WorkerCount:                  runtime.NumCPU(),
-		WorkerEvalDequeueTimeout:     types.Duration(5 * time.Second),
-		WorkerEvalDequeueBaseBackoff: types.Duration(1 * time.Second),
-		WorkerEvalDequeueMaxBackoff:  types.Duration(30 * time.Second),
-	},
-	Scheduler: types.SchedulerConfig{
-		QueueBackoff:               types.Duration(30 * time.Second),
-		NodeOverSubscriptionFactor: 1.5,
-	},
-	JobDefaults: types.JobDefaults{
-		TotalTimeout: types.Duration(30 * time.Minute),
-	},
-	StorageProvider: types.StorageProviderConfig{
-		S3: types.S3StorageProviderConfig{
-			PreSignedURLExpiration: types.Duration(30 * time.Minute),
-		},
-	},
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second),
-	},
-	NodeInfoStoreTTL: types.Duration(10 * time.Minute),
-}
diff --git a/pkg/config/configenv/staging.go b/pkg/config/configenv/staging.go
deleted file mode 100644
index 37bb932483..0000000000
--- a/pkg/config/configenv/staging.go
+++ /dev/null
@@ -1,181 +0,0 @@
-//nolint:gomnd
-package configenv
-
-import (
-	"os"
-	"runtime"
-	"time"
-
-	"github.com/bacalhau-project/bacalhau/pkg/authn"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-var Staging = types.BacalhauConfig{
-	Metrics: types.MetricsConfig{
-		EventTracerPath: os.DevNull,
-	},
-	Update: types.UpdateConfig{
-		SkipChecks:     false,
-		CheckFrequency: types.Duration(24 * time.Hour),
-	},
-	Auth: types.AuthConfig{
-		Methods: map[string]types.AuthenticatorConfig{
-			"ClientKey": {
-				Type: authn.MethodTypeChallenge,
-			},
-		},
-	},
-	Node: types.NodeConfig{
-		NameProvider: "puuid",
-		ClientAPI: types.APIConfig{
-			Host: "bootstrap.staging.bacalhau.org",
-			Port: 1234,
-		},
-		ServerAPI: types.APIConfig{
-			Host: "0.0.0.0",
-			Port: 1234,
-			TLS:  types.TLSConfiguration{},
-		},
-		Network: types.NetworkConfig{
-			Port: 4222,
-		},
-		DownloadURLRequestTimeout: types.Duration(300 * time.Second),
-		VolumeSizeRequestTimeout:  types.Duration(2 * time.Minute),
-		DownloadURLRequestRetries: 3,
-		LoggingMode:               logger.LogModeDefault,
-		Type:                      []string{"requester"},
-		AllowListedLocalPaths:     []string{},
-		Labels:                    map[string]string{},
-		DisabledFeatures: types.FeatureConfig{
-			Engines:    []string{},
-			Publishers: []string{},
-			Storages:   []string{},
-		},
-		IPFS: types.IpfsConfig{
-			Connect: "",
-		},
-		Compute:   StagingComputeConfig,
-		Requester: StagingRequesterConfig,
-		WebUI: types.WebUIConfig{
-			Enabled: false,
-			Port:    8483,
-		},
-		StrictVersionMatch: false,
-	},
-}
-
-var StagingComputeConfig = types.ComputeConfig{
-	Capacity: types.CapacityConfig{
-		IgnorePhysicalResourceLimits: false,
-		TotalResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		JobResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		DefaultJobResourceLimits: models.ResourcesConfig{
-			CPU:    "500m",
-			Memory: "1Gb",
-			Disk:   "",
-			GPU:    "",
-		},
-	},
-	ExecutionStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	JobTimeouts: types.JobTimeoutConfig{
-		JobExecutionTimeoutClientIDBypassList: []string{},
-		JobNegotiationTimeout:                 types.Duration(3 * time.Minute),
-		MinJobExecutionTimeout:                types.Duration(500 * time.Millisecond),
-		MaxJobExecutionTimeout:                types.Duration(models.NoTimeout),
-		DefaultJobExecutionTimeout:            types.Duration(10 * time.Minute),
-	},
-	JobSelection: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	Logging: types.LoggingConfig{
-		LogRunningExecutionsInterval: types.Duration(10 * time.Second),
-	},
-	ManifestCache: types.DockerCacheConfig{
-		Size:      1000,
-		Duration:  types.Duration(1 * time.Hour),
-		Frequency: types.Duration(1 * time.Hour),
-	},
-	LogStreamConfig: types.LogStreamConfig{
-		ChannelBufferSize: 10,
-	},
-	LocalPublisher: types.LocalPublisherConfig{
-		Address: "public",
-		Port:    6001,
-	},
-	ControlPlaneSettings: types.ComputeControlPlaneConfig{
-		InfoUpdateFrequency:     types.Duration(60 * time.Second),
-		ResourceUpdateFrequency: types.Duration(30 * time.Second),
-		HeartbeatFrequency:      types.Duration(15 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-	},
-}
-
-var StagingRequesterConfig = types.RequesterConfig{
-	ExternalVerifierHook: "",
-	JobSelectionPolicy: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	JobStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	HousekeepingBackgroundTaskInterval: types.Duration(30 * time.Second),
-	NodeRankRandomnessRange:            5,
-	OverAskForBidsFactor:               3,
-	FailureInjectionConfig: models.FailureInjectionRequesterConfig{
-		IsBadActor: false,
-	},
-	EvaluationBroker: types.EvaluationBrokerConfig{
-		EvalBrokerVisibilityTimeout:    types.Duration(60 * time.Second),
-		EvalBrokerInitialRetryDelay:    types.Duration(1 * time.Second),
-		EvalBrokerSubsequentRetryDelay: types.Duration(30 * time.Second),
-		EvalBrokerMaxRetryCount:        10,
-	},
-	Worker: types.WorkerConfig{
-		WorkerCount:                  runtime.NumCPU(),
-		WorkerEvalDequeueTimeout:     types.Duration(5 * time.Second),
-		WorkerEvalDequeueBaseBackoff: types.Duration(1 * time.Second),
-		WorkerEvalDequeueMaxBackoff:  types.Duration(30 * time.Second),
-	},
-	Scheduler: types.SchedulerConfig{
-		QueueBackoff:               types.Duration(1 * time.Minute),
-		NodeOverSubscriptionFactor: 1.5,
-	},
-	JobDefaults: types.JobDefaults{
-		TotalTimeout: types.Duration(30 * time.Minute),
-	},
-	StorageProvider: types.StorageProviderConfig{
-		S3: types.S3StorageProviderConfig{
-			PreSignedURLExpiration: types.Duration(30 * time.Minute),
-		},
-	},
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second),
-	},
-	NodeInfoStoreTTL: types.Duration(10 * time.Minute),
-}
diff --git a/pkg/config/environment.go b/pkg/config/environment.go
deleted file mode 100644
index 5a9520d632..0000000000
--- a/pkg/config/environment.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package config
-
-import (
-	"os"
-	"strings"
-
-	"github.com/rs/zerolog/log"
-	flag "github.com/spf13/pflag"
-
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-)
-
-type Environment string
-
-const (
-	// Known environments that are configured in ops/terraform:
-	EnvironmentStaging Environment = "staging"
-	EnvironmentProd    Environment = "production"
-	EnvironmentDev     Environment = "development"
-	EnvironmentTest    Environment = "test"
-	EnvironmentLocal   Environment = "local"
-)
-
-func (e Environment) String() string {
-	return string(e)
-}
-
-func (e Environment) IsKnown() bool {
-	switch e {
-	case EnvironmentStaging, EnvironmentProd, EnvironmentDev, EnvironmentTest, EnvironmentLocal:
-		return true
-	}
-	return false
-}
-
-func ForEnvironment() types.BacalhauConfig {
-	env := GetConfigEnvironment()
-	switch env {
-	case EnvironmentProd:
-		return configenv.Production
-	case EnvironmentStaging:
-		return configenv.Staging
-	case EnvironmentDev:
-		return configenv.Development
-	case EnvironmentTest:
-		return configenv.Testing
-	case EnvironmentLocal:
-		return configenv.Local
-	default:
-		// this would indicate an error in the above logic of `GetEnvironment()`
-		return configenv.Local
-	}
-}
-
-func GetConfigEnvironment() Environment {
-	env := Environment(os.Getenv("BACALHAU_ENVIRONMENT"))
-	if !env.IsKnown() {
-		// Log as trace since we don't want to spam CLI users:
-		log.Trace().Msgf("BACALHAU_ENVIRONMENT is not set to a known value: %s", env)
-
-		// This usually happens in the case of a short-lived test cluster, in
-		// which case we should default to development. However, we want to
-		// avoid using any environment-specific settings for IPFS swarms
-		// (which are only configured for production and staging)
-		if strings.Contains(os.Args[0], "/_test/") ||
-			strings.HasSuffix(os.Args[0], ".test") ||
-			flag.Lookup("test.v") != nil ||
-			flag.Lookup("test.run") != nil {
-			env = EnvironmentTest
-		} else {
-			log.Debug().Msgf("Defaulting to production environment: \n os.Args: %v", os.Args)
-			env = EnvironmentProd
-		}
-	}
-	return env
-}
diff --git a/pkg/config/migrate.go b/pkg/config/migrate.go
new file mode 100644
index 0000000000..f31424e043
--- /dev/null
+++ b/pkg/config/migrate.go
@@ -0,0 +1,229 @@
+package config
+
+import (
+	"fmt"
+	"slices"
+	"strings"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	v1types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
+)
+
+func MigrateV1(in v1types.BacalhauConfig) (types.Bacalhau, error) {
+	out := types.Bacalhau{
+		API: migrateAPI(in),
+		Orchestrator: types.Orchestrator{
+			Enabled: slices.ContainsFunc(in.Node.Type, func(s string) bool {
+				return strings.ToLower(s) == "requester"
+			}),
+			Advertise: in.Node.Network.AdvertisedAddress,
+			Cluster:   migrateCluster(in.Node.Network.Cluster),
+			NodeManager: types.NodeManager{
+				DisconnectTimeout: types.Duration(in.Node.Requester.ControlPlaneSettings.NodeDisconnectedAfter),
+				ManualApproval:    in.Node.Requester.ManualNodeApproval,
+			},
+			Scheduler: types.Scheduler{
+				WorkerCount:          in.Node.Requester.Worker.WorkerCount,
+				HousekeepingInterval: types.Duration(in.Node.Requester.HousekeepingBackgroundTaskInterval),
+			},
+			EvaluationBroker: types.EvaluationBroker{
+				VisibilityTimeout: types.Duration(in.Node.Requester.EvaluationBroker.EvalBrokerVisibilityTimeout),
+				MaxRetryCount:     in.Node.Requester.EvaluationBroker.EvalBrokerMaxRetryCount,
+			},
+		},
+		Compute: types.Compute{
+			Enabled: slices.ContainsFunc(in.Node.Type, func(s string) bool {
+				return strings.ToLower(s) == "compute"
+			}),
+			Orchestrators: in.Node.Network.Orchestrators,
+			Labels:        in.Node.Labels,
+			Heartbeat: types.Heartbeat{
+				Interval:               types.Duration(in.Node.Compute.ControlPlaneSettings.HeartbeatFrequency),
+				ResourceUpdateInterval: types.Duration(in.Node.Compute.ControlPlaneSettings.ResourceUpdateFrequency),
+				InfoUpdateInterval:     types.Duration(in.Node.Compute.ControlPlaneSettings.InfoUpdateFrequency),
+			},
+			AllowListedLocalPaths: in.Node.AllowListedLocalPaths,
+		},
+		WebUI: types.WebUI{
+			Enabled: in.Node.WebUI.Enabled,
+			Listen: func(enabled bool, port int) string {
+				if enabled {
+					return fmt.Sprintf("0.0.0.0:%d", port)
+				}
+				return ""
+			}(in.Node.WebUI.Enabled, in.Node.WebUI.Port),
+		},
+		InputSources:      migrateInputSources(in.Node),
+		Publishers:        migratePublishers(in.Node),
+		Engines:           migrateEngines(in.Node),
+		ResultDownloaders: migrateDownloadConfig(in.Node),
+		JobAdmissionControl: func(config v1types.NodeConfig) types.JobAdmissionControl {
+			out := types.JobAdmissionControl{
+				RejectStatelessJobs: in.Node.Requester.JobSelectionPolicy.RejectStatelessJobs,
+				AcceptNetworkedJobs: in.Node.Requester.JobSelectionPolicy.AcceptNetworkedJobs,
+				ProbeHTTP:           in.Node.Requester.JobSelectionPolicy.ProbeHTTP,
+				ProbeExec:           in.Node.Requester.JobSelectionPolicy.ProbeExec,
+			}
+
+			// compute node configuration takes precedence.
+			if in.Node.Compute.JobSelection.RejectStatelessJobs {
+				out.RejectStatelessJobs = in.Node.Compute.JobSelection.RejectStatelessJobs
+			}
+			if in.Node.Compute.JobSelection.AcceptNetworkedJobs {
+				out.RejectStatelessJobs = in.Node.Compute.JobSelection.AcceptNetworkedJobs
+			}
+			if in.Node.Compute.JobSelection.ProbeHTTP != "" {
+				out.ProbeHTTP = in.Node.Compute.JobSelection.ProbeHTTP
+			}
+			if in.Node.Compute.JobSelection.ProbeExec != "" {
+				out.ProbeExec = in.Node.Compute.JobSelection.ProbeExec
+			}
+
+			return out
+		}(in.Node),
+		Logging: types.Logging{
+			Mode:                 string(in.Node.LoggingMode),
+			LogDebugInfoInterval: types.Duration(in.Node.Compute.Logging.LogRunningExecutionsInterval),
+		},
+		UpdateConfig: types.UpdateConfig{
+			Interval: types.Duration(in.Update.CheckFrequency),
+		},
+		FeatureFlags: types.FeatureFlags{
+			ExecTranslation: in.Node.Requester.TranslationEnabled,
+		},
+	}
+	return out, nil
+}
+
+func migrateCluster(in v1types.NetworkClusterConfig) types.Cluster {
+	var out types.Cluster
+	if in.Port != 0 {
+		out.Port = in.Port
+	}
+	if len(in.Peers) != 0 {
+		out.Peers = in.Peers
+	}
+	if in.AdvertisedAddress != "" {
+		in.AdvertisedAddress = out.Advertise
+	}
+	return out
+}
+
+func migrateAPI(in v1types.BacalhauConfig) types.API {
+	var (
+		out types.API
+	)
+	// migrate the existing auth methods
+	if len(in.Auth.Methods) > 0 {
+		out.Auth.Methods = func(cfg map[string]v1types.AuthenticatorConfig) map[string]types.AuthenticatorConfig {
+			out := make(map[string]types.AuthenticatorConfig)
+			for k, v := range cfg {
+				out[k] = types.AuthenticatorConfig{
+					Type:       string(v.Type),
+					PolicyPath: v.PolicyPath,
+				}
+			}
+			return out
+		}(in.Auth.Methods)
+	}
+	out.Auth.AccessPolicyPath = in.Auth.AccessPolicyPath
+
+	// check for a client config, taking lowest precedence.
+	if in.Node.ClientAPI.Host != "" {
+		out.Host = in.Node.ClientAPI.Host
+	}
+	if in.Node.ClientAPI.Port != 0 {
+		out.Port = in.Node.ClientAPI.Port
+	}
+	if in.Node.ClientAPI.ClientTLS.UseTLS {
+		out.TLS.UseTLS = in.Node.ClientAPI.ClientTLS.UseTLS
+	}
+	if in.Node.ClientAPI.ClientTLS.CACert != "" {
+		out.TLS.CAFile = in.Node.ClientAPI.ClientTLS.CACert
+	}
+	if in.Node.ClientAPI.ClientTLS.Insecure {
+		out.TLS.Insecure = in.Node.ClientAPI.ClientTLS.Insecure
+	}
+
+	// check for a server config, taking highest precedence.
+	if in.Node.ServerAPI.Host != "" {
+		out.Host = in.Node.ServerAPI.Host
+	}
+	if in.Node.ServerAPI.Port != 0 {
+		out.Port = in.Node.ServerAPI.Port
+	}
+	if in.Node.ServerAPI.TLS.ServerKey != "" {
+		out.TLS.KeyFile = in.Node.ServerAPI.TLS.ServerKey
+	}
+	if in.Node.ServerAPI.TLS.SelfSigned {
+		out.TLS.SelfSigned = in.Node.ServerAPI.TLS.SelfSigned
+	}
+	if in.Node.ServerAPI.TLS.ServerCertificate != "" {
+		out.TLS.CertFile = in.Node.ServerAPI.TLS.ServerCertificate
+	}
+	if in.Node.ServerAPI.TLS.AutoCertCachePath != "" {
+		out.TLS.AutoCertCachePath = in.Node.ServerAPI.TLS.AutoCertCachePath
+	}
+	if in.Node.ServerAPI.TLS.AutoCert != "" {
+		out.TLS.AutoCert = in.Node.ServerAPI.TLS.AutoCert
+	}
+
+	return out
+}
+
+func migrateDownloadConfig(in v1types.NodeConfig) types.ResultDownloaders {
+	var out types.ResultDownloaders
+
+	out.Timeout = types.Duration(in.DownloadURLRequestTimeout)
+	out.Types.IPFS.Endpoint = in.IPFS.Connect
+
+	return out
+}
+
+func migrateEngines(in v1types.NodeConfig) types.EngineConfig {
+	var out types.EngineConfig
+
+	// migrate any disabled engines
+	out.Disabled = in.DisabledFeatures.Engines
+
+	out.Types.Docker.ManifestCache = types.DockerManifestCache{
+		Size:    in.Compute.ManifestCache.Size,
+		TTL:     types.Duration(in.Compute.ManifestCache.Duration),
+		Refresh: types.Duration(in.Compute.ManifestCache.Frequency),
+	}
+
+	return out
+}
+
+func migratePublishers(in v1types.NodeConfig) types.PublishersConfig {
+	var out types.PublishersConfig
+
+	// migrate any disabled publishers
+	out.Disabled = in.DisabledFeatures.Publishers
+
+	// ipfs
+	out.Types.IPFS.Endpoint = in.IPFS.Connect
+
+	// local
+	out.Types.Local.Port = in.Compute.LocalPublisher.Port
+	out.Types.Local.Address = in.Compute.LocalPublisher.Address
+	out.Types.Local.Directory = in.Compute.LocalPublisher.Directory
+
+	// s3
+	out.Types.S3.PreSignedURLExpiration = types.Duration(in.Requester.StorageProvider.S3.PreSignedURLExpiration)
+	out.Types.S3.PreSignedURLDisabled = in.Requester.StorageProvider.S3.PreSignedURLDisabled
+
+	return out
+}
+
+func migrateInputSources(in v1types.NodeConfig) types.InputSourcesConfig {
+	var out types.InputSourcesConfig
+
+	// migrate any disabled storages
+	out.Disabled = in.DisabledFeatures.Storages
+
+	// ipfs
+	out.Types.IPFS.Endpoint = in.IPFS.Connect
+
+	return out
+}
diff --git a/pkg/config/types/auth.go b/pkg/config/types/auth.go
index 3cc4c2181c..7ae009c441 100644
--- a/pkg/config/types/auth.go
+++ b/pkg/config/types/auth.go
@@ -1,26 +1,7 @@
 package types
 
-import "github.com/bacalhau-project/bacalhau/pkg/authn"
-
-// AuthenticationConfig is config for a specific named authentication method,
-// specifying the type of authentication and the path to a policy file that
-// controls the method. Some implementation types may require policies that meet
-// a certain interface beyond the default – see the documentation on that type
-// for more info.
-type AuthenticatorConfig struct {
-	Type       authn.MethodType `yaml:"Type"`
-	PolicyPath string           `yaml:"PolicyPath,omitempty"`
-}
-
 // AuthConfig is config that controls user authentication and authorization.
 type AuthConfig struct {
-	// TokensPath is the location where a state file of tokens will be stored.
-	// By default it will be local to the Bacalhau repo, but can be any location
-	// in the host filesystem. Tokens are sensitive and should be stored in a
-	// location that is only readable to the current user.
-	// Deprecated: replaced by cfg.AuthTokensPath()
-	TokensPath string `yaml:"TokensPath"`
-
 	// Methods maps "method names" to authenticator implementations. A method
 	// name is a human-readable string chosen by the person configuring the
 	// system that is shown to users to help them pick the authentication method
@@ -35,11 +16,21 @@ type AuthConfig struct {
 	//
 	// By default, only a single authentication method that accepts
 	// authentication via client keys will be enabled.
-	Methods map[string]AuthenticatorConfig `yaml:"Methods"`
+	Methods map[string]AuthenticatorConfig `yaml:"Methods,omitempty"`
 
 	// AccessPolicyPath is the path to a file or directory that will be loaded as
 	// the policy to apply to all inbound API requests. If unspecified, a policy
 	// that permits access to all API endpoints to both authenticated and
 	// unauthenticated users (the default as of v1.2.0) will be used.
-	AccessPolicyPath string `yaml:"AccessPolicyPath"`
+	AccessPolicyPath string `yaml:"AccessPolicyPath,omitempty"`
+}
+
+// AuthenticatorConfig is config for a specific named authentication method,
+// specifying the type of authentication and the path to a policy file that
+// controls the method. Some implementation types may require policies that meet
+// a certain interface beyond the default – see the documentation on that type
+// for more info.
+type AuthenticatorConfig struct {
+	Type       string `yaml:"Type,omitempty"`
+	PolicyPath string `yaml:"PolicyPath,omitempty"`
 }
diff --git a/pkg/config/types/bacalhau.go b/pkg/config/types/bacalhau.go
new file mode 100644
index 0000000000..a173e64fae
--- /dev/null
+++ b/pkg/config/types/bacalhau.go
@@ -0,0 +1,93 @@
+package types
+
+// NB: Developers, after making changes (comments included) to this struct or any of its children, run go generate.
+
+//go:generate go run gen/generate.go ./
+type Bacalhau struct {
+	API API `yaml:"API,omitempty"`
+	// NameProvider specifies the method used to generate names for the node. One of: hostname, aws, gcp, uuid, puuid.
+	NameProvider string `yaml:"NameProvider,omitempty"`
+	// DataDir specifies a location on disk where the bacalhau node will maintain state.
+	DataDir string `yaml:"DataDir,omitempty"`
+	// StrictVersionMatch indicates whether to enforce strict version matching.
+	StrictVersionMatch  bool                `yaml:"StrictVersionMatch,omitempty"`
+	Orchestrator        Orchestrator        `yaml:"Orchestrator,omitempty"`
+	Compute             Compute             `yaml:"Compute,omitempty"`
+	WebUI               WebUI               `yaml:"WebUI,omitempty"`
+	InputSources        InputSourcesConfig  `yaml:"InputSources,omitempty"`
+	Publishers          PublishersConfig    `yaml:"Publishers,omitempty"`
+	Engines             EngineConfig        `yaml:"Engines,omitempty"`
+	ResultDownloaders   ResultDownloaders   `yaml:"ResultDownloaders,omitempty"`
+	JobDefaults         JobDefaults         `yaml:"JobDefaults,omitempty"`
+	JobAdmissionControl JobAdmissionControl `yaml:"JobAdmissionControl,omitempty"`
+	Logging             Logging             `yaml:"Logging,omitempty"`
+	UpdateConfig        UpdateConfig        `yaml:"UpdateConfig,omitempty"`
+	FeatureFlags        FeatureFlags        `yaml:"FeatureFlags,omitempty"`
+}
+
+type API struct {
+	// Host specifies the hostname or IP address on which the API server listens or the client connects.
+	Host string `yaml:"Host,omitempty"`
+	// Port specifies the port number on which the API server listens or the client connects.
+	Port int        `yaml:"Port,omitempty"`
+	TLS  TLS        `yaml:"TLS,omitempty"`
+	Auth AuthConfig `yaml:"Auth,omitempty"`
+}
+
+type TLS struct {
+	// CertFile specifies the path to the TLS certificate file.
+	CertFile string `yaml:"CertFile,omitempty"`
+	// KeyFile specifies the path to the TLS private key file.
+	KeyFile string `yaml:"KeyFile,omitempty"`
+	// CAFile specifies the path to the Certificate Authority file.
+	CAFile string `yaml:"CAFile,omitempty"`
+
+	// UseTLS indicates whether to use TLS for client connections.
+	UseTLS bool `yaml:"UseTLS,omitempty"`
+	// Insecure allows insecure TLS connections (e.g., self-signed certificates).
+	Insecure bool `yaml:"Insecure"`
+
+	// SelfSigned indicates whether to use a self-signed certificate.
+	SelfSigned bool `yaml:"SelfSigned,omitempty"`
+	// AutoCert specifies the domain for automatic certificate generation.
+	AutoCert string `yaml:"AutoCert,omitempty"`
+	// AutoCertCachePath specifies the directory to cache auto-generated certificates.
+	AutoCertCachePath string `yaml:"AutoCertCachePath,omitempty"`
+}
+
+type WebUI struct {
+	// Enabled indicates whether the Web UI is enabled.
+	Enabled bool `yaml:"Enabled,omitempty"`
+	// Listen specifies the address and port on which the Web UI listens.
+	Listen string `yaml:"Listen,omitempty"`
+}
+
+type Logging struct {
+	// Level sets the logging level. One of: trace, debug, info, warn, error, fatal, panic.
+	Level string `yaml:"Level,omitempty"`
+	// Mode specifies the logging mode. One of: default, json.
+	Mode string `yaml:"Mode,omitempty"`
+	// LogDebugInfoInterval specifies the interval for logging debug information.
+	LogDebugInfoInterval Duration `yaml:"LogDebugInfoInterval,omitempty"`
+}
+
+type FeatureFlags struct {
+	// ExecTranslation enables the execution translation feature.
+	ExecTranslation bool `yaml:"ExecTranslation,omitempty"`
+}
+
+type UpdateConfig struct {
+	// Interval specifies the time between update checks, when set to 0 update checks are not performed.
+	Interval Duration `yaml:"Interval,omitempty"`
+}
+
+type JobAdmissionControl struct {
+	// RejectStatelessJobs indicates whether to reject stateless jobs, i.e. jobs without inputs.
+	RejectStatelessJobs bool `yaml:"RejectStatelessJobs,omitempty"`
+	// AcceptNetworkedJobs indicates whether to accept jobs that require network access.
+	AcceptNetworkedJobs bool `yaml:"AcceptNetworkedJobs,omitempty"`
+	// ProbeHTTP specifies the HTTP endpoint for probing job submission.
+	ProbeHTTP string `yaml:"ProbeHTTP,omitempty"`
+	// ProbeExec specifies the command to execute for probing job submission.
+	ProbeExec string `yaml:"ProbeExec,omitempty"`
+}
diff --git a/pkg/config/types/compute.go b/pkg/config/types/compute.go
index 116aeeff0d..168f576bc1 100644
--- a/pkg/config/types/compute.go
+++ b/pkg/config/types/compute.go
@@ -1,76 +1,24 @@
 package types
 
-import (
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-type ComputeConfig struct {
-	Capacity             CapacityConfig            `yaml:"Capacity"`
-	ExecutionStore       JobStoreConfig            `yaml:"ExecutionStore"`
-	JobTimeouts          JobTimeoutConfig          `yaml:"JobTimeouts"`
-	JobSelection         models.JobSelectionPolicy `yaml:"JobSelection"`
-	Logging              LoggingConfig             `yaml:"Logging"`
-	ManifestCache        DockerCacheConfig         `yaml:"ManifestCache"`
-	LogStreamConfig      LogStreamConfig           `yaml:"LogStream"`
-	LocalPublisher       LocalPublisherConfig      `yaml:"LocalPublisher"`
-	ControlPlaneSettings ComputeControlPlaneConfig `yaml:"ClusterTimeouts"`
-}
-
-type CapacityConfig struct {
-	IgnorePhysicalResourceLimits bool `yaml:"IgnorePhysicalResourceLimits"`
-	// Total amount of resource the system can be using at one time in aggregate for all jobs.
-	TotalResourceLimits models.ResourcesConfig `yaml:"TotalResourceLimits"`
-	// Per job amount of resource the system can be using at one time.
-	JobResourceLimits        models.ResourcesConfig `yaml:"JobResourceLimits"`
-	DefaultJobResourceLimits models.ResourcesConfig `yaml:"DefaultJobResourceLimits"`
-}
-
-type JobTimeoutConfig struct {
-	// JobExecutionTimeoutClientIDBypassList is the list of clients that are allowed to bypass the job execution timeout
-	// check.
-	JobExecutionTimeoutClientIDBypassList []string `yaml:"JobExecutionTimeoutClientIDBypassList"`
-	// JobNegotiationTimeout default timeout value to hold a bid for a job
-	JobNegotiationTimeout Duration `yaml:"JobNegotiationTimeout"`
-	// MinJobExecutionTimeout default value for the minimum execution timeout this compute node supports. Jobs with
-	// lower timeout requirements will not be bid on.
-	MinJobExecutionTimeout Duration `yaml:"MinJobExecutionTimeout"`
-	// MaxJobExecutionTimeout default value for the maximum execution timeout this compute node supports. Jobs with
-	// higher timeout requirements will not be bid on.
-	MaxJobExecutionTimeout Duration `yaml:"MaxJobExecutionTimeout"`
-	// DefaultJobExecutionTimeout default value for the execution timeout this compute node will assign to jobs with
-	// no timeout requirement defined.
-	DefaultJobExecutionTimeout Duration `yaml:"DefaultJobExecutionTimeout"`
-}
-
-type LoggingConfig struct {
-	// logging running executions
-	LogRunningExecutionsInterval Duration `yaml:"LogRunningExecutionsInterval"`
+type Compute struct {
+	// Enabled indicates whether the compute node is active and available for job execution.
+	Enabled bool `yaml:"Enabled,omitempty"`
+	// Orchestrators specifies a list of orchestrator endpoints that this compute node connects to.
+	Orchestrators []string  `yaml:"Orchestrators,omitempty"`
+	TLS           TLS       `yaml:"TLS,omitempty"`
+	Heartbeat     Heartbeat `yaml:"Heartbeat,omitempty"`
+	// Labels are key-value pairs used to describe and categorize the compute node.
+	Labels            map[string]string `yaml:"Labels,omitempty"`
+	AllocatedCapacity ResourceScaler    `yaml:"AllocatedCapacity,omitempty"`
+	// AllowListedLocalPaths specifies a list of local file system paths that the compute node is allowed to access.
+	AllowListedLocalPaths []string `yaml:"AllowListedLocalPaths"`
 }
 
-type LogStreamConfig struct {
-	// How many messages to buffer in the log stream channel, per stream
-	ChannelBufferSize int `yaml:"ChannelBufferSize"`
-}
-
-type LocalPublisherConfig struct {
-	Address   string `yaml:"Address"`
-	Port      int    `yaml:"Port"`
-	Directory string `yaml:"Directory"`
-}
-
-type ComputeControlPlaneConfig struct {
-	// The frequency with which the compute node will send node info (inc current labels)
-	// to the controlling requester node.
-	InfoUpdateFrequency Duration `yaml:"InfoUpdateFrequency"`
-
-	// How often the compute node will send current resource availability to the requester node.
-	ResourceUpdateFrequency Duration `yaml:"ResourceUpdateFrequency"`
-
-	// How often the compute node will send a heartbeat to the requester node to let it know
-	// that the compute node is still alive. This should be less than the requester's configured
-	// heartbeat timeout to avoid flapping.
-	HeartbeatFrequency Duration `yaml:"HeartbeatFrequency"`
-
-	// This is the pubsub topic that the compute node will use to send heartbeats to the requester node.
-	HeartbeatTopic string `yaml:"HeartbeatTopic"`
+type Heartbeat struct {
+	// InfoUpdateInterval specifies the time between updates of non-resource information to the orchestrator.
+	InfoUpdateInterval Duration `yaml:"InfoUpdateInterval,omitempty"`
+	// ResourceUpdateInterval specifies the time between updates of resource information to the orchestrator.
+	ResourceUpdateInterval Duration `yaml:"ResourceUpdateInterval,omitempty"`
+	// Interval specifies the time between heartbeat signals sent to the orchestrator.
+	Interval Duration `yaml:"Interval,omitempty"`
 }
diff --git a/pkg/config/types/default_config.go b/pkg/config/types/default_config.go
new file mode 100644
index 0000000000..dfbf8e3bb7
--- /dev/null
+++ b/pkg/config/types/default_config.go
@@ -0,0 +1,154 @@
+package types
+
+import (
+	"os"
+	"path/filepath"
+	"runtime"
+	"time"
+
+	"github.com/bacalhau-project/bacalhau/pkg/publisher/local"
+)
+
+const (
+	Second = Duration(time.Second)
+	Minute = Duration(time.Minute)
+	Day    = Duration(time.Hour * 24)
+)
+
+// Default is the default configuration for a bacalhau node.
+var Default = Bacalhau{
+	DataDir: DefaultDataDir(),
+	API: API{
+		Host: "0.0.0.0",
+		Port: 1234,
+		Auth: AuthConfig{
+			Methods: map[string]AuthenticatorConfig{
+				"ClientKey": {
+					Type: "challenge",
+				},
+			},
+		},
+	},
+	NameProvider: "puuid",
+	Orchestrator: Orchestrator{
+		Enabled: true,
+		Host:    "0.0.0.0",
+		Port:    4222,
+		NodeManager: NodeManager{
+			DisconnectTimeout: Minute,
+		},
+		Scheduler: Scheduler{
+			WorkerCount:          runtime.NumCPU(),
+			HousekeepingInterval: 30 * Second,
+			HousekeepingTimeout:  2 * Minute,
+		},
+		EvaluationBroker: EvaluationBroker{
+			VisibilityTimeout: Minute,
+			MaxRetryCount:     10,
+		},
+	},
+	Compute: Compute{
+		Enabled:       false,
+		Orchestrators: []string{"nats://127.0.0.1:4222"},
+		Heartbeat: Heartbeat{
+			InfoUpdateInterval:     Minute,
+			ResourceUpdateInterval: 30 * Second,
+			Interval:               15 * Second,
+		},
+		AllocatedCapacity: ResourceScaler{
+			CPU:    "70%",
+			Memory: "70%",
+			Disk:   "70%",
+			GPU:    "100%",
+		},
+	},
+	JobDefaults: JobDefaults{
+		Batch: BatchJobDefaultsConfig{
+			Priority: 0,
+			Task: BatchTaskDefaultConfig{
+				Resources: ResourcesConfig{
+					CPU:    "500m",
+					Memory: "1Gb",
+				},
+				Publisher: DefaultPublisherConfig{
+					Config: *local.NewSpecConfig(),
+				},
+			},
+		},
+		Ops: BatchJobDefaultsConfig{
+			Priority: 0,
+			Task: BatchTaskDefaultConfig{
+				Resources: ResourcesConfig{
+					CPU:    "500m",
+					Memory: "1Gb",
+				},
+				Publisher: DefaultPublisherConfig{
+					Config: *local.NewSpecConfig(),
+				},
+			},
+		},
+		Daemon: LongRunningJobDefaultsConfig{
+			Priority: 0,
+			Task: LongRunningTaskDefaultConfig{
+				Resources: ResourcesConfig{
+					CPU:    "500m",
+					Memory: "1Gb",
+				},
+			},
+		},
+		Service: LongRunningJobDefaultsConfig{
+			Priority: 0,
+			Task: LongRunningTaskDefaultConfig{
+				Resources: ResourcesConfig{
+					CPU:    "500m",
+					Memory: "1Gb",
+				},
+			},
+		},
+	},
+	InputSources: InputSourcesConfig{
+		ReadTimeout:   Duration(5 * time.Minute),
+		MaxRetryCount: 3,
+	},
+	Engines: EngineConfig{
+		Types: EngineConfigTypes{
+			Docker: Docker{
+				ManifestCache: DockerManifestCache{
+					Size:    1000,
+					TTL:     Duration(1 * time.Hour),
+					Refresh: Duration(1 * time.Hour),
+				}},
+		},
+	},
+	Logging: Logging{
+		Level:                "info",
+		Mode:                 "default",
+		LogDebugInfoInterval: 0,
+	},
+	UpdateConfig: UpdateConfig{
+		Interval: Day,
+	},
+	WebUI: WebUI{
+		Enabled: false,
+		Listen:  "0.0.0.0:8438",
+	},
+}
+
+const defaultBacalhauDir = ".bacalhau"
+
+// DefaultDataDir determines the appropriate default directory for storing repository data.
+// Priority order:
+// 1. If the environment variable BACALHAU_DIR is set and non-empty, use it.
+// 2. User's home directory with .bacalhau appended.
+// 3. If all above fail, use .bacalhau in the current directory.
+func DefaultDataDir() string {
+	if repoDir, set := os.LookupEnv("BACALHAU_DIR"); set && repoDir != "" {
+		return repoDir
+	}
+
+	if userHome, err := os.UserHomeDir(); err == nil {
+		return filepath.Join(userHome, defaultBacalhauDir)
+	}
+
+	return defaultBacalhauDir
+}
diff --git a/pkg/config/types/downloaders.go b/pkg/config/types/downloaders.go
new file mode 100644
index 0000000000..01f8d2c357
--- /dev/null
+++ b/pkg/config/types/downloaders.go
@@ -0,0 +1,31 @@
+package types
+
+import (
+	"slices"
+	"strings"
+)
+
+var _ Provider = (*ResultDownloaders)(nil)
+
+type ResultDownloaders struct {
+	// Disabled is a list of downloaders that are disabled.
+	Disabled []string `yaml:"Disabled,omitempty"`
+	// Timeout specifies the maximum time allowed for a download operation.
+	Timeout Duration               `yaml:"Timeout,omitempty"`
+	Types   ResultDownloadersTypes `yaml:"Types,omitempty"`
+}
+
+type ResultDownloadersTypes struct {
+	IPFS IpfsDownloader `yaml:"IPFS,omitempty"`
+}
+
+func (r ResultDownloaders) IsNotDisabled(kind string) bool {
+	return !slices.ContainsFunc(r.Disabled, func(s string) bool {
+		return strings.ToLower(s) == strings.ToLower(kind)
+	})
+}
+
+type IpfsDownloader struct {
+	// Endpoint specifies the multi-address to connect to for IPFS. e.g /ip4/127.0.0.1/tcp/5001
+	Endpoint string `yaml:"Endpoint,omitempty"`
+}
diff --git a/pkg/config/types/duration.go b/pkg/config/types/duration.go
index 2b7cb03be2..76ec4047e0 100644
--- a/pkg/config/types/duration.go
+++ b/pkg/config/types/duration.go
@@ -1,6 +1,8 @@
 package types
 
-import "time"
+import (
+	"time"
+)
 
 // Duration is a wrapper type for time.Duration
 // for decoding and encoding from/to YAML, etc.
diff --git a/pkg/config/types/engines.go b/pkg/config/types/engines.go
new file mode 100644
index 0000000000..6058e74550
--- /dev/null
+++ b/pkg/config/types/engines.go
@@ -0,0 +1,44 @@
+package types
+
+import (
+	"slices"
+	"strings"
+)
+
+var _ Provider = (*EngineConfig)(nil)
+
+type EngineConfig struct {
+	// Disabled specifies a list of engines that are disabled.
+	Disabled []string          `yaml:"Disabled,omitempty"`
+	Types    EngineConfigTypes `yaml:"Types,omitempty"`
+}
+
+type EngineConfigTypes struct {
+	Docker Docker `yaml:"Docker,omitempty"`
+	WASM   WASM   `yaml:"WASM,omitempty"`
+}
+
+func (e EngineConfig) IsNotDisabled(kind string) bool {
+	return !slices.ContainsFunc(e.Disabled, func(s string) bool {
+		return strings.ToLower(s) == strings.ToLower(kind)
+	})
+}
+
+// Docker represents the configuration settings for the Docker runtime provider.
+type Docker struct {
+	// ManifestCache specifies the settings for the Docker manifest cache.
+	ManifestCache DockerManifestCache `yaml:"ManifestCache,omitempty"`
+}
+
+// DockerManifestCache represents the configuration settings for the Docker manifest cache.
+type DockerManifestCache struct {
+	// Size specifies the size of the Docker manifest cache.
+	Size uint64 `yaml:"Size,omitempty"`
+	// TTL specifies the time-to-live duration for cache entries.
+	TTL Duration `yaml:"TTL,omitempty"`
+	// Refresh specifies the refresh interval for cache entries.
+	Refresh Duration `yaml:"Refresh,omitempty"`
+}
+
+type WASM struct {
+}
diff --git a/pkg/config/types/gen_paths/generate.go b/pkg/config/types/gen/generate.go
similarity index 65%
rename from pkg/config/types/gen_paths/generate.go
rename to pkg/config/types/gen/generate.go
index 1e355b981e..5eec5baca2 100644
--- a/pkg/config/types/gen_paths/generate.go
+++ b/pkg/config/types/gen/generate.go
@@ -13,6 +13,65 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
+// processStructFields processes the fields of a struct type using the provided handler function.
+func processStructFields(t reflect.Type, prefix string, file *os.File, handleLeafNode func(field reflect.StructField, newPrefix string)) {
+	for i := 0; i < t.NumField(); i++ {
+		field := t.Field(i)
+		tag := field.Tag.Get("config")
+		newPrefix := prefix
+
+		if tag != "" {
+			if newPrefix != "" {
+				newPrefix += "."
+			}
+			newPrefix += tag
+		} else if !field.Anonymous {
+			if newPrefix != "" {
+				newPrefix += "."
+			}
+			newPrefix += field.Name
+		}
+
+		if field.Type.Kind() == reflect.Struct {
+			// Recursively process nested structs
+			processStructFields(field.Type, newPrefix, file, handleLeafNode)
+		} else {
+			// Handle leaf node
+			handleLeafNode(field, newPrefix)
+		}
+	}
+}
+
+// generateConstants generates constant definitions for each leaf field in the given struct type.
+func generateConstants(t reflect.Type, prefix string, file *os.File) {
+	handleLeafNode := func(field reflect.StructField, newPrefix string) {
+		constantName := strings.ReplaceAll(newPrefix, ".", "")
+		constantValue := strings.ToLower(newPrefix)
+		fmt.Fprintf(file, "const %sKey = \"%s\"\n", constantName, constantValue)
+	}
+	processStructFields(t, prefix, file, handleLeafNode)
+}
+
+// generateDescriptions generates the map of configuration descriptions.
+func generateDescriptions(t reflect.Type, prefix string, file *os.File) {
+	handleLeafNode := func(field reflect.StructField, newPrefix string) {
+		description := commentsMap[field.Name]
+		if description == "" {
+			description = "No description available"
+		} else {
+			// Clean up the comment: remove leading "//" and newlines
+			description = strings.TrimPrefix(description, "//")
+			description = strings.ReplaceAll(description, "\n", " ")
+			description = strings.TrimSpace(description)
+			description = escapeString(description)
+		}
+
+		constantName := strings.ReplaceAll(newPrefix, ".", "")
+		fmt.Fprintf(file, "\t%sKey: \"%s\",\n", constantName, description)
+	}
+	processStructFields(t, prefix, file, handleLeafNode)
+}
+
 var commentsMap = make(map[string]string)
 
 // extractComments extracts comments from the source files in the provided directory.
@@ -48,78 +107,6 @@ func escapeString(s string) string {
 	return strings.ReplaceAll(s, `"`, `\"`)
 }
 
-// generateConstants generates constant definitions for each field in the given struct type.
-func generateConstants(t reflect.Type, prefix string, file *os.File) {
-	for i := 0; i < t.NumField(); i++ {
-		field := t.Field(i)
-		tag := field.Tag.Get("config")
-		newPrefix := ""
-
-		if tag != "" {
-			newPrefix = tag
-		} else if field.Anonymous {
-			newPrefix = prefix
-		} else {
-			newPrefix = prefix
-			if newPrefix != "" {
-				newPrefix += "."
-			}
-			newPrefix += field.Name
-		}
-
-		if field.Type.Kind() == reflect.Struct {
-			constantNameForStruct := strings.ReplaceAll(newPrefix, ".", "")
-			fmt.Fprintf(file, "const %s = \"%s\"\n", constantNameForStruct, strings.ToLower(newPrefix))
-			generateConstants(field.Type, newPrefix, file)
-		} else {
-			constantName := strings.ReplaceAll(newPrefix, ".", "")
-			constantValue := strings.ToLower(newPrefix)
-			fmt.Fprintf(file, "const %s = \"%s\"\n", constantName, constantValue)
-		}
-	}
-}
-
-// generateDescriptions generates the map of configuration descriptions.
-func generateDescriptions(t reflect.Type, prefix string, file *os.File) {
-	for i := 0; i < t.NumField(); i++ {
-		field := t.Field(i)
-		tag := field.Tag.Get("config")
-		newPrefix := prefix
-
-		if tag != "" {
-			if newPrefix != "" {
-				newPrefix += "."
-			}
-			newPrefix += tag
-		} else if !field.Anonymous {
-			if newPrefix != "" {
-				newPrefix += "."
-			}
-			newPrefix += field.Name
-		}
-
-		if field.Type.Kind() != reflect.Struct {
-			description := commentsMap[field.Name]
-			if description == "" {
-				description = "No description available"
-			} else {
-				// Clean up the comment: remove leading "//" and newlines
-				description = strings.TrimPrefix(description, "//")
-				description = strings.ReplaceAll(description, "\n", " ")
-				description = strings.TrimSpace(description)
-				description = escapeString(description)
-			}
-
-			constantName := strings.ReplaceAll(newPrefix, ".", "")
-			fmt.Fprintf(file, "\t%s: \"%s\",\n", constantName, description)
-		}
-
-		if field.Type.Kind() == reflect.Struct {
-			generateDescriptions(field.Type, newPrefix, file)
-		}
-	}
-}
-
 func main() {
 	if len(os.Args) != 2 {
 		fmt.Println("Please provide the path to the config directory.")
@@ -144,7 +131,7 @@ func main() {
 	fmt.Fprintf(constantsFile, "// CODE GENERATED BY pkg/config/types/gen_paths DO NOT EDIT\n\n")
 	fmt.Fprintf(constantsFile, "package types\n\n")
 
-	generateConstants(reflect.TypeOf(types.BacalhauConfig{}), "", constantsFile)
+	generateConstants(reflect.TypeOf(types.Bacalhau{}), "", constantsFile)
 
 	// Generate descriptions file
 	descriptionsFile, err := os.Create(filepath.Join(inputDir, "generated_descriptions.go"))
@@ -160,7 +147,7 @@ func main() {
 	fmt.Fprintf(descriptionsFile, "// ConfigDescriptions maps configuration paths to their descriptions\n")
 	fmt.Fprintf(descriptionsFile, "var ConfigDescriptions = map[string]string{\n")
 
-	generateDescriptions(reflect.TypeOf(types.BacalhauConfig{}), "", descriptionsFile)
+	generateDescriptions(reflect.TypeOf(types.Bacalhau{}), "", descriptionsFile)
 
 	fmt.Fprintf(descriptionsFile, "}\n")
 
diff --git a/pkg/config/types/generated_constants.go b/pkg/config/types/generated_constants.go
index c249872988..34ac738d8e 100644
--- a/pkg/config/types/generated_constants.go
+++ b/pkg/config/types/generated_constants.go
@@ -2,173 +2,122 @@
 
 package types
 
-const Node = "node"
-const NodeName = "node.name"
-const NodeNameProvider = "node.nameprovider"
-const NodeClientAPI = "node.clientapi"
-const NodeClientAPIHost = "node.clientapi.host"
-const NodeClientAPIPort = "node.clientapi.port"
-const NodeClientAPIClientTLS = "node.clientapi.clienttls"
-const NodeClientAPIClientTLSUseTLS = "node.clientapi.clienttls.usetls"
-const NodeClientAPIClientTLSCACert = "node.clientapi.clienttls.cacert"
-const NodeClientAPIClientTLSInsecure = "node.clientapi.clienttls.insecure"
-const NodeClientAPITLS = "node.clientapi.tls"
-const NodeClientAPITLSAutoCert = "node.clientapi.tls.autocert"
-const NodeClientAPITLSAutoCertCachePath = "node.clientapi.tls.autocertcachepath"
-const NodeClientAPITLSServerCertificate = "node.clientapi.tls.servercertificate"
-const NodeClientAPITLSServerKey = "node.clientapi.tls.serverkey"
-const NodeClientAPITLSSelfSigned = "node.clientapi.tls.selfsigned"
-const NodeServerAPI = "node.serverapi"
-const NodeServerAPIHost = "node.serverapi.host"
-const NodeServerAPIPort = "node.serverapi.port"
-const NodeServerAPIClientTLS = "node.serverapi.clienttls"
-const NodeServerAPIClientTLSUseTLS = "node.serverapi.clienttls.usetls"
-const NodeServerAPIClientTLSCACert = "node.serverapi.clienttls.cacert"
-const NodeServerAPIClientTLSInsecure = "node.serverapi.clienttls.insecure"
-const NodeServerAPITLS = "node.serverapi.tls"
-const NodeServerAPITLSAutoCert = "node.serverapi.tls.autocert"
-const NodeServerAPITLSAutoCertCachePath = "node.serverapi.tls.autocertcachepath"
-const NodeServerAPITLSServerCertificate = "node.serverapi.tls.servercertificate"
-const NodeServerAPITLSServerKey = "node.serverapi.tls.serverkey"
-const NodeServerAPITLSSelfSigned = "node.serverapi.tls.selfsigned"
-const NodeIPFS = "node.ipfs"
-const NodeIPFSConnect = "node.ipfs.connect"
-const NodeCompute = "node.compute"
-const NodeComputeCapacity = "node.compute.capacity"
-const NodeComputeCapacityIgnorePhysicalResourceLimits = "node.compute.capacity.ignorephysicalresourcelimits"
-const NodeComputeCapacityTotalResourceLimits = "node.compute.capacity.totalresourcelimits"
-const NodeComputeCapacityTotalResourceLimitsCPU = "node.compute.capacity.totalresourcelimits.cpu"
-const NodeComputeCapacityTotalResourceLimitsMemory = "node.compute.capacity.totalresourcelimits.memory"
-const NodeComputeCapacityTotalResourceLimitsDisk = "node.compute.capacity.totalresourcelimits.disk"
-const NodeComputeCapacityTotalResourceLimitsGPU = "node.compute.capacity.totalresourcelimits.gpu"
-const NodeComputeCapacityJobResourceLimits = "node.compute.capacity.jobresourcelimits"
-const NodeComputeCapacityJobResourceLimitsCPU = "node.compute.capacity.jobresourcelimits.cpu"
-const NodeComputeCapacityJobResourceLimitsMemory = "node.compute.capacity.jobresourcelimits.memory"
-const NodeComputeCapacityJobResourceLimitsDisk = "node.compute.capacity.jobresourcelimits.disk"
-const NodeComputeCapacityJobResourceLimitsGPU = "node.compute.capacity.jobresourcelimits.gpu"
-const NodeComputeCapacityDefaultJobResourceLimits = "node.compute.capacity.defaultjobresourcelimits"
-const NodeComputeCapacityDefaultJobResourceLimitsCPU = "node.compute.capacity.defaultjobresourcelimits.cpu"
-const NodeComputeCapacityDefaultJobResourceLimitsMemory = "node.compute.capacity.defaultjobresourcelimits.memory"
-const NodeComputeCapacityDefaultJobResourceLimitsDisk = "node.compute.capacity.defaultjobresourcelimits.disk"
-const NodeComputeCapacityDefaultJobResourceLimitsGPU = "node.compute.capacity.defaultjobresourcelimits.gpu"
-const NodeComputeExecutionStore = "node.compute.executionstore"
-const NodeComputeExecutionStoreType = "node.compute.executionstore.type"
-const NodeComputeExecutionStorePath = "node.compute.executionstore.path"
-const NodeComputeJobTimeouts = "node.compute.jobtimeouts"
-const NodeComputeJobTimeoutsJobExecutionTimeoutClientIDBypassList = "node.compute.jobtimeouts.jobexecutiontimeoutclientidbypasslist"
-const NodeComputeJobTimeoutsJobNegotiationTimeout = "node.compute.jobtimeouts.jobnegotiationtimeout"
-const NodeComputeJobTimeoutsMinJobExecutionTimeout = "node.compute.jobtimeouts.minjobexecutiontimeout"
-const NodeComputeJobTimeoutsMaxJobExecutionTimeout = "node.compute.jobtimeouts.maxjobexecutiontimeout"
-const NodeComputeJobTimeoutsDefaultJobExecutionTimeout = "node.compute.jobtimeouts.defaultjobexecutiontimeout"
-const NodeComputeJobSelection = "node.compute.jobselection"
-const NodeComputeJobSelectionLocality = "node.compute.jobselection.locality"
-const NodeComputeJobSelectionRejectStatelessJobs = "node.compute.jobselection.rejectstatelessjobs"
-const NodeComputeJobSelectionAcceptNetworkedJobs = "node.compute.jobselection.acceptnetworkedjobs"
-const NodeComputeJobSelectionProbeHTTP = "node.compute.jobselection.probehttp"
-const NodeComputeJobSelectionProbeExec = "node.compute.jobselection.probeexec"
-const NodeComputeLogging = "node.compute.logging"
-const NodeComputeLoggingLogRunningExecutionsInterval = "node.compute.logging.logrunningexecutionsinterval"
-const NodeComputeManifestCache = "node.compute.manifestcache"
-const NodeComputeManifestCacheSize = "node.compute.manifestcache.size"
-const NodeComputeManifestCacheDuration = "node.compute.manifestcache.duration"
-const NodeComputeManifestCacheFrequency = "node.compute.manifestcache.frequency"
-const NodeComputeLogStreamConfig = "node.compute.logstreamconfig"
-const NodeComputeLogStreamConfigChannelBufferSize = "node.compute.logstreamconfig.channelbuffersize"
-const NodeComputeLocalPublisher = "node.compute.localpublisher"
-const NodeComputeLocalPublisherAddress = "node.compute.localpublisher.address"
-const NodeComputeLocalPublisherPort = "node.compute.localpublisher.port"
-const NodeComputeLocalPublisherDirectory = "node.compute.localpublisher.directory"
-const NodeComputeControlPlaneSettings = "node.compute.controlplanesettings"
-const NodeComputeControlPlaneSettingsInfoUpdateFrequency = "node.compute.controlplanesettings.infoupdatefrequency"
-const NodeComputeControlPlaneSettingsResourceUpdateFrequency = "node.compute.controlplanesettings.resourceupdatefrequency"
-const NodeComputeControlPlaneSettingsHeartbeatFrequency = "node.compute.controlplanesettings.heartbeatfrequency"
-const NodeComputeControlPlaneSettingsHeartbeatTopic = "node.compute.controlplanesettings.heartbeattopic"
-const NodeRequester = "node.requester"
-const NodeRequesterJobDefaults = "node.requester.jobdefaults"
-const NodeRequesterJobDefaultsTotalTimeout = "node.requester.jobdefaults.totaltimeout"
-const NodeRequesterJobDefaultsExecutionTimeout = "node.requester.jobdefaults.executiontimeout"
-const NodeRequesterJobDefaultsQueueTimeout = "node.requester.jobdefaults.queuetimeout"
-const NodeRequesterExternalVerifierHook = "node.requester.externalverifierhook"
-const NodeRequesterJobSelectionPolicy = "node.requester.jobselectionpolicy"
-const NodeRequesterJobSelectionPolicyLocality = "node.requester.jobselectionpolicy.locality"
-const NodeRequesterJobSelectionPolicyRejectStatelessJobs = "node.requester.jobselectionpolicy.rejectstatelessjobs"
-const NodeRequesterJobSelectionPolicyAcceptNetworkedJobs = "node.requester.jobselectionpolicy.acceptnetworkedjobs"
-const NodeRequesterJobSelectionPolicyProbeHTTP = "node.requester.jobselectionpolicy.probehttp"
-const NodeRequesterJobSelectionPolicyProbeExec = "node.requester.jobselectionpolicy.probeexec"
-const NodeRequesterJobStore = "node.requester.jobstore"
-const NodeRequesterJobStoreType = "node.requester.jobstore.type"
-const NodeRequesterJobStorePath = "node.requester.jobstore.path"
-const NodeRequesterHousekeepingBackgroundTaskInterval = "node.requester.housekeepingbackgroundtaskinterval"
-const NodeRequesterNodeRankRandomnessRange = "node.requester.noderankrandomnessrange"
-const NodeRequesterOverAskForBidsFactor = "node.requester.overaskforbidsfactor"
-const NodeRequesterFailureInjectionConfig = "node.requester.failureinjectionconfig"
-const NodeRequesterFailureInjectionConfigIsBadActor = "node.requester.failureinjectionconfig.isbadactor"
-const NodeRequesterTranslationEnabled = "node.requester.translationenabled"
-const NodeRequesterEvaluationBroker = "node.requester.evaluationbroker"
-const NodeRequesterEvaluationBrokerEvalBrokerVisibilityTimeout = "node.requester.evaluationbroker.evalbrokervisibilitytimeout"
-const NodeRequesterEvaluationBrokerEvalBrokerInitialRetryDelay = "node.requester.evaluationbroker.evalbrokerinitialretrydelay"
-const NodeRequesterEvaluationBrokerEvalBrokerSubsequentRetryDelay = "node.requester.evaluationbroker.evalbrokersubsequentretrydelay"
-const NodeRequesterEvaluationBrokerEvalBrokerMaxRetryCount = "node.requester.evaluationbroker.evalbrokermaxretrycount"
-const NodeRequesterWorker = "node.requester.worker"
-const NodeRequesterWorkerWorkerCount = "node.requester.worker.workercount"
-const NodeRequesterWorkerWorkerEvalDequeueTimeout = "node.requester.worker.workerevaldequeuetimeout"
-const NodeRequesterWorkerWorkerEvalDequeueBaseBackoff = "node.requester.worker.workerevaldequeuebasebackoff"
-const NodeRequesterWorkerWorkerEvalDequeueMaxBackoff = "node.requester.worker.workerevaldequeuemaxbackoff"
-const NodeRequesterScheduler = "node.requester.scheduler"
-const NodeRequesterSchedulerQueueBackoff = "node.requester.scheduler.queuebackoff"
-const NodeRequesterSchedulerNodeOverSubscriptionFactor = "node.requester.scheduler.nodeoversubscriptionfactor"
-const NodeRequesterStorageProvider = "node.requester.storageprovider"
-const NodeRequesterStorageProviderS3 = "node.requester.storageprovider.s3"
-const NodeRequesterStorageProviderS3PreSignedURLDisabled = "node.requester.storageprovider.s3.presignedurldisabled"
-const NodeRequesterStorageProviderS3PreSignedURLExpiration = "node.requester.storageprovider.s3.presignedurlexpiration"
-const NodeRequesterTagCache = "node.requester.tagcache"
-const NodeRequesterTagCacheSize = "node.requester.tagcache.size"
-const NodeRequesterTagCacheDuration = "node.requester.tagcache.duration"
-const NodeRequesterTagCacheFrequency = "node.requester.tagcache.frequency"
-const NodeRequesterDefaultPublisher = "node.requester.defaultpublisher"
-const NodeRequesterControlPlaneSettings = "node.requester.controlplanesettings"
-const NodeRequesterControlPlaneSettingsHeartbeatCheckFrequency = "node.requester.controlplanesettings.heartbeatcheckfrequency"
-const NodeRequesterControlPlaneSettingsHeartbeatTopic = "node.requester.controlplanesettings.heartbeattopic"
-const NodeRequesterControlPlaneSettingsNodeDisconnectedAfter = "node.requester.controlplanesettings.nodedisconnectedafter"
-const NodeRequesterNodeInfoStoreTTL = "node.requester.nodeinfostorettl"
-const NodeRequesterManualNodeApproval = "node.requester.manualnodeapproval"
-const NodeDownloadURLRequestRetries = "node.downloadurlrequestretries"
-const NodeDownloadURLRequestTimeout = "node.downloadurlrequesttimeout"
-const NodeVolumeSizeRequestTimeout = "node.volumesizerequesttimeout"
-const NodeExecutorPluginPath = "node.executorpluginpath"
-const NodeComputeStoragePath = "node.computestoragepath"
-const NodeLoggingMode = "node.loggingmode"
-const NodeType = "node.type"
-const NodeAllowListedLocalPaths = "node.allowlistedlocalpaths"
-const NodeDisabledFeatures = "node.disabledfeatures"
-const NodeDisabledFeaturesEngines = "node.disabledfeatures.engines"
-const NodeDisabledFeaturesPublishers = "node.disabledfeatures.publishers"
-const NodeDisabledFeaturesStorages = "node.disabledfeatures.storages"
-const NodeLabels = "node.labels"
-const NodeWebUI = "node.webui"
-const NodeWebUIEnabled = "node.webui.enabled"
-const NodeWebUIPort = "node.webui.port"
-const NodeNetwork = "node.network"
-const NodeNetworkPort = "node.network.port"
-const NodeNetworkAdvertisedAddress = "node.network.advertisedaddress"
-const NodeNetworkAuthSecret = "node.network.authsecret"
-const NodeNetworkOrchestrators = "node.network.orchestrators"
-const NodeNetworkStoreDir = "node.network.storedir"
-const NodeNetworkCluster = "node.network.cluster"
-const NodeNetworkClusterName = "node.network.cluster.name"
-const NodeNetworkClusterPort = "node.network.cluster.port"
-const NodeNetworkClusterAdvertisedAddress = "node.network.cluster.advertisedaddress"
-const NodeNetworkClusterPeers = "node.network.cluster.peers"
-const NodeStrictVersionMatch = "node.strictversionmatch"
-const User = "user"
-const UserKeyPath = "user.keypath"
-const UserInstallationID = "user.installationid"
-const Metrics = "metrics"
-const MetricsEventTracerPath = "metrics.eventtracerpath"
-const Update = "update"
-const UpdateSkipChecks = "update.skipchecks"
-const UpdateCheckFrequency = "update.checkfrequency"
-const Auth = "auth"
-const AuthTokensPath = "auth.tokenspath"
-const AuthMethods = "auth.methods"
-const AuthAccessPolicyPath = "auth.accesspolicypath"
+const APIHostKey = "api.host"
+const APIPortKey = "api.port"
+const APITLSCertFileKey = "api.tls.certfile"
+const APITLSKeyFileKey = "api.tls.keyfile"
+const APITLSCAFileKey = "api.tls.cafile"
+const APITLSUseTLSKey = "api.tls.usetls"
+const APITLSInsecureKey = "api.tls.insecure"
+const APITLSSelfSignedKey = "api.tls.selfsigned"
+const APITLSAutoCertKey = "api.tls.autocert"
+const APITLSAutoCertCachePathKey = "api.tls.autocertcachepath"
+const APIAuthMethodsKey = "api.auth.methods"
+const APIAuthAccessPolicyPathKey = "api.auth.accesspolicypath"
+const NameProviderKey = "nameprovider"
+const DataDirKey = "datadir"
+const StrictVersionMatchKey = "strictversionmatch"
+const OrchestratorEnabledKey = "orchestrator.enabled"
+const OrchestratorHostKey = "orchestrator.host"
+const OrchestratorPortKey = "orchestrator.port"
+const OrchestratorAdvertiseKey = "orchestrator.advertise"
+const OrchestratorAuthSecretKey = "orchestrator.authsecret"
+const OrchestratorTLSCertFileKey = "orchestrator.tls.certfile"
+const OrchestratorTLSKeyFileKey = "orchestrator.tls.keyfile"
+const OrchestratorTLSCAFileKey = "orchestrator.tls.cafile"
+const OrchestratorTLSUseTLSKey = "orchestrator.tls.usetls"
+const OrchestratorTLSInsecureKey = "orchestrator.tls.insecure"
+const OrchestratorTLSSelfSignedKey = "orchestrator.tls.selfsigned"
+const OrchestratorTLSAutoCertKey = "orchestrator.tls.autocert"
+const OrchestratorTLSAutoCertCachePathKey = "orchestrator.tls.autocertcachepath"
+const OrchestratorClusterNameKey = "orchestrator.cluster.name"
+const OrchestratorClusterHostKey = "orchestrator.cluster.host"
+const OrchestratorClusterPortKey = "orchestrator.cluster.port"
+const OrchestratorClusterAdvertiseKey = "orchestrator.cluster.advertise"
+const OrchestratorClusterPeersKey = "orchestrator.cluster.peers"
+const OrchestratorNodeManagerDisconnectTimeoutKey = "orchestrator.nodemanager.disconnecttimeout"
+const OrchestratorNodeManagerManualApprovalKey = "orchestrator.nodemanager.manualapproval"
+const OrchestratorSchedulerWorkerCountKey = "orchestrator.scheduler.workercount"
+const OrchestratorSchedulerHousekeepingIntervalKey = "orchestrator.scheduler.housekeepinginterval"
+const OrchestratorSchedulerHousekeepingTimeoutKey = "orchestrator.scheduler.housekeepingtimeout"
+const OrchestratorEvaluationBrokerVisibilityTimeoutKey = "orchestrator.evaluationbroker.visibilitytimeout"
+const OrchestratorEvaluationBrokerMaxRetryCountKey = "orchestrator.evaluationbroker.maxretrycount"
+const ComputeEnabledKey = "compute.enabled"
+const ComputeOrchestratorsKey = "compute.orchestrators"
+const ComputeTLSCertFileKey = "compute.tls.certfile"
+const ComputeTLSKeyFileKey = "compute.tls.keyfile"
+const ComputeTLSCAFileKey = "compute.tls.cafile"
+const ComputeTLSUseTLSKey = "compute.tls.usetls"
+const ComputeTLSInsecureKey = "compute.tls.insecure"
+const ComputeTLSSelfSignedKey = "compute.tls.selfsigned"
+const ComputeTLSAutoCertKey = "compute.tls.autocert"
+const ComputeTLSAutoCertCachePathKey = "compute.tls.autocertcachepath"
+const ComputeHeartbeatInfoUpdateIntervalKey = "compute.heartbeat.infoupdateinterval"
+const ComputeHeartbeatResourceUpdateIntervalKey = "compute.heartbeat.resourceupdateinterval"
+const ComputeHeartbeatIntervalKey = "compute.heartbeat.interval"
+const ComputeLabelsKey = "compute.labels"
+const ComputeAllocatedCapacityCPUKey = "compute.allocatedcapacity.cpu"
+const ComputeAllocatedCapacityMemoryKey = "compute.allocatedcapacity.memory"
+const ComputeAllocatedCapacityDiskKey = "compute.allocatedcapacity.disk"
+const ComputeAllocatedCapacityGPUKey = "compute.allocatedcapacity.gpu"
+const ComputeAllowListedLocalPathsKey = "compute.allowlistedlocalpaths"
+const WebUIEnabledKey = "webui.enabled"
+const WebUIListenKey = "webui.listen"
+const InputSourcesDisabledKey = "inputsources.disabled"
+const InputSourcesReadTimeoutKey = "inputsources.readtimeout"
+const InputSourcesMaxRetryCountKey = "inputsources.maxretrycount"
+const InputSourcesTypesIPFSEndpointKey = "inputsources.types.ipfs.endpoint"
+const InputSourcesTypesS3EndpointKey = "inputsources.types.s3.endpoint"
+const InputSourcesTypesS3AccessKeyKey = "inputsources.types.s3.accesskey"
+const InputSourcesTypesS3SecretKeyKey = "inputsources.types.s3.secretkey"
+const PublishersDisabledKey = "publishers.disabled"
+const PublishersTypesIPFSEndpointKey = "publishers.types.ipfs.endpoint"
+const PublishersTypesS3PreSignedURLDisabledKey = "publishers.types.s3.presignedurldisabled"
+const PublishersTypesS3PreSignedURLExpirationKey = "publishers.types.s3.presignedurlexpiration"
+const PublishersTypesLocalAddressKey = "publishers.types.local.address"
+const PublishersTypesLocalPortKey = "publishers.types.local.port"
+const PublishersTypesLocalDirectoryKey = "publishers.types.local.directory"
+const EnginesDisabledKey = "engines.disabled"
+const EnginesTypesDockerManifestCacheSizeKey = "engines.types.docker.manifestcache.size"
+const EnginesTypesDockerManifestCacheTTLKey = "engines.types.docker.manifestcache.ttl"
+const EnginesTypesDockerManifestCacheRefreshKey = "engines.types.docker.manifestcache.refresh"
+const ResultDownloadersDisabledKey = "resultdownloaders.disabled"
+const ResultDownloadersTimeoutKey = "resultdownloaders.timeout"
+const ResultDownloadersTypesIPFSEndpointKey = "resultdownloaders.types.ipfs.endpoint"
+const JobDefaultsBatchPriorityKey = "jobdefaults.batch.priority"
+const JobDefaultsBatchTaskResourcesCPUKey = "jobdefaults.batch.task.resources.cpu"
+const JobDefaultsBatchTaskResourcesMemoryKey = "jobdefaults.batch.task.resources.memory"
+const JobDefaultsBatchTaskResourcesDiskKey = "jobdefaults.batch.task.resources.disk"
+const JobDefaultsBatchTaskResourcesGPUKey = "jobdefaults.batch.task.resources.gpu"
+const JobDefaultsBatchTaskPublisherConfigTypeKey = "jobdefaults.batch.task.publisher.config.type"
+const JobDefaultsBatchTaskPublisherConfigParamsKey = "jobdefaults.batch.task.publisher.config.params"
+const JobDefaultsBatchTaskTimeoutsTotalTimeoutKey = "jobdefaults.batch.task.timeouts.totaltimeout"
+const JobDefaultsBatchTaskTimeoutsExecutionTimeoutKey = "jobdefaults.batch.task.timeouts.executiontimeout"
+const JobDefaultsOpsPriorityKey = "jobdefaults.ops.priority"
+const JobDefaultsOpsTaskResourcesCPUKey = "jobdefaults.ops.task.resources.cpu"
+const JobDefaultsOpsTaskResourcesMemoryKey = "jobdefaults.ops.task.resources.memory"
+const JobDefaultsOpsTaskResourcesDiskKey = "jobdefaults.ops.task.resources.disk"
+const JobDefaultsOpsTaskResourcesGPUKey = "jobdefaults.ops.task.resources.gpu"
+const JobDefaultsOpsTaskPublisherConfigTypeKey = "jobdefaults.ops.task.publisher.config.type"
+const JobDefaultsOpsTaskPublisherConfigParamsKey = "jobdefaults.ops.task.publisher.config.params"
+const JobDefaultsOpsTaskTimeoutsTotalTimeoutKey = "jobdefaults.ops.task.timeouts.totaltimeout"
+const JobDefaultsOpsTaskTimeoutsExecutionTimeoutKey = "jobdefaults.ops.task.timeouts.executiontimeout"
+const JobDefaultsDaemonPriorityKey = "jobdefaults.daemon.priority"
+const JobDefaultsDaemonTaskResourcesCPUKey = "jobdefaults.daemon.task.resources.cpu"
+const JobDefaultsDaemonTaskResourcesMemoryKey = "jobdefaults.daemon.task.resources.memory"
+const JobDefaultsDaemonTaskResourcesDiskKey = "jobdefaults.daemon.task.resources.disk"
+const JobDefaultsDaemonTaskResourcesGPUKey = "jobdefaults.daemon.task.resources.gpu"
+const JobDefaultsServicePriorityKey = "jobdefaults.service.priority"
+const JobDefaultsServiceTaskResourcesCPUKey = "jobdefaults.service.task.resources.cpu"
+const JobDefaultsServiceTaskResourcesMemoryKey = "jobdefaults.service.task.resources.memory"
+const JobDefaultsServiceTaskResourcesDiskKey = "jobdefaults.service.task.resources.disk"
+const JobDefaultsServiceTaskResourcesGPUKey = "jobdefaults.service.task.resources.gpu"
+const JobAdmissionControlRejectStatelessJobsKey = "jobadmissioncontrol.rejectstatelessjobs"
+const JobAdmissionControlAcceptNetworkedJobsKey = "jobadmissioncontrol.acceptnetworkedjobs"
+const JobAdmissionControlProbeHTTPKey = "jobadmissioncontrol.probehttp"
+const JobAdmissionControlProbeExecKey = "jobadmissioncontrol.probeexec"
+const LoggingLevelKey = "logging.level"
+const LoggingModeKey = "logging.mode"
+const LoggingLogDebugInfoIntervalKey = "logging.logdebuginfointerval"
+const UpdateConfigIntervalKey = "updateconfig.interval"
+const FeatureFlagsExecTranslationKey = "featureflags.exectranslation"
diff --git a/pkg/config/types/generated_descriptions.go b/pkg/config/types/generated_descriptions.go
index 1c30380923..00ad539fe5 100644
--- a/pkg/config/types/generated_descriptions.go
+++ b/pkg/config/types/generated_descriptions.go
@@ -4,133 +4,123 @@ package types
 
 // ConfigDescriptions maps configuration paths to their descriptions
 var ConfigDescriptions = map[string]string{
-	NodeName: "No description available",
-	NodeNameProvider: "No description available",
-	NodeClientAPIHost: "Host is the hostname of an environment's public API servers.",
-	NodeClientAPIPort: "Port is the port that an environment serves the public API on.",
-	NodeClientAPIClientTLSUseTLS: "Used for NodeConfig.ClientAPI, instructs the client to connect over TLS.  Auto enabled if Insecure or CACert are specified.",
-	NodeClientAPIClientTLSCACert: "Used for NodeConfig.ClientAPI, specifies the location of a ca certificate file (primarily for self-signed server certs). Will use HTTPS for requests.",
-	NodeClientAPIClientTLSInsecure: "Used for NodeConfig.ClientAPI, and when true instructs the client to use HTTPS, but not to attempt to verify the certificate.",
-	NodeClientAPITLSAutoCert: "AutoCert specifies a hostname for a certificate to be obtained via ACME. This is only used by the server, and only by the requester node when it has a publicly resolvable domain name.",
-	NodeClientAPITLSAutoCertCachePath: "AutoCertCachePath specifies the directory where the autocert process will cache certificates to avoid rate limits.",
-	NodeClientAPITLSServerCertificate: "ServerCertificate specifies the location of a TLS certificate to be used by the requester to serve TLS requests",
-	NodeClientAPITLSServerKey: "ServerKey is the TLS server key to match the certificate to allow the requester to server TLS.",
-	NodeClientAPITLSSelfSigned: "SelfSignedCert will auto-generate a self-signed certificate for the requester node if TLS certificates have not been provided.",
-	NodeServerAPIHost: "Host is the hostname of an environment's public API servers.",
-	NodeServerAPIPort: "Port is the port that an environment serves the public API on.",
-	NodeServerAPIClientTLSUseTLS: "Used for NodeConfig.ClientAPI, instructs the client to connect over TLS.  Auto enabled if Insecure or CACert are specified.",
-	NodeServerAPIClientTLSCACert: "Used for NodeConfig.ClientAPI, specifies the location of a ca certificate file (primarily for self-signed server certs). Will use HTTPS for requests.",
-	NodeServerAPIClientTLSInsecure: "Used for NodeConfig.ClientAPI, and when true instructs the client to use HTTPS, but not to attempt to verify the certificate.",
-	NodeServerAPITLSAutoCert: "AutoCert specifies a hostname for a certificate to be obtained via ACME. This is only used by the server, and only by the requester node when it has a publicly resolvable domain name.",
-	NodeServerAPITLSAutoCertCachePath: "AutoCertCachePath specifies the directory where the autocert process will cache certificates to avoid rate limits.",
-	NodeServerAPITLSServerCertificate: "ServerCertificate specifies the location of a TLS certificate to be used by the requester to serve TLS requests",
-	NodeServerAPITLSServerKey: "ServerKey is the TLS server key to match the certificate to allow the requester to server TLS.",
-	NodeServerAPITLSSelfSigned: "SelfSignedCert will auto-generate a self-signed certificate for the requester node if TLS certificates have not been provided.",
-	NodeIPFSConnect: "Connect is the multiaddress to connect to for IPFS.",
-	NodeComputeCapacityIgnorePhysicalResourceLimits: "No description available",
-	NodeComputeCapacityTotalResourceLimitsCPU: "No description available",
-	NodeComputeCapacityTotalResourceLimitsMemory: "No description available",
-	NodeComputeCapacityTotalResourceLimitsDisk: "No description available",
-	NodeComputeCapacityTotalResourceLimitsGPU: "No description available",
-	NodeComputeCapacityJobResourceLimitsCPU: "No description available",
-	NodeComputeCapacityJobResourceLimitsMemory: "No description available",
-	NodeComputeCapacityJobResourceLimitsDisk: "No description available",
-	NodeComputeCapacityJobResourceLimitsGPU: "No description available",
-	NodeComputeCapacityDefaultJobResourceLimitsCPU: "No description available",
-	NodeComputeCapacityDefaultJobResourceLimitsMemory: "No description available",
-	NodeComputeCapacityDefaultJobResourceLimitsDisk: "No description available",
-	NodeComputeCapacityDefaultJobResourceLimitsGPU: "No description available",
-	NodeComputeExecutionStoreType: "Type is \"compute\", \"requester\" or both",
-	NodeComputeExecutionStorePath: "No description available",
-	NodeComputeJobTimeoutsJobExecutionTimeoutClientIDBypassList: "JobExecutionTimeoutClientIDBypassList is the list of clients that are allowed to bypass the job execution timeout check.",
-	NodeComputeJobTimeoutsJobNegotiationTimeout: "JobNegotiationTimeout default timeout value to hold a bid for a job",
-	NodeComputeJobTimeoutsMinJobExecutionTimeout: "MinJobExecutionTimeout default value for the minimum execution timeout this compute node supports. Jobs with lower timeout requirements will not be bid on.",
-	NodeComputeJobTimeoutsMaxJobExecutionTimeout: "MaxJobExecutionTimeout default value for the maximum execution timeout this compute node supports. Jobs with higher timeout requirements will not be bid on.",
-	NodeComputeJobTimeoutsDefaultJobExecutionTimeout: "DefaultJobExecutionTimeout default value for the execution timeout this compute node will assign to jobs with no timeout requirement defined.",
-	NodeComputeJobSelectionLocality: "No description available",
-	NodeComputeJobSelectionRejectStatelessJobs: "No description available",
-	NodeComputeJobSelectionAcceptNetworkedJobs: "No description available",
-	NodeComputeJobSelectionProbeHTTP: "No description available",
-	NodeComputeJobSelectionProbeExec: "No description available",
-	NodeComputeLoggingLogRunningExecutionsInterval: "logging running executions",
-	NodeComputeManifestCacheSize: "No description available",
-	NodeComputeManifestCacheDuration: "No description available",
-	NodeComputeManifestCacheFrequency: "No description available",
-	NodeComputeLogStreamConfigChannelBufferSize: "How many messages to buffer in the log stream channel, per stream",
-	NodeComputeLocalPublisherAddress: "No description available",
-	NodeComputeLocalPublisherPort: "Port is the port that an environment serves the public API on.",
-	NodeComputeLocalPublisherDirectory: "No description available",
-	NodeComputeControlPlaneSettingsInfoUpdateFrequency: "The frequency with which the compute node will send node info (inc current labels) to the controlling requester node.",
-	NodeComputeControlPlaneSettingsResourceUpdateFrequency: "How often the compute node will send current resource availability to the requester node.",
-	NodeComputeControlPlaneSettingsHeartbeatFrequency: "How often the compute node will send a heartbeat to the requester node to let it know that the compute node is still alive. This should be less than the requester's configured heartbeat timeout to avoid flapping.",
-	NodeComputeControlPlaneSettingsHeartbeatTopic: "This is the pubsub topic that the compute node will use to send heartbeats to the requester node.",
-	NodeRequesterJobDefaultsTotalTimeout: "No description available",
-	NodeRequesterJobDefaultsExecutionTimeout: "No description available",
-	NodeRequesterJobDefaultsQueueTimeout: "No description available",
-	NodeRequesterExternalVerifierHook: "URL where to send external verification requests to.",
-	NodeRequesterJobSelectionPolicyLocality: "No description available",
-	NodeRequesterJobSelectionPolicyRejectStatelessJobs: "No description available",
-	NodeRequesterJobSelectionPolicyAcceptNetworkedJobs: "No description available",
-	NodeRequesterJobSelectionPolicyProbeHTTP: "No description available",
-	NodeRequesterJobSelectionPolicyProbeExec: "No description available",
-	NodeRequesterJobStoreType: "Type is \"compute\", \"requester\" or both",
-	NodeRequesterJobStorePath: "No description available",
-	NodeRequesterHousekeepingBackgroundTaskInterval: "No description available",
-	NodeRequesterNodeRankRandomnessRange: "No description available",
-	NodeRequesterOverAskForBidsFactor: "No description available",
-	NodeRequesterFailureInjectionConfigIsBadActor: "No description available",
-	NodeRequesterTranslationEnabled: "No description available",
-	NodeRequesterEvaluationBrokerEvalBrokerVisibilityTimeout: "No description available",
-	NodeRequesterEvaluationBrokerEvalBrokerInitialRetryDelay: "No description available",
-	NodeRequesterEvaluationBrokerEvalBrokerSubsequentRetryDelay: "No description available",
-	NodeRequesterEvaluationBrokerEvalBrokerMaxRetryCount: "No description available",
-	NodeRequesterWorkerWorkerCount: "No description available",
-	NodeRequesterWorkerWorkerEvalDequeueTimeout: "No description available",
-	NodeRequesterWorkerWorkerEvalDequeueBaseBackoff: "No description available",
-	NodeRequesterWorkerWorkerEvalDequeueMaxBackoff: "No description available",
-	NodeRequesterSchedulerQueueBackoff: "No description available",
-	NodeRequesterSchedulerNodeOverSubscriptionFactor: "No description available",
-	NodeRequesterStorageProviderS3PreSignedURLDisabled: "No description available",
-	NodeRequesterStorageProviderS3PreSignedURLExpiration: "No description available",
-	NodeRequesterTagCacheSize: "No description available",
-	NodeRequesterTagCacheDuration: "No description available",
-	NodeRequesterTagCacheFrequency: "No description available",
-	NodeRequesterDefaultPublisher: "No description available",
-	NodeRequesterControlPlaneSettingsHeartbeatCheckFrequency: "This setting is the time period after which a compute node is considered to be unresponsive. If the compute node misses two of these frequencies, it will be marked as unknown.  The compute node should have a frequency setting less than this one to ensure that it does not keep switching between unknown and active too frequently.",
-	NodeRequesterControlPlaneSettingsHeartbeatTopic: "This is the pubsub topic that the compute node will use to send heartbeats to the requester node.",
-	NodeRequesterControlPlaneSettingsNodeDisconnectedAfter: "This is the time period after which a compute node is considered to be disconnected. If the compute node does not deliver a heartbeat every `NodeDisconnectedAfter` then it is considered disconnected.",
-	NodeRequesterNodeInfoStoreTTL: "No description available",
-	NodeRequesterManualNodeApproval: "ManualNodeApproval is a flag that determines if nodes should be manually approved or not. By default, nodes are auto-approved to simplify upgrades, by setting this property to true, nodes will need to be manually approved before they are included in node selection.",
-	NodeDownloadURLRequestRetries: "No description available",
-	NodeDownloadURLRequestTimeout: "No description available",
-	NodeVolumeSizeRequestTimeout: "No description available",
-	NodeExecutorPluginPath: "No description available",
-	NodeComputeStoragePath: "TODO(forrest) [refactor]: rename this to ExecutorStoragePath",
-	NodeLoggingMode: "No description available",
-	NodeType: "Type is \"compute\", \"requester\" or both",
-	NodeAllowListedLocalPaths: "AllowListedLocalPaths contains local paths that are allowed to be mounted into jobs",
-	NodeDisabledFeaturesEngines: "No description available",
-	NodeDisabledFeaturesPublishers: "No description available",
-	NodeDisabledFeaturesStorages: "No description available",
-	NodeLabels: "Labels to apply to the node that can be used for node selection and filtering",
-	NodeWebUIEnabled: "No description available",
-	NodeWebUIPort: "Port is the port that an environment serves the public API on.",
-	NodeNetworkPort: "Port is the port that an environment serves the public API on.",
-	NodeNetworkAdvertisedAddress: "No description available",
-	NodeNetworkAuthSecret: "No description available",
-	NodeNetworkOrchestrators: "No description available",
-	NodeNetworkStoreDir: "No description available",
-	NodeNetworkClusterName: "No description available",
-	NodeNetworkClusterPort: "Port is the port that an environment serves the public API on.",
-	NodeNetworkClusterAdvertisedAddress: "No description available",
-	NodeNetworkClusterPeers: "No description available",
-	NodeStrictVersionMatch: "No description available",
-	UserKeyPath: "No description available",
-	UserInstallationID: "No description available",
-	MetricsEventTracerPath: "No description available",
-	UpdateSkipChecks: "No description available",
-	UpdateCheckFrequency: "No description available",
-	AuthTokensPath: "TokensPath is the location where a state file of tokens will be stored. By default it will be local to the Bacalhau repo, but can be any location in the host filesystem. Tokens are sensitive and should be stored in a location that is only readable to the current user.",
-	AuthMethods: "Methods maps \"method names\" to authenticator implementations. A method name is a human-readable string chosen by the person configuring the system that is shown to users to help them pick the authentication method they want to use. There can be multiple usages of the same Authenticator *type* but with different configs and parameters, each identified with a unique method name.  For example, if an implementation wants to allow users to log in with Github or Bitbucket, they might both use an authenticator implementation of type \"oidc\", and each would appear once on this provider with key / method name \"github\" and \"bitbucket\".  By default, only a single authentication method that accepts authentication via client keys will be enabled.",
-	AuthAccessPolicyPath: "AccessPolicyPath is the path to a file or directory that will be loaded as the policy to apply to all inbound API requests. If unspecified, a policy that permits access to all API endpoints to both authenticated and unauthenticated users (the default as of v1.2.0) will be used.",
+	APIHostKey:                                       "Host specifies the hostname or IP address for cluster communication.",
+	APIPortKey:                                       "Port specifies the port number for cluster communication.",
+	APITLSCertFileKey:                                "CertFile specifies the path to the TLS certificate file.",
+	APITLSKeyFileKey:                                 "KeyFile specifies the path to the TLS private key file.",
+	APITLSCAFileKey:                                  "CAFile specifies the path to the Certificate Authority file.",
+	APITLSUseTLSKey:                                  "UseTLS indicates whether to use TLS for client connections.",
+	APITLSInsecureKey:                                "Insecure allows insecure TLS connections (e.g., self-signed certificates).",
+	APITLSSelfSignedKey:                              "SelfSigned indicates whether to use a self-signed certificate.",
+	APITLSAutoCertKey:                                "AutoCert specifies the domain for automatic certificate generation.",
+	APITLSAutoCertCachePathKey:                       "AutoCertCachePath specifies the directory to cache auto-generated certificates.",
+	APIAuthMethodsKey:                                "Methods maps \"method names\" to authenticator implementations. A method name is a human-readable string chosen by the person configuring the system that is shown to users to help them pick the authentication method they want to use. There can be multiple usages of the same Authenticator *type* but with different configs and parameters, each identified with a unique method name.  For example, if an implementation wants to allow users to log in with Github or Bitbucket, they might both use an authenticator implementation of type \"oidc\", and each would appear once on this provider with key / method name \"github\" and \"bitbucket\".  By default, only a single authentication method that accepts authentication via client keys will be enabled.",
+	APIAuthAccessPolicyPathKey:                       "AccessPolicyPath is the path to a file or directory that will be loaded as the policy to apply to all inbound API requests. If unspecified, a policy that permits access to all API endpoints to both authenticated and unauthenticated users (the default as of v1.2.0) will be used.",
+	NameProviderKey:                                  "NameProvider specifies the method used to generate names for the node. One of: hostname, aws, gcp, uuid, puuid.",
+	DataDirKey:                                       "DataDir specifies a location on disk where the bacalhau node will maintain state.",
+	StrictVersionMatchKey:                            "StrictVersionMatch indicates whether to enforce strict version matching.",
+	OrchestratorEnabledKey:                           "Enabled indicates whether the orchestrator node is active and available for job submission.",
+	OrchestratorHostKey:                              "Host specifies the hostname or IP address for cluster communication.",
+	OrchestratorPortKey:                              "Port specifies the port number for cluster communication.",
+	OrchestratorAdvertiseKey:                         "Advertise specifies the address to advertise to other cluster members.",
+	OrchestratorAuthSecretKey:                        "AuthSecret key specifies the key used by compute nodes to connect to an orchestrator.",
+	OrchestratorTLSCertFileKey:                       "CertFile specifies the path to the TLS certificate file.",
+	OrchestratorTLSKeyFileKey:                        "KeyFile specifies the path to the TLS private key file.",
+	OrchestratorTLSCAFileKey:                         "CAFile specifies the path to the Certificate Authority file.",
+	OrchestratorTLSUseTLSKey:                         "UseTLS indicates whether to use TLS for client connections.",
+	OrchestratorTLSInsecureKey:                       "Insecure allows insecure TLS connections (e.g., self-signed certificates).",
+	OrchestratorTLSSelfSignedKey:                     "SelfSigned indicates whether to use a self-signed certificate.",
+	OrchestratorTLSAutoCertKey:                       "AutoCert specifies the domain for automatic certificate generation.",
+	OrchestratorTLSAutoCertCachePathKey:              "AutoCertCachePath specifies the directory to cache auto-generated certificates.",
+	OrchestratorClusterNameKey:                       "Name specifies the unique identifier for this orchestrator cluster.",
+	OrchestratorClusterHostKey:                       "Host specifies the hostname or IP address for cluster communication.",
+	OrchestratorClusterPortKey:                       "Port specifies the port number for cluster communication.",
+	OrchestratorClusterAdvertiseKey:                  "Advertise specifies the address to advertise to other cluster members.",
+	OrchestratorClusterPeersKey:                      "Peers is a list of other cluster members to connect to on startup.",
+	OrchestratorNodeManagerDisconnectTimeoutKey:      "DisconnectTimeout specifies how long to wait before considering a node disconnected.",
+	OrchestratorNodeManagerManualApprovalKey:         "ManualApproval, if true, requires manual approval for new compute nodes joining the cluster.",
+	OrchestratorSchedulerWorkerCountKey:              "WorkerCount specifies the number of concurrent workers for job scheduling.",
+	OrchestratorSchedulerHousekeepingIntervalKey:     "HousekeepingInterval specifies how often to run housekeeping tasks.",
+	OrchestratorSchedulerHousekeepingTimeoutKey:      "HousekeepingTimeout specifies the maximum time allowed for a single housekeeping run.",
+	OrchestratorEvaluationBrokerVisibilityTimeoutKey: "VisibilityTimeout specifies how long an evaluation can be claimed before it's returned to the queue.",
+	OrchestratorEvaluationBrokerMaxRetryCountKey:     "ReadTimeout specifies the maximum number of attempts for reading from a storage.",
+	ComputeEnabledKey:                                "Enabled indicates whether the orchestrator node is active and available for job submission.",
+	ComputeOrchestratorsKey:                          "Orchestrators specifies a list of orchestrator endpoints that this compute node connects to.",
+	ComputeTLSCertFileKey:                            "CertFile specifies the path to the TLS certificate file.",
+	ComputeTLSKeyFileKey:                             "KeyFile specifies the path to the TLS private key file.",
+	ComputeTLSCAFileKey:                              "CAFile specifies the path to the Certificate Authority file.",
+	ComputeTLSUseTLSKey:                              "UseTLS indicates whether to use TLS for client connections.",
+	ComputeTLSInsecureKey:                            "Insecure allows insecure TLS connections (e.g., self-signed certificates).",
+	ComputeTLSSelfSignedKey:                          "SelfSigned indicates whether to use a self-signed certificate.",
+	ComputeTLSAutoCertKey:                            "AutoCert specifies the domain for automatic certificate generation.",
+	ComputeTLSAutoCertCachePathKey:                   "AutoCertCachePath specifies the directory to cache auto-generated certificates.",
+	ComputeHeartbeatInfoUpdateIntervalKey:            "InfoUpdateInterval specifies the time between updates of non-resource information to the orchestrator.",
+	ComputeHeartbeatResourceUpdateIntervalKey:        "ResourceUpdateInterval specifies the time between updates of resource information to the orchestrator.",
+	ComputeHeartbeatIntervalKey:                      "Interval specifies the time between update checks, when set to 0 update checks are not performed.",
+	ComputeLabelsKey:                                 "Labels are key-value pairs used to describe and categorize the compute node.",
+	ComputeAllocatedCapacityCPUKey:                   "CPU specifies the amount of CPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"100m\").",
+	ComputeAllocatedCapacityMemoryKey:                "Memory specifies the amount of Memory a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1Gi\").",
+	ComputeAllocatedCapacityDiskKey:                  "Disk specifies the amount of Disk space a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"10Gi\").",
+	ComputeAllocatedCapacityGPUKey:                   "GPU specifies the amount of GPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1\"). Note: When using percentages, the result is always rounded up to the nearest whole GPU.",
+	ComputeAllowListedLocalPathsKey:                  "AllowListedLocalPaths specifies a list of local file system paths that the compute node is allowed to access.",
+	WebUIEnabledKey:                                  "Enabled indicates whether the orchestrator node is active and available for job submission.",
+	WebUIListenKey:                                   "Listen specifies the address and port on which the Web UI listens.",
+	InputSourcesDisabledKey:                          "Disabled specifies a list of storages that are disabled.",
+	InputSourcesReadTimeoutKey:                       "ReadTimeout specifies the maximum time allowed for reading from a storage.",
+	InputSourcesMaxRetryCountKey:                     "ReadTimeout specifies the maximum number of attempts for reading from a storage.",
+	InputSourcesTypesIPFSEndpointKey:                 "Endpoint specifies the endpoint URL for the S3 input source.",
+	InputSourcesTypesS3EndpointKey:                   "Endpoint specifies the endpoint URL for the S3 input source.",
+	InputSourcesTypesS3AccessKeyKey:                  "AccessKey specifies the access key for the S3 input source.",
+	InputSourcesTypesS3SecretKeyKey:                  "SecretKey specifies the secret key for the S3 input source.",
+	PublishersDisabledKey:                            "Disabled specifies a list of storages that are disabled.",
+	PublishersTypesIPFSEndpointKey:                   "Endpoint specifies the endpoint URL for the S3 input source.",
+	PublishersTypesS3PreSignedURLDisabledKey:         "PreSignedURLDisabled specifies whether pre-signed URLs are enabled for the S3 provider.",
+	PublishersTypesS3PreSignedURLExpirationKey:       "PreSignedURLExpiration specifies the duration before a pre-signed URL expires.",
+	PublishersTypesLocalAddressKey:                   "Address specifies the endpoint the publisher serves on.",
+	PublishersTypesLocalPortKey:                      "Port specifies the port number for cluster communication.",
+	PublishersTypesLocalDirectoryKey:                 "Directory specifies a path to location on disk where content is served from.",
+	EnginesDisabledKey:                               "Disabled specifies a list of storages that are disabled.",
+	EnginesTypesDockerManifestCacheSizeKey:           "Size specifies the size of the Docker manifest cache.",
+	EnginesTypesDockerManifestCacheTTLKey:            "TTL specifies the time-to-live duration for cache entries.",
+	EnginesTypesDockerManifestCacheRefreshKey:        "Refresh specifies the refresh interval for cache entries.",
+	ResultDownloadersDisabledKey:                     "Disabled specifies a list of storages that are disabled.",
+	ResultDownloadersTimeoutKey:                      "Timeout specifies the maximum time allowed for a download operation.",
+	ResultDownloadersTypesIPFSEndpointKey:            "Endpoint specifies the endpoint URL for the S3 input source.",
+	JobDefaultsBatchPriorityKey:                      "Priority specifies the default priority allocated to a service or daemon job. This value is used when the job hasn't explicitly set its priority requirement.",
+	JobDefaultsBatchTaskResourcesCPUKey:              "CPU specifies the amount of CPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"100m\").",
+	JobDefaultsBatchTaskResourcesMemoryKey:           "Memory specifies the amount of Memory a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1Gi\").",
+	JobDefaultsBatchTaskResourcesDiskKey:             "Disk specifies the amount of Disk space a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"10Gi\").",
+	JobDefaultsBatchTaskResourcesGPUKey:              "GPU specifies the amount of GPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1\"). Note: When using percentages, the result is always rounded up to the nearest whole GPU.",
+	JobDefaultsBatchTaskPublisherConfigTypeKey:       "No description available",
+	JobDefaultsBatchTaskPublisherConfigParamsKey:     "No description available",
+	JobDefaultsBatchTaskTimeoutsTotalTimeoutKey:      "TotalTimeout is the maximum total time allowed for a task",
+	JobDefaultsBatchTaskTimeoutsExecutionTimeoutKey:  "ExecutionTimeout is the maximum time allowed for task execution",
+	JobDefaultsOpsPriorityKey:                        "Priority specifies the default priority allocated to a service or daemon job. This value is used when the job hasn't explicitly set its priority requirement.",
+	JobDefaultsOpsTaskResourcesCPUKey:                "CPU specifies the amount of CPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"100m\").",
+	JobDefaultsOpsTaskResourcesMemoryKey:             "Memory specifies the amount of Memory a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1Gi\").",
+	JobDefaultsOpsTaskResourcesDiskKey:               "Disk specifies the amount of Disk space a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"10Gi\").",
+	JobDefaultsOpsTaskResourcesGPUKey:                "GPU specifies the amount of GPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1\"). Note: When using percentages, the result is always rounded up to the nearest whole GPU.",
+	JobDefaultsOpsTaskPublisherConfigTypeKey:         "No description available",
+	JobDefaultsOpsTaskPublisherConfigParamsKey:       "No description available",
+	JobDefaultsOpsTaskTimeoutsTotalTimeoutKey:        "TotalTimeout is the maximum total time allowed for a task",
+	JobDefaultsOpsTaskTimeoutsExecutionTimeoutKey:    "ExecutionTimeout is the maximum time allowed for task execution",
+	JobDefaultsDaemonPriorityKey:                     "Priority specifies the default priority allocated to a service or daemon job. This value is used when the job hasn't explicitly set its priority requirement.",
+	JobDefaultsDaemonTaskResourcesCPUKey:             "CPU specifies the amount of CPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"100m\").",
+	JobDefaultsDaemonTaskResourcesMemoryKey:          "Memory specifies the amount of Memory a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1Gi\").",
+	JobDefaultsDaemonTaskResourcesDiskKey:            "Disk specifies the amount of Disk space a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"10Gi\").",
+	JobDefaultsDaemonTaskResourcesGPUKey:             "GPU specifies the amount of GPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1\"). Note: When using percentages, the result is always rounded up to the nearest whole GPU.",
+	JobDefaultsServicePriorityKey:                    "Priority specifies the default priority allocated to a service or daemon job. This value is used when the job hasn't explicitly set its priority requirement.",
+	JobDefaultsServiceTaskResourcesCPUKey:            "CPU specifies the amount of CPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"100m\").",
+	JobDefaultsServiceTaskResourcesMemoryKey:         "Memory specifies the amount of Memory a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1Gi\").",
+	JobDefaultsServiceTaskResourcesDiskKey:           "Disk specifies the amount of Disk space a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"10Gi\").",
+	JobDefaultsServiceTaskResourcesGPUKey:            "GPU specifies the amount of GPU a compute node allocates for running jobs. It can be expressed as a percentage (e.g., \"85%\") or a Kubernetes resource string (e.g., \"1\"). Note: When using percentages, the result is always rounded up to the nearest whole GPU.",
+	JobAdmissionControlRejectStatelessJobsKey:        "RejectStatelessJobs indicates whether to reject stateless jobs, i.e. jobs without inputs.",
+	JobAdmissionControlAcceptNetworkedJobsKey:        "AcceptNetworkedJobs indicates whether to accept jobs that require network access.",
+	JobAdmissionControlProbeHTTPKey:                  "ProbeHTTP specifies the HTTP endpoint for probing job submission.",
+	JobAdmissionControlProbeExecKey:                  "ProbeExec specifies the command to execute for probing job submission.",
+	LoggingLevelKey:                                  "Level sets the logging level. One of: trace, debug, info, warn, error, fatal, panic.",
+	LoggingModeKey:                                   "Mode specifies the logging mode. One of: default, json.",
+	LoggingLogDebugInfoIntervalKey:                   "LogDebugInfoInterval specifies the interval for logging debug information.",
+	UpdateConfigIntervalKey:                          "Interval specifies the time between update checks, when set to 0 update checks are not performed.",
+	FeatureFlagsExecTranslationKey:                   "ExecTranslation enables the execution translation feature.",
 }
diff --git a/pkg/config/types/interface.go b/pkg/config/types/interface.go
new file mode 100644
index 0000000000..a060c5326b
--- /dev/null
+++ b/pkg/config/types/interface.go
@@ -0,0 +1,5 @@
+package types
+
+type Provider interface {
+	IsNotDisabled(kind string) bool
+}
diff --git a/pkg/config/types/jobdefaults.go b/pkg/config/types/jobdefaults.go
new file mode 100644
index 0000000000..0746c3b821
--- /dev/null
+++ b/pkg/config/types/jobdefaults.go
@@ -0,0 +1,69 @@
+package types
+
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/models"
+)
+
+type JobDefaults struct {
+	Batch   BatchJobDefaultsConfig       `yaml:"Batch,omitempty"`
+	Ops     BatchJobDefaultsConfig       `yaml:"Ops,omitempty"`
+	Daemon  LongRunningJobDefaultsConfig `yaml:"Daemon,omitempty"`
+	Service LongRunningJobDefaultsConfig `yaml:"Service,omitempty"`
+}
+
+type BatchJobDefaultsConfig struct {
+	// Priority specifies the default priority allocated to a batch or ops job.
+	// This value is used when the job hasn't explicitly set its priority requirement.
+	Priority int                    `yaml:"Priority,omitempty"`
+	Task     BatchTaskDefaultConfig `yaml:"Task,omitempty"`
+}
+
+type BatchTaskDefaultConfig struct {
+	Resources ResourcesConfig        `yaml:"Resources,omitempty"`
+	Publisher DefaultPublisherConfig `yaml:"Publisher,omitempty"`
+	Timeouts  TaskTimeoutConfig      `yaml:"Timeouts,omitempty"`
+}
+
+type ResourcesConfig struct {
+	// CPU specifies the default amount of CPU allocated to a task.
+	// It uses Kubernetes resource string format (e.g., "100m" for 0.1 CPU cores).
+	// This value is used when the task hasn't explicitly set its CPU requirement.
+	CPU string `yaml:"CPU,omitempty"`
+
+	// Memory specifies the default amount of memory allocated to a task.
+	// It uses Kubernetes resource string format (e.g., "256Mi" for 256 mebibytes).
+	// This value is used when the task hasn't explicitly set its memory requirement.
+	Memory string `yaml:"Memory,omitempty"`
+
+	// Disk specifies the default amount of disk space allocated to a task.
+	// It uses Kubernetes resource string format (e.g., "1Gi" for 1 gibibyte).
+	// This value is used when the task hasn't explicitly set its disk space requirement.
+	Disk string `yaml:"Disk,omitempty"`
+
+	// GPU specifies the default number of GPUs allocated to a task.
+	// It uses Kubernetes resource string format (e.g., "1" for 1 GPU).
+	// This value is used when the task hasn't explicitly set its GPU requirement.
+	GPU string `yaml:"GPU,omitempty"`
+}
+
+type DefaultPublisherConfig struct {
+	Config models.SpecConfig `yaml:"Config,omitempty"`
+}
+
+type TaskTimeoutConfig struct {
+	// TotalTimeout is the maximum total time allowed for a task
+	TotalTimeout Duration `yaml:"TotalTimeout,omitempty"`
+	// ExecutionTimeout is the maximum time allowed for task execution
+	ExecutionTimeout Duration `yaml:"ExecutionTimeout,omitempty"`
+}
+
+type LongRunningJobDefaultsConfig struct {
+	// Priority specifies the default priority allocated to a service or daemon job.
+	// This value is used when the job hasn't explicitly set its priority requirement.
+	Priority int                          `yaml:"Priority,omitempty"`
+	Task     LongRunningTaskDefaultConfig `yaml:"Task,omitempty"`
+}
+
+type LongRunningTaskDefaultConfig struct {
+	Resources ResourcesConfig `yaml:"Resources,omitempty"`
+}
diff --git a/pkg/config/types/orchestrator.go b/pkg/config/types/orchestrator.go
new file mode 100644
index 0000000000..39a1c751b6
--- /dev/null
+++ b/pkg/config/types/orchestrator.go
@@ -0,0 +1,55 @@
+package types
+
+type Orchestrator struct {
+	// Enabled indicates whether the orchestrator node is active and available for job submission.
+	Enabled bool `yaml:"Enabled,omitempty"`
+	// Host specifies the hostname or IP address on which the Orchestrator server listens for compute node connections.
+	Host string `yaml:"Host,omitempty"`
+	// Host specifies the port number on which the Orchestrator server listens for compute node connections.
+	Port int `yaml:"Port,omitempty"`
+	// Advertise specifies URL to advertise to other servers.
+	Advertise string `yaml:"Advertise,omitempty"`
+	// AuthSecret key specifies the key used by compute nodes to connect to an orchestrator.
+	AuthSecret       string           `yaml:"AuthSecret,omitempty"`
+	TLS              TLS              `yaml:"TLS,omitempty"`
+	Cluster          Cluster          `yaml:"Cluster,omitempty"`
+	NodeManager      NodeManager      `yaml:"NodeManager,omitempty"`
+	Scheduler        Scheduler        `yaml:"Scheduler,omitempty"`
+	EvaluationBroker EvaluationBroker `yaml:"EvaluationBroker,omitempty"`
+}
+
+type Cluster struct {
+	// Name specifies the unique identifier for this orchestrator cluster.
+	Name string `yaml:"Name,omitempty"`
+	// Host specifies the hostname or IP address for cluster communication.
+	Host string `yaml:"Host,omitempty"`
+	// Port specifies the port number for cluster communication.
+	Port int `yaml:"Port,omitempty"`
+	// Advertise specifies the address to advertise to other cluster members.
+	Advertise string `yaml:"Advertise,omitempty"`
+	// Peers is a list of other cluster members to connect to on startup.
+	Peers []string `yaml:"Peers,omitempty"`
+}
+
+type NodeManager struct {
+	// DisconnectTimeout specifies how long to wait before considering a node disconnected.
+	DisconnectTimeout Duration `yaml:"DisconnectTimeout,omitempty"`
+	// ManualApproval, if true, requires manual approval for new compute nodes joining the cluster.
+	ManualApproval bool `yaml:"ManualApproval,omitempty"`
+}
+
+type Scheduler struct {
+	// WorkerCount specifies the number of concurrent workers for job scheduling.
+	WorkerCount int `yaml:"WorkerCount,omitempty"`
+	// HousekeepingInterval specifies how often to run housekeeping tasks.
+	HousekeepingInterval Duration `yaml:"HousekeepingInterval,omitempty"`
+	// HousekeepingTimeout specifies the maximum time allowed for a single housekeeping run.
+	HousekeepingTimeout Duration `yaml:"HousekeepingTimeout,omitempty"`
+}
+
+type EvaluationBroker struct {
+	// VisibilityTimeout specifies how long an evaluation can be claimed before it's returned to the queue.
+	VisibilityTimeout Duration `yaml:"VisibilityTimeout,omitempty"`
+	// MaxRetryCount specifies the maximum number of times an evaluation can be retried before being marked as failed.
+	MaxRetryCount int `yaml:"MaxRetryCount,omitempty"`
+}
diff --git a/pkg/config/types/parse.go b/pkg/config/types/parse.go
new file mode 100644
index 0000000000..63707094d4
--- /dev/null
+++ b/pkg/config/types/parse.go
@@ -0,0 +1,141 @@
+package types
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+func CastConfigValueForKey(key string, value any) (any, error) {
+	key = strings.ToLower(key)
+	typ, ok := AllKeys()[key]
+	if !ok {
+		return nil, fmt.Errorf("%q is not a valid config key", key)
+	}
+
+	switch v := value.(type) {
+	case bool:
+		return v, nil
+	case string:
+		return parseString(key, v, typ)
+	case []string:
+		return parseStringSlice(key, v, typ)
+	default:
+		return nil, fmt.Errorf("DEVELOPER ERROR CastConfigValueForKey called with unsupported type: %T", v)
+	}
+}
+
+func parseString(key, value string, typ reflect.Type) (any, error) {
+	if typ == reflect.TypeOf(Duration(0)) {
+		return parseDuration(key, value)
+	}
+	if typ == reflect.TypeOf([]string{}) {
+		return parseStringToSlice(value)
+	}
+	return parseByKind(key, value, typ)
+}
+
+func parseStringToSlice(value string) ([]string, error) {
+	// Check for invalid separators
+	if strings.Contains(value, ";") || strings.Contains(value, " ") {
+		return nil, fmt.Errorf("invalid separator in string slice '%s', only comma (,) is allowed", value)
+	}
+
+	// If there's no comma, return a slice with a single element
+	if !strings.Contains(value, ",") {
+		return []string{value}, nil
+	}
+
+	// Split the string by comma
+	tokens := strings.Split(value, ",")
+
+	// Check for empty tokens
+	for i, token := range tokens {
+		trimmedToken := strings.TrimSpace(token)
+		if trimmedToken == "" {
+			return nil, fmt.Errorf("empty token found at position %d in string slice '%s'", i, value)
+		}
+		tokens[i] = trimmedToken // Store the trimmed token back
+	}
+
+	return tokens, nil
+}
+
+func parseStringSlice(key string, values []string, typ reflect.Type) (any, error) {
+	if typ == reflect.TypeOf(Duration(0)) {
+		return parseDuration(key, values[0])
+	}
+	if typ == reflect.TypeOf([]string{}) {
+		return values, nil
+	}
+	return parseByKind(key, values[0], typ)
+}
+
+func parseDuration(key, value string) (string, error) {
+	duration, err := time.ParseDuration(value)
+	if err != nil {
+		return "", fmt.Errorf("parsing value: '%s' for key: '%s' to duration: %w", value, key, err)
+	}
+	return duration.String(), nil
+}
+
+func parseByKind(key, value string, typ reflect.Type) (any, error) {
+	switch typ.Kind() {
+	case reflect.String:
+		return value, nil
+	case reflect.Bool:
+		return strconv.ParseBool(value)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return strconv.ParseInt(value, 10, 64)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		return strconv.ParseUint(value, 10, 64)
+	case reflect.Map:
+		tokens := strings.Split(value, ",")
+		return StringSliceToMap(tokens)
+	default:
+		return nil, fmt.Errorf("parsing value: '%s' for key: '%s': unsupported configuration type: %v", value, key, typ)
+	}
+}
+
+func StringSliceToMap(slice []string) (map[string]string, error) {
+	result := make(map[string]string)
+	for _, item := range slice {
+		tokens := strings.Split(item, "=")
+		if len(tokens) != 2 {
+			return nil, fmt.Errorf("expected 'key=value', received invalid format for key-value pair: '%s' in '%s'", item, slice)
+		}
+		key, value := tokens[0], tokens[1]
+		result[key] = value
+	}
+	return result, nil
+}
+
+func AllKeys() map[string]reflect.Type {
+	config := Bacalhau{}
+	paths := make(map[string]reflect.Type)
+	buildPathMap(reflect.ValueOf(config), "", paths)
+	return paths
+}
+
+func buildPathMap(v reflect.Value, prefix string, paths map[string]reflect.Type) {
+	switch v.Kind() {
+	case reflect.Struct:
+		for i := 0; i < v.NumField(); i++ {
+			field := v.Type().Field(i)
+			tag := field.Tag.Get("yaml")
+			if tag == "" {
+				tag = field.Name
+			} else {
+				tag = strings.Split(tag, ",")[0]
+			}
+			fieldPath := prefix + strings.ToLower(tag)
+			buildPathMap(v.Field(i), fieldPath+".", paths)
+		}
+	case reflect.Map, reflect.Slice, reflect.Array, reflect.Ptr:
+		paths[prefix[:len(prefix)-1]] = v.Type()
+	default:
+		paths[prefix[:len(prefix)-1]] = v.Type()
+	}
+}
diff --git a/pkg/config/types/paths.go b/pkg/config/types/paths.go
new file mode 100644
index 0000000000..2fff193073
--- /dev/null
+++ b/pkg/config/types/paths.go
@@ -0,0 +1,123 @@
+package types
+
+import (
+	"fmt"
+	"path/filepath"
+)
+
+const UserKeyFileName = "user_id.pem"
+
+func (c Bacalhau) UserKeyPath() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, UserKeyFileName)
+	if exists, err := fileExists(path); err != nil {
+		return "", fmt.Errorf("checking if user key exists: %w", err)
+	} else if exists {
+		return path, nil
+	}
+	if err := initUserIDKey(path); err != nil {
+		return "", fmt.Errorf("creating user private key: %w", err)
+	}
+	return path, nil
+}
+
+const AuthTokensFileName = "tokens.json"
+
+func (c Bacalhau) AuthTokensPath() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	return filepath.Join(c.DataDir, AuthTokensFileName), nil
+}
+
+const OrchestratorDirName = "orchestrator"
+
+func (c Bacalhau) OrchestratorDir() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, OrchestratorDirName)
+	if err := ensureDir(path); err != nil {
+		return "", fmt.Errorf("getting orchestrator path: %w", err)
+	}
+	return path, nil
+}
+
+const JobStoreFileName = "state_boltdb.db"
+
+func (c Bacalhau) JobStoreFilePath() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	// make sure the parent dir exists first
+	if _, err := c.OrchestratorDir(); err != nil {
+		return "", fmt.Errorf("getting job store path: %w", err)
+	}
+	return filepath.Join(c.DataDir, OrchestratorDirName, JobStoreFileName), nil
+}
+
+const NetworkTransportDirName = "nats-store"
+
+func (c Bacalhau) NetworkTransportDir() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, OrchestratorDirName, NetworkTransportDirName)
+	if err := ensureDir(path); err != nil {
+		return "", fmt.Errorf("getting network transport path: %w", err)
+	}
+	return path, nil
+}
+
+const ComputeDirName = "compute"
+
+func (c Bacalhau) ComputeDir() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, ComputeDirName)
+	if err := ensureDir(path); err != nil {
+		return "", fmt.Errorf("getting compute path: %w", err)
+	}
+	return path, nil
+}
+
+const ExecutionDirName = "executions"
+
+func (c Bacalhau) ExecutionDir() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, ComputeDirName, ExecutionDirName)
+	if err := ensureDir(path); err != nil {
+		return "", fmt.Errorf("getting executions path: %w", err)
+	}
+	return path, nil
+}
+
+const PluginsDirName = "plugins"
+
+func (c Bacalhau) PluginsDir() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	path := filepath.Join(c.DataDir, PluginsDirName)
+	if err := ensureDir(path); err != nil {
+		return "", fmt.Errorf("getting plugins path: %w", err)
+	}
+	return path, nil
+}
+
+const ExecutionStoreFileName = "state_boltdb.db"
+
+func (c Bacalhau) ExecutionStoreFilePath() (string, error) {
+	if c.DataDir == "" {
+		return "", fmt.Errorf("data dir not set")
+	}
+	if _, err := c.ComputeDir(); err != nil {
+		return "", fmt.Errorf("getting execution store path: %w", err)
+	}
+	return filepath.Join(c.DataDir, ComputeDirName, ExecutionStoreFileName), nil
+}
diff --git a/pkg/config/types/publishers.go b/pkg/config/types/publishers.go
new file mode 100644
index 0000000000..580e67317d
--- /dev/null
+++ b/pkg/config/types/publishers.go
@@ -0,0 +1,47 @@
+package types
+
+import (
+	"slices"
+	"strings"
+)
+
+var _ Provider = (*PublishersConfig)(nil)
+
+type PublishersConfig struct {
+	// Disabled specifies a list of publishers that are disabled.
+	Disabled []string       `yaml:"Disabled,omitempty"`
+	Types    PublisherTypes `yaml:"Types,omitempty"`
+}
+
+type PublisherTypes struct {
+	IPFS  IPFSPublisher  `yaml:"IPFS,omitempty"`
+	S3    S3Publisher    `yaml:"S3,omitempty"`
+	Local LocalPublisher `yaml:"Local,omitempty"`
+}
+
+func (p PublishersConfig) IsNotDisabled(kind string) bool {
+	return !slices.ContainsFunc(p.Disabled, func(s string) bool {
+		return strings.ToLower(s) == strings.ToLower(kind)
+	})
+}
+
+type IPFSPublisher struct {
+	// Endpoint specifies the multi-address to connect to for IPFS. e.g /ip4/127.0.0.1/tcp/5001
+	Endpoint string `yaml:"Endpoint,omitempty"`
+}
+
+type S3Publisher struct {
+	// PreSignedURLDisabled specifies whether pre-signed URLs are enabled for the S3 provider.
+	PreSignedURLDisabled bool `yaml:"PreSignedURLDisabled,omitempty"`
+	// PreSignedURLExpiration specifies the duration before a pre-signed URL expires.
+	PreSignedURLExpiration Duration `yaml:"PreSignedURLExpiration,omitempty"`
+}
+
+type LocalPublisher struct {
+	// Address specifies the endpoint the publisher serves on.
+	Address string `yaml:"Address,omitempty"`
+	// Port specifies the port the publisher serves on.
+	Port int `yaml:"Port,omitempty"`
+	// Directory specifies a path to location on disk where content is served from.
+	Directory string `yaml:"Directory,omitempty"`
+}
diff --git a/pkg/config/types/resource.go b/pkg/config/types/resource.go
new file mode 100644
index 0000000000..31430d6eef
--- /dev/null
+++ b/pkg/config/types/resource.go
@@ -0,0 +1,127 @@
+package types
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/BTBurke/k8sresource"
+	"github.com/dustin/go-humanize"
+
+	"github.com/bacalhau-project/bacalhau/pkg/models"
+)
+
+type ResourceScaler struct {
+	// CPU specifies the amount of CPU a compute node allocates for running jobs.
+	// It can be expressed as a percentage (e.g., "85%") or a Kubernetes resource string (e.g., "100m").
+	CPU ResourceType `yaml:"CPU,omitempty"`
+
+	// Memory specifies the amount of Memory a compute node allocates for running jobs.
+	// It can be expressed as a percentage (e.g., "85%") or a Kubernetes resource string (e.g., "1Gi").
+	Memory ResourceType `yaml:"Memory,omitempty"`
+
+	// Disk specifies the amount of Disk space a compute node allocates for running jobs.
+	// It can be expressed as a percentage (e.g., "85%") or a Kubernetes resource string (e.g., "10Gi").
+	Disk ResourceType `yaml:"Disk,omitempty"`
+
+	// GPU specifies the amount of GPU a compute node allocates for running jobs.
+	// It can be expressed as a percentage (e.g., "85%") or a Kubernetes resource string (e.g., "1").
+	// Note: When using percentages, the result is always rounded up to the nearest whole GPU.
+	GPU ResourceType `yaml:"GPU,omitempty"`
+}
+
+func (s ResourceScaler) IsZero() bool {
+	return s.CPU == "" && s.Memory == "" && s.Disk == "" && s.GPU == ""
+}
+
+func (s ResourceScaler) ToResource(in models.Resources) (*models.Resources, error) {
+	out := new(models.Resources)
+	if s.CPU.IsScaler() {
+		scalerStr := strings.TrimSuffix(string(s.CPU), "%")
+		value, err := strconv.ParseFloat(scalerStr, 64)
+		if err != nil {
+			return nil, fmt.Errorf("cpu capacity invalid percentage format: %w", err)
+		}
+		if value < 0 || value > 100 {
+			return nil, fmt.Errorf("cpu capacity percentage must be between 0%% and 100%%, got %s", s.CPU)
+		}
+		value = value / 100
+		out.CPU = in.CPU * value
+	} else {
+		cpu, err := k8sresource.NewCPUFromString(string(s.CPU))
+		if err != nil {
+			return nil, fmt.Errorf("invalid CPU value %q: %w", s.CPU, err)
+		}
+		out.CPU = cpu.ToFloat64()
+	}
+
+	if s.Memory.IsScaler() {
+		scalerStr := strings.TrimSuffix(string(s.Memory), "%")
+		value, err := strconv.ParseFloat(scalerStr, 64)
+		if err != nil {
+			return nil, fmt.Errorf("memory capacity invalid percentage format: %w", err)
+		}
+		if value < 0 || value > 100 {
+			return nil, fmt.Errorf("memory capacity percentage must be between 0%% and 100%%, got %s", s.Memory)
+		}
+		value = value / 100
+		out.Memory = uint64(float64(in.Memory) * value)
+	} else {
+		mem, err := humanize.ParseBytes(string(s.Memory))
+		if err != nil {
+			return nil, fmt.Errorf("invalid Memory value %q: %w", s.Memory, err)
+		}
+		out.Memory = mem
+	}
+
+	if s.Disk.IsScaler() {
+		scalerStr := strings.TrimSuffix(string(s.Disk), "%")
+		value, err := strconv.ParseFloat(scalerStr, 64)
+		if err != nil {
+			return nil, fmt.Errorf("disk capacity invalid percentage format: %w", err)
+		}
+		if value < 0 || value > 100 {
+			return nil, fmt.Errorf("disk capacity percentage must be between 0%% and 100%%, got %s", s.Disk)
+		}
+		value = value / 100
+		out.Disk = uint64(float64(in.Disk) * value)
+	} else {
+		disk, err := humanize.ParseBytes(string(s.Disk))
+		if err != nil {
+			return nil, fmt.Errorf("invalid Disk value %q: %w", s.Disk, err)
+		}
+		out.Disk = disk
+	}
+
+	if s.GPU.IsScaler() {
+		scalerStr := strings.TrimSuffix(string(s.GPU), "%")
+		value, err := strconv.ParseFloat(scalerStr, 64)
+		if err != nil {
+			return nil, fmt.Errorf("invalid percentage format: %w", err)
+		}
+		if value < 0 || value > 100 {
+			return nil, fmt.Errorf("percentage must be between 0%% and 100%%, got %s", s.GPU)
+		}
+		value = value / 100
+		// ensure we never scale a GPU down to zero unless there isn't a GPU
+		tmp := float64(in.GPU) * value
+		if tmp < 1 && in.GPU >= 1 {
+			tmp = 1
+		}
+		out.GPU = uint64(tmp)
+	} else {
+		gpu, err := strconv.ParseUint(string(s.GPU), 10, 64)
+		if err != nil {
+			return nil, fmt.Errorf("invalid GPU value %q: %w", s.GPU, err)
+		}
+		out.GPU = gpu
+	}
+
+	return out, nil
+}
+
+type ResourceType string
+
+func (t ResourceType) IsScaler() bool {
+	return strings.HasSuffix(string(t), "%")
+}
diff --git a/pkg/config/types/storage.go b/pkg/config/types/storage.go
new file mode 100644
index 0000000000..355dd6f629
--- /dev/null
+++ b/pkg/config/types/storage.go
@@ -0,0 +1,43 @@
+package types
+
+import (
+	"slices"
+	"strings"
+)
+
+var _ Provider = (*InputSourcesConfig)(nil)
+
+type InputSourcesConfig struct {
+	// Disabled specifies a list of storages that are disabled.
+	Disabled []string `yaml:"Disabled,omitempty"`
+	// ReadTimeout specifies the maximum time allowed for reading from a storage.
+	ReadTimeout Duration `yaml:"ReadTimeout,omitempty"`
+	// ReadTimeout specifies the maximum number of attempts for reading from a storage.
+	MaxRetryCount int               `yaml:"MaxRetryCount,omitempty"`
+	Types         InputSourcesTypes `yaml:"Types,omitempty"`
+}
+
+type InputSourcesTypes struct {
+	IPFS IPFSStorage `yaml:"IPFS,omitempty"`
+	S3   S3Storage   `yaml:"S3,omitempty"`
+}
+
+func (i InputSourcesConfig) IsNotDisabled(kind string) bool {
+	return !slices.ContainsFunc(i.Disabled, func(s string) bool {
+		return strings.ToLower(s) == strings.ToLower(kind)
+	})
+}
+
+type IPFSStorage struct {
+	// Endpoint specifies the multi-address to connect to for IPFS. e.g /ip4/127.0.0.1/tcp/5001
+	Endpoint string `yaml:"Endpoint,omitempty"`
+}
+
+type S3Storage struct {
+	// Endpoint specifies the endpoint URL for the S3 input source.
+	Endpoint string `yaml:"Endpoint,omitempty"`
+	// AccessKey specifies the access key for the S3 input source.
+	AccessKey string `yaml:"AccessKey,omitempty"`
+	// SecretKey specifies the secret key for the S3 input source.
+	SecretKey string `yaml:"SecretKey,omitempty"`
+}
diff --git a/pkg/config_legacy/DEPRECATED.md b/pkg/config_legacy/DEPRECATED.md
new file mode 100644
index 0000000000..1f3b10a3dc
--- /dev/null
+++ b/pkg/config_legacy/DEPRECATED.md
@@ -0,0 +1,3 @@
+# This Package is deprecated and must not be used or modified
+
+Please refer to pkg/config for the latest implementation.
\ No newline at end of file
diff --git a/pkg/config_legacy/config.go b/pkg/config_legacy/config.go
new file mode 100644
index 0000000000..2c4b065501
--- /dev/null
+++ b/pkg/config_legacy/config.go
@@ -0,0 +1,273 @@
+package config_legacy
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"reflect"
+	"strings"
+
+	"github.com/mitchellh/mapstructure"
+	"github.com/rs/zerolog/log"
+	"github.com/spf13/pflag"
+	"github.com/spf13/viper"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy/configenv"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
+)
+
+type ReadWriter interface {
+	Reader
+	Writer
+}
+
+var _ Reader = (*config)(nil)
+
+type Reader interface {
+	Current() (types.BacalhauConfig, error)
+}
+
+var _ Writer = (*config)(nil)
+
+type Writer interface {
+	Set(key string, value interface{})
+	SetIfAbsent(key string, value interface{})
+}
+
+const (
+	FileName = "config.yaml"
+
+	environmentVariablePrefix = "BACALHAU"
+	inferConfigTypes          = true
+
+	// user key files
+	UserPrivateKeyFileName = "user_id.pem"
+
+	// compute paths
+	ComputeStoragesPath = "executor_storages"
+	ComputeStorePath    = "compute_store"
+	PluginsPath         = "plugins"
+
+	// orchestrator paths
+	OrchestratorStorePath = "orchestrator_store"
+	AutoCertCachePath     = "autocert-cache"
+	NetworkTransportStore = "nats-store"
+
+	// auth paths
+	TokensPath = "tokens.json"
+)
+
+var (
+	ComputeExecutionsStorePath = filepath.Join(ComputeStorePath, "executions.db")
+	OrchestratorJobStorePath   = filepath.Join(OrchestratorStorePath, "jobs.db")
+
+	environmentVariableReplace = strings.NewReplacer(".", "_")
+	DecoderHook                = viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())
+)
+
+type config struct {
+	// viper instance for holding user provided configuration.
+	base *viper.Viper
+	// the default configuration values to initialize with.
+	defaultCfg types.BacalhauConfig
+
+	// paths to configuration files merged from [0] to [N]
+	// e.g. file at index 1 overrides index 0, index 2 overrides index 1 and 0, etc.
+	paths []string
+
+	flags map[string]*pflag.Flag
+
+	environmentVariables map[string][]string
+
+	// values to inject into the config, taking highest precedence.
+	values map[string]any
+}
+
+type Option = func(s *config)
+
+// WithDefault sets the default config to be used when no values are provided.
+func WithDefault(cfg types.BacalhauConfig) Option {
+	return func(c *config) {
+		c.defaultCfg = cfg
+	}
+}
+
+// WithPaths sets paths to configuration files to be loaded
+// paths to configuration files merged from [0] to [N]
+// e.g. file at index 1 overrides index 0, index 2 overrides index 1 and 0, etc.
+func WithPaths(path ...string) Option {
+	return func(c *config) {
+		c.paths = append(c.paths, path...)
+	}
+}
+
+func WithFlags(flags map[string]*pflag.Flag) Option {
+	return func(s *config) {
+		s.flags = flags
+	}
+}
+
+func WithEnvironmentVariables(ev map[string][]string) Option {
+	return func(s *config) {
+		s.environmentVariables = ev
+	}
+}
+
+// WithValues sets values to be injected into the config, taking precedence over all other options.
+func WithValues(values map[string]any) Option {
+	return func(c *config) {
+		c.values = values
+	}
+}
+
+// New returns a configuration with the provided options applied. If no options are provided, the returned config
+// contains only the default values.
+func New(opts ...Option) (*config, error) {
+	base := viper.New()
+	base.SetEnvPrefix(environmentVariablePrefix)
+	base.SetTypeByDefaultValue(inferConfigTypes)
+	base.AutomaticEnv()
+	base.SetEnvKeyReplacer(environmentVariableReplace)
+
+	c := &config{
+		base:       base,
+		defaultCfg: configenv.Production,
+		paths:      make([]string, 0),
+	}
+	for _, opt := range opts {
+		opt(c)
+	}
+
+	c.setDefault(c.defaultCfg)
+
+	// merge the config files in the order they were passed.
+	for _, path := range c.paths {
+		if err := c.Merge(path); err != nil {
+			if os.IsNotExist(err) {
+				return nil, fmt.Errorf("the specified configuration file %q doesn't exist", path)
+			}
+			return nil, fmt.Errorf("opening config file %q: %w", path, err)
+		}
+	}
+
+	for name, values := range c.environmentVariables {
+		if err := c.base.BindEnv(append([]string{name}, values...)...); err != nil {
+			return nil, fmt.Errorf("binding environment variable %q to config: %w", name, err)
+		}
+	}
+
+	for name, flag := range c.flags {
+		if err := c.base.BindPFlag(name, flag); err != nil {
+			return nil, fmt.Errorf("binding flag %q to config: %w", name, err)
+		}
+	}
+
+	// merge the passed values last as they take highest precedence
+	for name, value := range c.values {
+		c.base.Set(name, value)
+	}
+
+	return c, nil
+}
+
+// Load reads in the configuration file specified by `path` overriding any previously set configuration with the values
+// from the read config file.
+// Load returns an error if the file cannot be read.
+func (c *config) Load(path string) error {
+	c.base.SetConfigFile(path)
+	if err := c.base.ReadInConfig(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (c *config) Merge(path string) error {
+	c.base.SetConfigFile(path)
+	if err := c.base.MergeInConfig(); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Write persists the current configuration to `path`.
+// Write returns an error if:
+//   - the path cannot be accessed
+//   - the current configuration cannot be marshaled.
+func (c *config) Write(path string) error {
+	return c.base.WriteConfigAs(path)
+}
+
+// Current returns the current configuration.
+// Current returns an error if the configuration cannot be unmarshalled.
+func (c *config) Current() (types.BacalhauConfig, error) {
+	out := new(types.BacalhauConfig)
+	if err := c.base.Unmarshal(&out, DecoderHook); err != nil {
+		return types.BacalhauConfig{}, err
+	}
+	return *out, nil
+}
+
+// Set sets the configuration value.
+// This value won't be persisted in the config file.
+// Will be used instead of values obtained via flags, config file, ENV, default.
+func (c *config) Set(key string, value interface{}) {
+	c.base.Set(key, value)
+}
+
+func (c *config) SetIfAbsent(key string, value interface{}) {
+	if !c.base.IsSet(key) || reflect.ValueOf(c.base.Get(key)).IsZero() {
+		c.Set(key, value)
+	}
+}
+
+// setDefault sets the default value for the configuration.
+// Default only used when no value is provided by the user via an explicit call to Set, flag, config file or ENV.
+func (c *config) setDefault(config types.BacalhauConfig) {
+	types.SetDefaults(config, types.WithViper(c.base))
+}
+
+// WritePersistedConfigs will write certain values from the resolved config to the persisted config.
+// These include fields for configurations that must not change between version updates, such as the
+// execution store and job store paths, in case we change their default values in future updates.
+func WritePersistedConfigs(configFilePath string, cfg types.BacalhauConfig) error {
+	// a viper config instance that is only based on the config file.
+	viperWriter := viper.New()
+	viperWriter.SetTypeByDefaultValue(true)
+	viperWriter.SetConfigFile(configFilePath)
+
+	// read existing config if it exists.
+	if err := viperWriter.ReadInConfig(); err != nil {
+		if !os.IsNotExist(err) {
+			return err
+		}
+	}
+
+	var fileCfg types.BacalhauConfig
+	if err := viperWriter.Unmarshal(&fileCfg, DecoderHook); err != nil {
+		return err
+	}
+
+	// check if any of the values that we want to write are not set in the config file.
+	var doWrite bool
+	var logMessage strings.Builder
+	set := func(key string, value interface{}) {
+		viperWriter.Set(key, value)
+		logMessage.WriteString(fmt.Sprintf("\n%s:\t%v", key, value))
+		doWrite = true
+	}
+	emptyStoreConfig := types.JobStoreConfig{}
+	if fileCfg.Node.Compute.ExecutionStore == emptyStoreConfig {
+		set(types.NodeComputeExecutionStore, cfg.Node.Compute.ExecutionStore)
+	}
+	if fileCfg.Node.Requester.JobStore == emptyStoreConfig {
+		set(types.NodeRequesterJobStore, cfg.Node.Requester.JobStore)
+	}
+	if fileCfg.Node.Name == "" && cfg.Node.Name != "" {
+		set(types.NodeName, cfg.Node.Name)
+	}
+	if doWrite {
+		log.Info().Msgf("Writing to config file %s:%s", configFilePath, logMessage.String())
+		return viperWriter.WriteConfig()
+	}
+	return nil
+}
diff --git a/pkg/config/configenv/production.go b/pkg/config_legacy/configenv/production.go
similarity index 98%
rename from pkg/config/configenv/production.go
rename to pkg/config_legacy/configenv/production.go
index b9721e1c6f..7e130f63ab 100644
--- a/pkg/config/configenv/production.go
+++ b/pkg/config_legacy/configenv/production.go
@@ -7,7 +7,7 @@ import (
 	"time"
 
 	"github.com/bacalhau-project/bacalhau/pkg/authn"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 )
diff --git a/pkg/config/helpers.go b/pkg/config_legacy/helpers.go
similarity index 99%
rename from pkg/config/helpers.go
rename to pkg/config_legacy/helpers.go
index d263479002..9dbc01f44b 100644
--- a/pkg/config/helpers.go
+++ b/pkg/config_legacy/helpers.go
@@ -1,4 +1,4 @@
-package config
+package config_legacy
 
 import (
 	"crypto"
diff --git a/pkg/config_legacy/types/auth.go b/pkg/config_legacy/types/auth.go
new file mode 100644
index 0000000000..3cc4c2181c
--- /dev/null
+++ b/pkg/config_legacy/types/auth.go
@@ -0,0 +1,45 @@
+package types
+
+import "github.com/bacalhau-project/bacalhau/pkg/authn"
+
+// AuthenticationConfig is config for a specific named authentication method,
+// specifying the type of authentication and the path to a policy file that
+// controls the method. Some implementation types may require policies that meet
+// a certain interface beyond the default – see the documentation on that type
+// for more info.
+type AuthenticatorConfig struct {
+	Type       authn.MethodType `yaml:"Type"`
+	PolicyPath string           `yaml:"PolicyPath,omitempty"`
+}
+
+// AuthConfig is config that controls user authentication and authorization.
+type AuthConfig struct {
+	// TokensPath is the location where a state file of tokens will be stored.
+	// By default it will be local to the Bacalhau repo, but can be any location
+	// in the host filesystem. Tokens are sensitive and should be stored in a
+	// location that is only readable to the current user.
+	// Deprecated: replaced by cfg.AuthTokensPath()
+	TokensPath string `yaml:"TokensPath"`
+
+	// Methods maps "method names" to authenticator implementations. A method
+	// name is a human-readable string chosen by the person configuring the
+	// system that is shown to users to help them pick the authentication method
+	// they want to use. There can be multiple usages of the same Authenticator
+	// *type* but with different configs and parameters, each identified with a
+	// unique method name.
+	//
+	// For example, if an implementation wants to allow users to log in with
+	// Github or Bitbucket, they might both use an authenticator implementation
+	// of type "oidc", and each would appear once on this provider with key /
+	// method name "github" and "bitbucket".
+	//
+	// By default, only a single authentication method that accepts
+	// authentication via client keys will be enabled.
+	Methods map[string]AuthenticatorConfig `yaml:"Methods"`
+
+	// AccessPolicyPath is the path to a file or directory that will be loaded as
+	// the policy to apply to all inbound API requests. If unspecified, a policy
+	// that permits access to all API endpoints to both authenticated and
+	// unauthenticated users (the default as of v1.2.0) will be used.
+	AccessPolicyPath string `yaml:"AccessPolicyPath"`
+}
diff --git a/pkg/config_legacy/types/compute.go b/pkg/config_legacy/types/compute.go
new file mode 100644
index 0000000000..116aeeff0d
--- /dev/null
+++ b/pkg/config_legacy/types/compute.go
@@ -0,0 +1,76 @@
+package types
+
+import (
+	"github.com/bacalhau-project/bacalhau/pkg/models"
+)
+
+type ComputeConfig struct {
+	Capacity             CapacityConfig            `yaml:"Capacity"`
+	ExecutionStore       JobStoreConfig            `yaml:"ExecutionStore"`
+	JobTimeouts          JobTimeoutConfig          `yaml:"JobTimeouts"`
+	JobSelection         models.JobSelectionPolicy `yaml:"JobSelection"`
+	Logging              LoggingConfig             `yaml:"Logging"`
+	ManifestCache        DockerCacheConfig         `yaml:"ManifestCache"`
+	LogStreamConfig      LogStreamConfig           `yaml:"LogStream"`
+	LocalPublisher       LocalPublisherConfig      `yaml:"LocalPublisher"`
+	ControlPlaneSettings ComputeControlPlaneConfig `yaml:"ClusterTimeouts"`
+}
+
+type CapacityConfig struct {
+	IgnorePhysicalResourceLimits bool `yaml:"IgnorePhysicalResourceLimits"`
+	// Total amount of resource the system can be using at one time in aggregate for all jobs.
+	TotalResourceLimits models.ResourcesConfig `yaml:"TotalResourceLimits"`
+	// Per job amount of resource the system can be using at one time.
+	JobResourceLimits        models.ResourcesConfig `yaml:"JobResourceLimits"`
+	DefaultJobResourceLimits models.ResourcesConfig `yaml:"DefaultJobResourceLimits"`
+}
+
+type JobTimeoutConfig struct {
+	// JobExecutionTimeoutClientIDBypassList is the list of clients that are allowed to bypass the job execution timeout
+	// check.
+	JobExecutionTimeoutClientIDBypassList []string `yaml:"JobExecutionTimeoutClientIDBypassList"`
+	// JobNegotiationTimeout default timeout value to hold a bid for a job
+	JobNegotiationTimeout Duration `yaml:"JobNegotiationTimeout"`
+	// MinJobExecutionTimeout default value for the minimum execution timeout this compute node supports. Jobs with
+	// lower timeout requirements will not be bid on.
+	MinJobExecutionTimeout Duration `yaml:"MinJobExecutionTimeout"`
+	// MaxJobExecutionTimeout default value for the maximum execution timeout this compute node supports. Jobs with
+	// higher timeout requirements will not be bid on.
+	MaxJobExecutionTimeout Duration `yaml:"MaxJobExecutionTimeout"`
+	// DefaultJobExecutionTimeout default value for the execution timeout this compute node will assign to jobs with
+	// no timeout requirement defined.
+	DefaultJobExecutionTimeout Duration `yaml:"DefaultJobExecutionTimeout"`
+}
+
+type LoggingConfig struct {
+	// logging running executions
+	LogRunningExecutionsInterval Duration `yaml:"LogRunningExecutionsInterval"`
+}
+
+type LogStreamConfig struct {
+	// How many messages to buffer in the log stream channel, per stream
+	ChannelBufferSize int `yaml:"ChannelBufferSize"`
+}
+
+type LocalPublisherConfig struct {
+	Address   string `yaml:"Address"`
+	Port      int    `yaml:"Port"`
+	Directory string `yaml:"Directory"`
+}
+
+type ComputeControlPlaneConfig struct {
+	// The frequency with which the compute node will send node info (inc current labels)
+	// to the controlling requester node.
+	InfoUpdateFrequency Duration `yaml:"InfoUpdateFrequency"`
+
+	// How often the compute node will send current resource availability to the requester node.
+	ResourceUpdateFrequency Duration `yaml:"ResourceUpdateFrequency"`
+
+	// How often the compute node will send a heartbeat to the requester node to let it know
+	// that the compute node is still alive. This should be less than the requester's configured
+	// heartbeat timeout to avoid flapping.
+	HeartbeatFrequency Duration `yaml:"HeartbeatFrequency"`
+
+	// This is the pubsub topic that the compute node will use to send heartbeats to the requester node.
+	HeartbeatTopic string `yaml:"HeartbeatTopic"`
+}
diff --git a/pkg/config/types/config.go b/pkg/config_legacy/types/config.go
similarity index 100%
rename from pkg/config/types/config.go
rename to pkg/config_legacy/types/config.go
diff --git a/pkg/config_legacy/types/duration.go b/pkg/config_legacy/types/duration.go
new file mode 100644
index 0000000000..2b7cb03be2
--- /dev/null
+++ b/pkg/config_legacy/types/duration.go
@@ -0,0 +1,48 @@
+package types
+
+import "time"
+
+// Duration is a wrapper type for time.Duration
+// for decoding and encoding from/to YAML, etc.
+type Duration time.Duration
+
+// UnmarshalText implements interface for YAML decoding
+func (dur *Duration) UnmarshalText(text []byte) error {
+	d, err := time.ParseDuration(string(text))
+	if err != nil {
+		return err
+	}
+	*dur = Duration(d)
+	return err
+}
+
+func (dur Duration) MarshalText() ([]byte, error) {
+	d := time.Duration(dur)
+	return []byte(d.String()), nil
+}
+
+func (dur Duration) String() string {
+	return time.Duration(dur).String()
+}
+
+/*
+AsTimeDuration returns Duration as a time.Duration type.
+It is only called in the code gen to set viper defaults.
+This method exists for the following reasons:
+ 1. our config file is yaml, and we want to use durations for configuring things, printed in a human-readable format.
+ 2. time.Duration does not, and will not implement MarshalText/UnmarshalText
+    - https://github.com/golang/go/issues/16039
+ 3. viper.GetDuration doesn't return an error, and instead returns `0` if it fails to cast
+    - https://github.com/spf13/viper/blob/master/viper.go#L1048
+    - https://github.com/spf13/cast/blob/master/caste.go#L61
+    viper.GetDuration is unable to cast a types.Duration to a time.Duration (see second link), so it returns 0.
+
+To meet the 3 constraints above we write durations into viper as a time.Duration, but cast them
+to a types.Duration when they are added to our config structure. This allows us to:
+1. Have human-readable times in out config file.
+2. Have type safety on out cli, i.e. config set <duration_key> 10s
+3. Return durations instead of `0` from viper.GetDuration.
+*/
+func (dur Duration) AsTimeDuration() time.Duration {
+	return time.Duration(dur)
+}
diff --git a/pkg/config_legacy/types/fs.go b/pkg/config_legacy/types/fs.go
new file mode 100644
index 0000000000..9a9e958140
--- /dev/null
+++ b/pkg/config_legacy/types/fs.go
@@ -0,0 +1,122 @@
+package types
+
+import (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"fmt"
+	"os"
+
+	"github.com/rs/zerolog/log"
+
+	"github.com/bacalhau-project/bacalhau/pkg/storage/util"
+)
+
+func ensureDir(path string) error {
+	exists, err := dirExists(path)
+	if err != nil {
+		return err
+	}
+	if exists {
+		return nil
+	}
+	return mkDir(path)
+}
+
+func mkDir(path string) error {
+	// dir cannot already exist
+	exists, err := dirExists(path)
+	if err != nil {
+		return fmt.Errorf("checking if directory exists at path %q: %w", path, err)
+	}
+	if exists {
+		return os.ErrExist
+	}
+
+	// create the directory and return the full path
+	if err := os.MkdirAll(path, util.OS_USER_RWX); err != nil {
+		return fmt.Errorf("failed to create directory at at %q: %w", path, err)
+	}
+	return nil
+}
+
+func dirExists(path string) (bool, error) {
+	// stat path to check if exists
+	stat, err := os.Stat(path)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return false, nil
+		}
+		// it exists, but we failed to stat it, return err
+		return false, fmt.Errorf("failed to check if directory exists at path %q: %w", path, err)
+	}
+	// if the path exists, ensure it's a directory
+	if !stat.IsDir() {
+		return false, fmt.Errorf("path %q is a file, expected directory", path)
+	}
+	return true, nil
+}
+
+const (
+	// bitsPerKey number of bits in generated RSA keypairs for the user key.
+	bitsPerKey = 2048 // number of bits in generated RSA keypairs
+)
+
+func initUserIDKey(path string) error {
+	// Check if the file exists, fail if it does, create it if it doesn't
+	exists, err := fileExists(path)
+	if err != nil {
+		return fmt.Errorf("failed to check user key file at path: %w", err)
+	}
+	if exists {
+		// user key already exists.
+		return fmt.Errorf("user key file already exists at path: %s", path)
+	}
+
+	// File does not exist, proceed with initialization
+	log.Debug().Msgf("initializing user ID key file at '%s'", path)
+
+	var key *rsa.PrivateKey
+	key, err = rsa.GenerateKey(rand.Reader, bitsPerKey)
+	if err != nil {
+		return fmt.Errorf("failed to generate private key: %w", err)
+	}
+
+	keyBytes := x509.MarshalPKCS1PrivateKey(key)
+	keyBlock := pem.Block{
+		Type:  "RSA PRIVATE KEY",
+		Bytes: keyBytes,
+	}
+
+	var file *os.File
+	file, err = os.Create(path)
+	if err != nil {
+		return fmt.Errorf("failed to create key file: %w", err)
+	}
+	defer file.Close()
+
+	if err = pem.Encode(file, &keyBlock); err != nil {
+		return fmt.Errorf("failed to encode key file: %w", err)
+	}
+
+	if err = os.Chmod(path, util.OS_USER_RW); err != nil {
+		return fmt.Errorf("failed to set permission on key file: %w", err)
+	}
+
+	return nil
+}
+
+func fileExists(path string) (bool, error) {
+	// Check if the file exists
+	_, err := os.Stat(path)
+	if err == nil {
+		// File exists
+		return true, nil
+	} else if !os.IsNotExist(err) {
+		// os.Stat returned an error other than "file does not exist"
+		return false, fmt.Errorf("failed to check if file exists at path: %w", err)
+	}
+	// file does not exist
+	return false, nil
+}
diff --git a/pkg/config/types/gen_viper/generate.go b/pkg/config_legacy/types/gen_viper/generate.go
similarity index 97%
rename from pkg/config/types/gen_viper/generate.go
rename to pkg/config_legacy/types/gen_viper/generate.go
index 72ca364ab8..184f0d5d8d 100644
--- a/pkg/config/types/gen_viper/generate.go
+++ b/pkg/config_legacy/types/gen_viper/generate.go
@@ -7,7 +7,7 @@ import (
 	"reflect"
 	"strings"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 )
 
 // generateSetDefaults is a recursive function that takes a reflect.Type representing the structure of the configuration,
@@ -84,7 +84,7 @@ func main() {
 	defer file.Close()
 
 	// You would replace this with an actual instance of BacalhauConfig with the default values set
-	defaultConfig := types.BacalhauConfig{}
+	defaultConfig := legacy_types.BacalhauConfig{}
 
 	// Adding the package name
 	fmt.Fprintf(file, `// CODE GENERATED BY pkg/config/types/gen_viper DO NOT EDIT
diff --git a/pkg/config_legacy/types/generated_constants.go b/pkg/config_legacy/types/generated_constants.go
new file mode 100644
index 0000000000..c249872988
--- /dev/null
+++ b/pkg/config_legacy/types/generated_constants.go
@@ -0,0 +1,174 @@
+// CODE GENERATED BY pkg/config/types/gen_paths DO NOT EDIT
+
+package types
+
+const Node = "node"
+const NodeName = "node.name"
+const NodeNameProvider = "node.nameprovider"
+const NodeClientAPI = "node.clientapi"
+const NodeClientAPIHost = "node.clientapi.host"
+const NodeClientAPIPort = "node.clientapi.port"
+const NodeClientAPIClientTLS = "node.clientapi.clienttls"
+const NodeClientAPIClientTLSUseTLS = "node.clientapi.clienttls.usetls"
+const NodeClientAPIClientTLSCACert = "node.clientapi.clienttls.cacert"
+const NodeClientAPIClientTLSInsecure = "node.clientapi.clienttls.insecure"
+const NodeClientAPITLS = "node.clientapi.tls"
+const NodeClientAPITLSAutoCert = "node.clientapi.tls.autocert"
+const NodeClientAPITLSAutoCertCachePath = "node.clientapi.tls.autocertcachepath"
+const NodeClientAPITLSServerCertificate = "node.clientapi.tls.servercertificate"
+const NodeClientAPITLSServerKey = "node.clientapi.tls.serverkey"
+const NodeClientAPITLSSelfSigned = "node.clientapi.tls.selfsigned"
+const NodeServerAPI = "node.serverapi"
+const NodeServerAPIHost = "node.serverapi.host"
+const NodeServerAPIPort = "node.serverapi.port"
+const NodeServerAPIClientTLS = "node.serverapi.clienttls"
+const NodeServerAPIClientTLSUseTLS = "node.serverapi.clienttls.usetls"
+const NodeServerAPIClientTLSCACert = "node.serverapi.clienttls.cacert"
+const NodeServerAPIClientTLSInsecure = "node.serverapi.clienttls.insecure"
+const NodeServerAPITLS = "node.serverapi.tls"
+const NodeServerAPITLSAutoCert = "node.serverapi.tls.autocert"
+const NodeServerAPITLSAutoCertCachePath = "node.serverapi.tls.autocertcachepath"
+const NodeServerAPITLSServerCertificate = "node.serverapi.tls.servercertificate"
+const NodeServerAPITLSServerKey = "node.serverapi.tls.serverkey"
+const NodeServerAPITLSSelfSigned = "node.serverapi.tls.selfsigned"
+const NodeIPFS = "node.ipfs"
+const NodeIPFSConnect = "node.ipfs.connect"
+const NodeCompute = "node.compute"
+const NodeComputeCapacity = "node.compute.capacity"
+const NodeComputeCapacityIgnorePhysicalResourceLimits = "node.compute.capacity.ignorephysicalresourcelimits"
+const NodeComputeCapacityTotalResourceLimits = "node.compute.capacity.totalresourcelimits"
+const NodeComputeCapacityTotalResourceLimitsCPU = "node.compute.capacity.totalresourcelimits.cpu"
+const NodeComputeCapacityTotalResourceLimitsMemory = "node.compute.capacity.totalresourcelimits.memory"
+const NodeComputeCapacityTotalResourceLimitsDisk = "node.compute.capacity.totalresourcelimits.disk"
+const NodeComputeCapacityTotalResourceLimitsGPU = "node.compute.capacity.totalresourcelimits.gpu"
+const NodeComputeCapacityJobResourceLimits = "node.compute.capacity.jobresourcelimits"
+const NodeComputeCapacityJobResourceLimitsCPU = "node.compute.capacity.jobresourcelimits.cpu"
+const NodeComputeCapacityJobResourceLimitsMemory = "node.compute.capacity.jobresourcelimits.memory"
+const NodeComputeCapacityJobResourceLimitsDisk = "node.compute.capacity.jobresourcelimits.disk"
+const NodeComputeCapacityJobResourceLimitsGPU = "node.compute.capacity.jobresourcelimits.gpu"
+const NodeComputeCapacityDefaultJobResourceLimits = "node.compute.capacity.defaultjobresourcelimits"
+const NodeComputeCapacityDefaultJobResourceLimitsCPU = "node.compute.capacity.defaultjobresourcelimits.cpu"
+const NodeComputeCapacityDefaultJobResourceLimitsMemory = "node.compute.capacity.defaultjobresourcelimits.memory"
+const NodeComputeCapacityDefaultJobResourceLimitsDisk = "node.compute.capacity.defaultjobresourcelimits.disk"
+const NodeComputeCapacityDefaultJobResourceLimitsGPU = "node.compute.capacity.defaultjobresourcelimits.gpu"
+const NodeComputeExecutionStore = "node.compute.executionstore"
+const NodeComputeExecutionStoreType = "node.compute.executionstore.type"
+const NodeComputeExecutionStorePath = "node.compute.executionstore.path"
+const NodeComputeJobTimeouts = "node.compute.jobtimeouts"
+const NodeComputeJobTimeoutsJobExecutionTimeoutClientIDBypassList = "node.compute.jobtimeouts.jobexecutiontimeoutclientidbypasslist"
+const NodeComputeJobTimeoutsJobNegotiationTimeout = "node.compute.jobtimeouts.jobnegotiationtimeout"
+const NodeComputeJobTimeoutsMinJobExecutionTimeout = "node.compute.jobtimeouts.minjobexecutiontimeout"
+const NodeComputeJobTimeoutsMaxJobExecutionTimeout = "node.compute.jobtimeouts.maxjobexecutiontimeout"
+const NodeComputeJobTimeoutsDefaultJobExecutionTimeout = "node.compute.jobtimeouts.defaultjobexecutiontimeout"
+const NodeComputeJobSelection = "node.compute.jobselection"
+const NodeComputeJobSelectionLocality = "node.compute.jobselection.locality"
+const NodeComputeJobSelectionRejectStatelessJobs = "node.compute.jobselection.rejectstatelessjobs"
+const NodeComputeJobSelectionAcceptNetworkedJobs = "node.compute.jobselection.acceptnetworkedjobs"
+const NodeComputeJobSelectionProbeHTTP = "node.compute.jobselection.probehttp"
+const NodeComputeJobSelectionProbeExec = "node.compute.jobselection.probeexec"
+const NodeComputeLogging = "node.compute.logging"
+const NodeComputeLoggingLogRunningExecutionsInterval = "node.compute.logging.logrunningexecutionsinterval"
+const NodeComputeManifestCache = "node.compute.manifestcache"
+const NodeComputeManifestCacheSize = "node.compute.manifestcache.size"
+const NodeComputeManifestCacheDuration = "node.compute.manifestcache.duration"
+const NodeComputeManifestCacheFrequency = "node.compute.manifestcache.frequency"
+const NodeComputeLogStreamConfig = "node.compute.logstreamconfig"
+const NodeComputeLogStreamConfigChannelBufferSize = "node.compute.logstreamconfig.channelbuffersize"
+const NodeComputeLocalPublisher = "node.compute.localpublisher"
+const NodeComputeLocalPublisherAddress = "node.compute.localpublisher.address"
+const NodeComputeLocalPublisherPort = "node.compute.localpublisher.port"
+const NodeComputeLocalPublisherDirectory = "node.compute.localpublisher.directory"
+const NodeComputeControlPlaneSettings = "node.compute.controlplanesettings"
+const NodeComputeControlPlaneSettingsInfoUpdateFrequency = "node.compute.controlplanesettings.infoupdatefrequency"
+const NodeComputeControlPlaneSettingsResourceUpdateFrequency = "node.compute.controlplanesettings.resourceupdatefrequency"
+const NodeComputeControlPlaneSettingsHeartbeatFrequency = "node.compute.controlplanesettings.heartbeatfrequency"
+const NodeComputeControlPlaneSettingsHeartbeatTopic = "node.compute.controlplanesettings.heartbeattopic"
+const NodeRequester = "node.requester"
+const NodeRequesterJobDefaults = "node.requester.jobdefaults"
+const NodeRequesterJobDefaultsTotalTimeout = "node.requester.jobdefaults.totaltimeout"
+const NodeRequesterJobDefaultsExecutionTimeout = "node.requester.jobdefaults.executiontimeout"
+const NodeRequesterJobDefaultsQueueTimeout = "node.requester.jobdefaults.queuetimeout"
+const NodeRequesterExternalVerifierHook = "node.requester.externalverifierhook"
+const NodeRequesterJobSelectionPolicy = "node.requester.jobselectionpolicy"
+const NodeRequesterJobSelectionPolicyLocality = "node.requester.jobselectionpolicy.locality"
+const NodeRequesterJobSelectionPolicyRejectStatelessJobs = "node.requester.jobselectionpolicy.rejectstatelessjobs"
+const NodeRequesterJobSelectionPolicyAcceptNetworkedJobs = "node.requester.jobselectionpolicy.acceptnetworkedjobs"
+const NodeRequesterJobSelectionPolicyProbeHTTP = "node.requester.jobselectionpolicy.probehttp"
+const NodeRequesterJobSelectionPolicyProbeExec = "node.requester.jobselectionpolicy.probeexec"
+const NodeRequesterJobStore = "node.requester.jobstore"
+const NodeRequesterJobStoreType = "node.requester.jobstore.type"
+const NodeRequesterJobStorePath = "node.requester.jobstore.path"
+const NodeRequesterHousekeepingBackgroundTaskInterval = "node.requester.housekeepingbackgroundtaskinterval"
+const NodeRequesterNodeRankRandomnessRange = "node.requester.noderankrandomnessrange"
+const NodeRequesterOverAskForBidsFactor = "node.requester.overaskforbidsfactor"
+const NodeRequesterFailureInjectionConfig = "node.requester.failureinjectionconfig"
+const NodeRequesterFailureInjectionConfigIsBadActor = "node.requester.failureinjectionconfig.isbadactor"
+const NodeRequesterTranslationEnabled = "node.requester.translationenabled"
+const NodeRequesterEvaluationBroker = "node.requester.evaluationbroker"
+const NodeRequesterEvaluationBrokerEvalBrokerVisibilityTimeout = "node.requester.evaluationbroker.evalbrokervisibilitytimeout"
+const NodeRequesterEvaluationBrokerEvalBrokerInitialRetryDelay = "node.requester.evaluationbroker.evalbrokerinitialretrydelay"
+const NodeRequesterEvaluationBrokerEvalBrokerSubsequentRetryDelay = "node.requester.evaluationbroker.evalbrokersubsequentretrydelay"
+const NodeRequesterEvaluationBrokerEvalBrokerMaxRetryCount = "node.requester.evaluationbroker.evalbrokermaxretrycount"
+const NodeRequesterWorker = "node.requester.worker"
+const NodeRequesterWorkerWorkerCount = "node.requester.worker.workercount"
+const NodeRequesterWorkerWorkerEvalDequeueTimeout = "node.requester.worker.workerevaldequeuetimeout"
+const NodeRequesterWorkerWorkerEvalDequeueBaseBackoff = "node.requester.worker.workerevaldequeuebasebackoff"
+const NodeRequesterWorkerWorkerEvalDequeueMaxBackoff = "node.requester.worker.workerevaldequeuemaxbackoff"
+const NodeRequesterScheduler = "node.requester.scheduler"
+const NodeRequesterSchedulerQueueBackoff = "node.requester.scheduler.queuebackoff"
+const NodeRequesterSchedulerNodeOverSubscriptionFactor = "node.requester.scheduler.nodeoversubscriptionfactor"
+const NodeRequesterStorageProvider = "node.requester.storageprovider"
+const NodeRequesterStorageProviderS3 = "node.requester.storageprovider.s3"
+const NodeRequesterStorageProviderS3PreSignedURLDisabled = "node.requester.storageprovider.s3.presignedurldisabled"
+const NodeRequesterStorageProviderS3PreSignedURLExpiration = "node.requester.storageprovider.s3.presignedurlexpiration"
+const NodeRequesterTagCache = "node.requester.tagcache"
+const NodeRequesterTagCacheSize = "node.requester.tagcache.size"
+const NodeRequesterTagCacheDuration = "node.requester.tagcache.duration"
+const NodeRequesterTagCacheFrequency = "node.requester.tagcache.frequency"
+const NodeRequesterDefaultPublisher = "node.requester.defaultpublisher"
+const NodeRequesterControlPlaneSettings = "node.requester.controlplanesettings"
+const NodeRequesterControlPlaneSettingsHeartbeatCheckFrequency = "node.requester.controlplanesettings.heartbeatcheckfrequency"
+const NodeRequesterControlPlaneSettingsHeartbeatTopic = "node.requester.controlplanesettings.heartbeattopic"
+const NodeRequesterControlPlaneSettingsNodeDisconnectedAfter = "node.requester.controlplanesettings.nodedisconnectedafter"
+const NodeRequesterNodeInfoStoreTTL = "node.requester.nodeinfostorettl"
+const NodeRequesterManualNodeApproval = "node.requester.manualnodeapproval"
+const NodeDownloadURLRequestRetries = "node.downloadurlrequestretries"
+const NodeDownloadURLRequestTimeout = "node.downloadurlrequesttimeout"
+const NodeVolumeSizeRequestTimeout = "node.volumesizerequesttimeout"
+const NodeExecutorPluginPath = "node.executorpluginpath"
+const NodeComputeStoragePath = "node.computestoragepath"
+const NodeLoggingMode = "node.loggingmode"
+const NodeType = "node.type"
+const NodeAllowListedLocalPaths = "node.allowlistedlocalpaths"
+const NodeDisabledFeatures = "node.disabledfeatures"
+const NodeDisabledFeaturesEngines = "node.disabledfeatures.engines"
+const NodeDisabledFeaturesPublishers = "node.disabledfeatures.publishers"
+const NodeDisabledFeaturesStorages = "node.disabledfeatures.storages"
+const NodeLabels = "node.labels"
+const NodeWebUI = "node.webui"
+const NodeWebUIEnabled = "node.webui.enabled"
+const NodeWebUIPort = "node.webui.port"
+const NodeNetwork = "node.network"
+const NodeNetworkPort = "node.network.port"
+const NodeNetworkAdvertisedAddress = "node.network.advertisedaddress"
+const NodeNetworkAuthSecret = "node.network.authsecret"
+const NodeNetworkOrchestrators = "node.network.orchestrators"
+const NodeNetworkStoreDir = "node.network.storedir"
+const NodeNetworkCluster = "node.network.cluster"
+const NodeNetworkClusterName = "node.network.cluster.name"
+const NodeNetworkClusterPort = "node.network.cluster.port"
+const NodeNetworkClusterAdvertisedAddress = "node.network.cluster.advertisedaddress"
+const NodeNetworkClusterPeers = "node.network.cluster.peers"
+const NodeStrictVersionMatch = "node.strictversionmatch"
+const User = "user"
+const UserKeyPath = "user.keypath"
+const UserInstallationID = "user.installationid"
+const Metrics = "metrics"
+const MetricsEventTracerPath = "metrics.eventtracerpath"
+const Update = "update"
+const UpdateSkipChecks = "update.skipchecks"
+const UpdateCheckFrequency = "update.checkfrequency"
+const Auth = "auth"
+const AuthTokensPath = "auth.tokenspath"
+const AuthMethods = "auth.methods"
+const AuthAccessPolicyPath = "auth.accesspolicypath"
diff --git a/pkg/config_legacy/types/generated_descriptions.go b/pkg/config_legacy/types/generated_descriptions.go
new file mode 100644
index 0000000000..1c81667752
--- /dev/null
+++ b/pkg/config_legacy/types/generated_descriptions.go
@@ -0,0 +1,136 @@
+// Code generated by go generate; DO NOT EDIT.
+
+package types
+
+// ConfigDescriptions maps configuration paths to their descriptions
+var ConfigDescriptions = map[string]string{
+	NodeName:                                                    "No description available",
+	NodeNameProvider:                                            "No description available",
+	NodeClientAPIHost:                                           "Host is the hostname of an environment's public API servers.",
+	NodeClientAPIPort:                                           "Port is the port that an environment serves the public API on.",
+	NodeClientAPIClientTLSUseTLS:                                "Used for NodeConfig.ClientAPI, instructs the client to connect over TLS.  Auto enabled if Insecure or CACert are specified.",
+	NodeClientAPIClientTLSCACert:                                "Used for NodeConfig.ClientAPI, specifies the location of a ca certificate file (primarily for self-signed server certs). Will use HTTPS for requests.",
+	NodeClientAPIClientTLSInsecure:                              "Used for NodeConfig.ClientAPI, and when true instructs the client to use HTTPS, but not to attempt to verify the certificate.",
+	NodeClientAPITLSAutoCert:                                    "AutoCert specifies a hostname for a certificate to be obtained via ACME. This is only used by the server, and only by the requester node when it has a publicly resolvable domain name.",
+	NodeClientAPITLSAutoCertCachePath:                           "AutoCertCachePath specifies the directory where the autocert process will cache certificates to avoid rate limits.",
+	NodeClientAPITLSServerCertificate:                           "ServerCertificate specifies the location of a TLS certificate to be used by the requester to serve TLS requests",
+	NodeClientAPITLSServerKey:                                   "ServerKey is the TLS server key to match the certificate to allow the requester to server TLS.",
+	NodeClientAPITLSSelfSigned:                                  "SelfSignedCert will auto-generate a self-signed certificate for the requester node if TLS certificates have not been provided.",
+	NodeServerAPIHost:                                           "Host is the hostname of an environment's public API servers.",
+	NodeServerAPIPort:                                           "Port is the port that an environment serves the public API on.",
+	NodeServerAPIClientTLSUseTLS:                                "Used for NodeConfig.ClientAPI, instructs the client to connect over TLS.  Auto enabled if Insecure or CACert are specified.",
+	NodeServerAPIClientTLSCACert:                                "Used for NodeConfig.ClientAPI, specifies the location of a ca certificate file (primarily for self-signed server certs). Will use HTTPS for requests.",
+	NodeServerAPIClientTLSInsecure:                              "Used for NodeConfig.ClientAPI, and when true instructs the client to use HTTPS, but not to attempt to verify the certificate.",
+	NodeServerAPITLSAutoCert:                                    "AutoCert specifies a hostname for a certificate to be obtained via ACME. This is only used by the server, and only by the requester node when it has a publicly resolvable domain name.",
+	NodeServerAPITLSAutoCertCachePath:                           "AutoCertCachePath specifies the directory where the autocert process will cache certificates to avoid rate limits.",
+	NodeServerAPITLSServerCertificate:                           "ServerCertificate specifies the location of a TLS certificate to be used by the requester to serve TLS requests",
+	NodeServerAPITLSServerKey:                                   "ServerKey is the TLS server key to match the certificate to allow the requester to server TLS.",
+	NodeServerAPITLSSelfSigned:                                  "SelfSignedCert will auto-generate a self-signed certificate for the requester node if TLS certificates have not been provided.",
+	NodeIPFSConnect:                                             "Connect is the multiaddress to connect to for IPFS.",
+	NodeComputeCapacityIgnorePhysicalResourceLimits:             "No description available",
+	NodeComputeCapacityTotalResourceLimitsCPU:                   "No description available",
+	NodeComputeCapacityTotalResourceLimitsMemory:                "No description available",
+	NodeComputeCapacityTotalResourceLimitsDisk:                  "No description available",
+	NodeComputeCapacityTotalResourceLimitsGPU:                   "No description available",
+	NodeComputeCapacityJobResourceLimitsCPU:                     "No description available",
+	NodeComputeCapacityJobResourceLimitsMemory:                  "No description available",
+	NodeComputeCapacityJobResourceLimitsDisk:                    "No description available",
+	NodeComputeCapacityJobResourceLimitsGPU:                     "No description available",
+	NodeComputeCapacityDefaultJobResourceLimitsCPU:              "No description available",
+	NodeComputeCapacityDefaultJobResourceLimitsMemory:           "No description available",
+	NodeComputeCapacityDefaultJobResourceLimitsDisk:             "No description available",
+	NodeComputeCapacityDefaultJobResourceLimitsGPU:              "No description available",
+	NodeComputeExecutionStoreType:                               "Type is \"compute\", \"requester\" or both",
+	NodeComputeExecutionStorePath:                               "No description available",
+	NodeComputeJobTimeoutsJobExecutionTimeoutClientIDBypassList: "JobExecutionTimeoutClientIDBypassList is the list of clients that are allowed to bypass the job execution timeout check.",
+	NodeComputeJobTimeoutsJobNegotiationTimeout:                 "JobNegotiationTimeout default timeout value to hold a bid for a job",
+	NodeComputeJobTimeoutsMinJobExecutionTimeout:                "MinJobExecutionTimeout default value for the minimum execution timeout this compute node supports. Jobs with lower timeout requirements will not be bid on.",
+	NodeComputeJobTimeoutsMaxJobExecutionTimeout:                "MaxJobExecutionTimeout default value for the maximum execution timeout this compute node supports. Jobs with higher timeout requirements will not be bid on.",
+	NodeComputeJobTimeoutsDefaultJobExecutionTimeout:            "DefaultJobExecutionTimeout default value for the execution timeout this compute node will assign to jobs with no timeout requirement defined.",
+	NodeComputeJobSelectionLocality:                             "No description available",
+	NodeComputeJobSelectionRejectStatelessJobs:                  "No description available",
+	NodeComputeJobSelectionAcceptNetworkedJobs:                  "No description available",
+	NodeComputeJobSelectionProbeHTTP:                            "No description available",
+	NodeComputeJobSelectionProbeExec:                            "No description available",
+	NodeComputeLoggingLogRunningExecutionsInterval:              "logging running executions",
+	NodeComputeManifestCacheSize:                                "No description available",
+	NodeComputeManifestCacheDuration:                            "No description available",
+	NodeComputeManifestCacheFrequency:                           "No description available",
+	NodeComputeLogStreamConfigChannelBufferSize:                 "How many messages to buffer in the log stream channel, per stream",
+	NodeComputeLocalPublisherAddress:                            "No description available",
+	NodeComputeLocalPublisherPort:                               "Port is the port that an environment serves the public API on.",
+	NodeComputeLocalPublisherDirectory:                          "No description available",
+	NodeComputeControlPlaneSettingsInfoUpdateFrequency:          "The frequency with which the compute node will send node info (inc current labels) to the controlling requester node.",
+	NodeComputeControlPlaneSettingsResourceUpdateFrequency:      "How often the compute node will send current resource availability to the requester node.",
+	NodeComputeControlPlaneSettingsHeartbeatFrequency:           "How often the compute node will send a heartbeat to the requester node to let it know that the compute node is still alive. This should be less than the requester's configured heartbeat timeout to avoid flapping.",
+	NodeComputeControlPlaneSettingsHeartbeatTopic:               "This is the pubsub topic that the compute node will use to send heartbeats to the requester node.",
+	NodeRequesterJobDefaultsTotalTimeout:                        "No description available",
+	NodeRequesterJobDefaultsExecutionTimeout:                    "No description available",
+	NodeRequesterJobDefaultsQueueTimeout:                        "No description available",
+	NodeRequesterExternalVerifierHook:                           "URL where to send external verification requests to.",
+	NodeRequesterJobSelectionPolicyLocality:                     "No description available",
+	NodeRequesterJobSelectionPolicyRejectStatelessJobs:          "No description available",
+	NodeRequesterJobSelectionPolicyAcceptNetworkedJobs:          "No description available",
+	NodeRequesterJobSelectionPolicyProbeHTTP:                    "No description available",
+	NodeRequesterJobSelectionPolicyProbeExec:                    "No description available",
+	NodeRequesterJobStoreType:                                   "Type is \"compute\", \"requester\" or both",
+	NodeRequesterJobStorePath:                                   "No description available",
+	NodeRequesterHousekeepingBackgroundTaskInterval:             "No description available",
+	NodeRequesterNodeRankRandomnessRange:                        "No description available",
+	NodeRequesterOverAskForBidsFactor:                           "No description available",
+	NodeRequesterFailureInjectionConfigIsBadActor:               "No description available",
+	NodeRequesterTranslationEnabled:                             "No description available",
+	NodeRequesterEvaluationBrokerEvalBrokerVisibilityTimeout:    "No description available",
+	NodeRequesterEvaluationBrokerEvalBrokerInitialRetryDelay:    "No description available",
+	NodeRequesterEvaluationBrokerEvalBrokerSubsequentRetryDelay: "No description available",
+	NodeRequesterEvaluationBrokerEvalBrokerMaxRetryCount:        "No description available",
+	NodeRequesterWorkerWorkerCount:                              "No description available",
+	NodeRequesterWorkerWorkerEvalDequeueTimeout:                 "No description available",
+	NodeRequesterWorkerWorkerEvalDequeueBaseBackoff:             "No description available",
+	NodeRequesterWorkerWorkerEvalDequeueMaxBackoff:              "No description available",
+	NodeRequesterSchedulerQueueBackoff:                          "No description available",
+	NodeRequesterSchedulerNodeOverSubscriptionFactor:            "No description available",
+	NodeRequesterStorageProviderS3PreSignedURLDisabled:          "No description available",
+	NodeRequesterStorageProviderS3PreSignedURLExpiration:        "No description available",
+	NodeRequesterTagCacheSize:                                   "No description available",
+	NodeRequesterTagCacheDuration:                               "No description available",
+	NodeRequesterTagCacheFrequency:                              "No description available",
+	NodeRequesterDefaultPublisher:                               "No description available",
+	NodeRequesterControlPlaneSettingsHeartbeatCheckFrequency:    "This setting is the time period after which a compute node is considered to be unresponsive. If the compute node misses two of these frequencies, it will be marked as unknown.  The compute node should have a frequency setting less than this one to ensure that it does not keep switching between unknown and active too frequently.",
+	NodeRequesterControlPlaneSettingsHeartbeatTopic:             "This is the pubsub topic that the compute node will use to send heartbeats to the requester node.",
+	NodeRequesterControlPlaneSettingsNodeDisconnectedAfter:      "This is the time period after which a compute node is considered to be disconnected. If the compute node does not deliver a heartbeat every `NodeDisconnectedAfter` then it is considered disconnected.",
+	NodeRequesterNodeInfoStoreTTL:                               "No description available",
+	NodeRequesterManualNodeApproval:                             "ManualNodeApproval is a flag that determines if nodes should be manually approved or not. By default, nodes are auto-approved to simplify upgrades, by setting this property to true, nodes will need to be manually approved before they are included in node selection.",
+	NodeDownloadURLRequestRetries:                               "No description available",
+	NodeDownloadURLRequestTimeout:                               "No description available",
+	NodeVolumeSizeRequestTimeout:                                "No description available",
+	NodeExecutorPluginPath:                                      "No description available",
+	NodeComputeStoragePath:                                      "TODO(forrest) [refactor]: rename this to ExecutorStoragePath",
+	NodeLoggingMode:                                             "No description available",
+	NodeType:                                                    "Type is \"compute\", \"requester\" or both",
+	NodeAllowListedLocalPaths:                                   "AllowListedLocalPaths contains local paths that are allowed to be mounted into jobs",
+	NodeDisabledFeaturesEngines:                                 "No description available",
+	NodeDisabledFeaturesPublishers:                              "No description available",
+	NodeDisabledFeaturesStorages:                                "No description available",
+	NodeLabels:                                                  "Labels to apply to the node that can be used for node selection and filtering",
+	NodeWebUIEnabled:                                            "No description available",
+	NodeWebUIPort:                                               "Port is the port that an environment serves the public API on.",
+	NodeNetworkPort:                                             "Port is the port that an environment serves the public API on.",
+	NodeNetworkAdvertisedAddress:                                "No description available",
+	NodeNetworkAuthSecret:                                       "No description available",
+	NodeNetworkOrchestrators:                                    "No description available",
+	NodeNetworkStoreDir:                                         "No description available",
+	NodeNetworkClusterName:                                      "No description available",
+	NodeNetworkClusterPort:                                      "Port is the port that an environment serves the public API on.",
+	NodeNetworkClusterAdvertisedAddress:                         "No description available",
+	NodeNetworkClusterPeers:                                     "No description available",
+	NodeStrictVersionMatch:                                      "No description available",
+	UserKeyPath:                                                 "No description available",
+	UserInstallationID:                                          "No description available",
+	MetricsEventTracerPath:                                      "No description available",
+	UpdateSkipChecks:                                            "No description available",
+	UpdateCheckFrequency:                                        "No description available",
+	AuthTokensPath:                                              "TokensPath is the location where a state file of tokens will be stored. By default it will be local to the Bacalhau repo, but can be any location in the host filesystem. Tokens are sensitive and should be stored in a location that is only readable to the current user.",
+	AuthMethods:                                                 "Methods maps \"method names\" to authenticator implementations. A method name is a human-readable string chosen by the person configuring the system that is shown to users to help them pick the authentication method they want to use. There can be multiple usages of the same Authenticator *type* but with different configs and parameters, each identified with a unique method name.  For example, if an implementation wants to allow users to log in with Github or Bitbucket, they might both use an authenticator implementation of type \"oidc\", and each would appear once on this provider with key / method name \"github\" and \"bitbucket\".  By default, only a single authentication method that accepts authentication via client keys will be enabled.",
+	AuthAccessPolicyPath:                                        "AccessPolicyPath is the path to a file or directory that will be loaded as the policy to apply to all inbound API requests. If unspecified, a policy that permits access to all API endpoints to both authenticated and unauthenticated users (the default as of v1.2.0) will be used.",
+}
diff --git a/pkg/config/types/generated_viper_defaults.go b/pkg/config_legacy/types/generated_viper_defaults.go
similarity index 100%
rename from pkg/config/types/generated_viper_defaults.go
rename to pkg/config_legacy/types/generated_viper_defaults.go
diff --git a/pkg/config/types/node.go b/pkg/config_legacy/types/node.go
similarity index 100%
rename from pkg/config/types/node.go
rename to pkg/config_legacy/types/node.go
diff --git a/pkg/config/types/requester.go b/pkg/config_legacy/types/requester.go
similarity index 100%
rename from pkg/config/types/requester.go
rename to pkg/config_legacy/types/requester.go
diff --git a/pkg/config/types/storagetype.go b/pkg/config_legacy/types/storagetype.go
similarity index 100%
rename from pkg/config/types/storagetype.go
rename to pkg/config_legacy/types/storagetype.go
diff --git a/pkg/config/types/storagetype_string.go b/pkg/config_legacy/types/storagetype_string.go
similarity index 100%
rename from pkg/config/types/storagetype_string.go
rename to pkg/config_legacy/types/storagetype_string.go
diff --git a/pkg/devstack/devstack.go b/pkg/devstack/devstack.go
index fc01b8fdc3..9288e36ea9 100644
--- a/pkg/devstack/devstack.go
+++ b/pkg/devstack/devstack.go
@@ -16,6 +16,7 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store/boltdb"
 	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	boltjobstore "github.com/bacalhau-project/bacalhau/pkg/jobstore/boltdb"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
@@ -69,7 +70,7 @@ type DevStack struct {
 //nolint:funlen,gocyclo
 func Setup(
 	ctx context.Context,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	cm *system.CleanupManager,
 	fsRepo *repo.FsRepo,
 	opts ...ConfigOption,
@@ -186,19 +187,17 @@ func Setup(
 			if err != nil {
 				return nil, errors.Wrap(err, "failed to get free port for local publisher")
 			}
-
-			localPublisherConfig := types.LocalPublisherConfig{
+			cfg.Publishers.Types.Local = types.LocalPublisher{
 				Port:      fport,
-				Address:   "127.0.0.1", //nolint:gomnd
+				Address:   "127.0.0.1",
 				Directory: path.Join(repoPath, fmt.Sprintf("local-publisher-%d", i)),
 			}
-			err = os.MkdirAll(localPublisherConfig.Directory, util.OS_USER_RWX)
+
+			err = os.MkdirAll(cfg.Publishers.Types.Local.Directory, util.OS_USER_RWX)
 			if err != nil {
 				return nil, fmt.Errorf("failed to create local publisher directory %s: %w",
-					localPublisherConfig.Directory, err)
+					cfg.Publishers.Types.Local.Directory, err)
 			}
-
-			stackConfig.ComputeConfig.LocalPublisher = localPublisherConfig
 		}
 
 		nodeConfig := node.NodeConfig{
@@ -222,7 +221,7 @@ func Setup(
 			AuthConfig: types.AuthConfig{
 				Methods: map[string]types.AuthenticatorConfig{
 					"ClientKey": {
-						Type: authn.MethodTypeChallenge,
+						Type: string(authn.MethodTypeChallenge),
 					},
 				},
 			},
@@ -281,7 +280,7 @@ func Setup(
 	}, nil
 }
 
-func setStorePaths(ctx context.Context, cfg types.BacalhauConfig, nodeConfig *node.NodeConfig) error {
+func setStorePaths(ctx context.Context, cfg types.Bacalhau, nodeConfig *node.NodeConfig) error {
 	nodeID := nodeConfig.NodeID
 	orchestratorDir, err := cfg.OrchestratorDir()
 	if err != nil {
@@ -309,7 +308,7 @@ func setStorePaths(ctx context.Context, cfg types.BacalhauConfig, nodeConfig *no
 
 //nolint:funlen
 func (stack *DevStack) PrintNodeInfo(ctx context.Context, fsRepo *repo.FsRepo, cm *system.CleanupManager) (string, error) {
-	if !config.DevstackGetShouldPrintInfo() {
+	if !config_legacy.DevstackGetShouldPrintInfo() {
 		return "", nil
 	}
 
@@ -338,12 +337,12 @@ export BACALHAU_API_PORT_%d=%d`,
 	summaryBuilder := strings.Builder{}
 	summaryBuilder.WriteString(fmt.Sprintf(
 		"export %s=%s\n",
-		config.KeyAsEnvVar(types.NodeClientAPIHost),
+		config.KeyAsEnvVar(types.APIHostKey),
 		devStackAPIHost,
 	))
 	summaryBuilder.WriteString(fmt.Sprintf(
 		"export %s=%s\n",
-		config.KeyAsEnvVar(types.NodeClientAPIPort),
+		config.KeyAsEnvVar(types.APIPortKey),
 		devStackAPIPort,
 	))
 
diff --git a/pkg/docker/cache.go b/pkg/docker/cache.go
index c1f527125d..095e748e1b 100644
--- a/pkg/docker/cache.go
+++ b/pkg/docker/cache.go
@@ -6,13 +6,13 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
-func NewManifestCache(cfg types.DockerCacheConfig) cache.Cache[ImageManifest] {
+func NewManifestCache(cfg types.DockerManifestCache) cache.Cache[ImageManifest] {
 	// Used by compute nodes to map requester provided image identifiers (with
 	// digest) to
 	c, _ := basic.NewCache[ImageManifest](
-		basic.WithCleanupFrequency(cfg.Frequency.AsTimeDuration()),
+		basic.WithCleanupFrequency(cfg.Refresh.AsTimeDuration()),
 		basic.WithMaxCost(cfg.Size),
-		basic.WithTTL(cfg.Duration.AsTimeDuration()),
+		basic.WithTTL(cfg.TTL.AsTimeDuration()),
 	)
 	return c
 }
diff --git a/pkg/docker/docker.go b/pkg/docker/docker.go
index 1448eb2aca..aebf927b8b 100644
--- a/pkg/docker/docker.go
+++ b/pkg/docker/docker.go
@@ -31,7 +31,7 @@ import (
 	"go.ptx.dk/multierrgroup"
 	"golang.org/x/exp/slices"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/docker/tracing"
 	"github.com/bacalhau-project/bacalhau/pkg/util/closer"
 )
@@ -39,7 +39,7 @@ import (
 type ImageUnavailableError struct {
 	Verb  string
 	Image string
-	Creds config.DockerCredentials
+	Creds config_legacy.DockerCredentials
 	Err   error
 }
 
@@ -55,14 +55,14 @@ func (die ImageUnavailableError) Error() string {
 func (die ImageUnavailableError) Hint() string {
 	if !die.Creds.IsValid() {
 		return "If the image is private, supply the node with valid Docker login credentials " +
-			"using the " + config.DockerUsernameEnvVar + " and " + config.DockerPasswordEnvVar +
+			"using the " + config_legacy.DockerUsernameEnvVar + " and " + config_legacy.DockerPasswordEnvVar +
 			" environment variables"
 	}
 
 	return ""
 }
 
-func NewImageInspectError(image string, creds config.DockerCredentials, err error) error {
+func NewImageInspectError(image string, creds config_legacy.DockerCredentials, err error) error {
 	return ImageUnavailableError{
 		Verb:  "inspect",
 		Image: image,
@@ -71,7 +71,7 @@ func NewImageInspectError(image string, creds config.DockerCredentials, err erro
 	}
 }
 
-func NewImagePullError(image string, creds config.DockerCredentials, err error) error {
+func NewImagePullError(image string, creds config_legacy.DockerCredentials, err error) error {
 	return ImageUnavailableError{
 		Verb:  "pull",
 		Image: image,
@@ -248,7 +248,7 @@ func (c *Client) RemoveContainer(ctx context.Context, id string) error {
 	return nil
 }
 
-func (c *Client) ImagePlatforms(ctx context.Context, image string, dockerCreds config.DockerCredentials) ([]v1.Platform, error) {
+func (c *Client) ImagePlatforms(ctx context.Context, image string, dockerCreds config_legacy.DockerCredentials) ([]v1.Platform, error) {
 	info, _, err := c.ImageInspectWithRaw(ctx, image)
 	if err == nil {
 		return []v1.Platform{
@@ -346,7 +346,7 @@ func (c *Client) SupportedPlatforms(ctx context.Context) ([]v1.Platform, error)
 //
 // This is the image that will finally be installed.
 func (c *Client) ImageDistribution(
-	ctx context.Context, image string, creds config.DockerCredentials,
+	ctx context.Context, image string, creds config_legacy.DockerCredentials,
 ) (*ImageManifest, error) {
 	// Check whether the requested image (e.g. ubuntu:kinetic) is available from
 	// the local docker daemon from a previous download, and use that digest.
@@ -394,7 +394,7 @@ func (c *Client) ImageDistribution(
 	return manifest, nil
 }
 
-func (c *Client) PullImage(ctx context.Context, img string, dockerCreds config.DockerCredentials) error {
+func (c *Client) PullImage(ctx context.Context, img string, dockerCreds config_legacy.DockerCredentials) error {
 	_, _, err := c.ImageInspectWithRaw(ctx, img)
 	if err == nil {
 		// If there is no error, then return immediately as it means we have the docker image
@@ -496,7 +496,7 @@ func logImagePullStatus(ctx context.Context, m *sync.Map) {
 	e.Msg("Pulling layers")
 }
 
-func getAuthToken(ctx context.Context, image string, dockerCreds config.DockerCredentials) string {
+func getAuthToken(ctx context.Context, image string, dockerCreds config_legacy.DockerCredentials) string {
 	if dockerCreds.IsValid() {
 		// We only currently support auth for the default registry, so any
 		// pulls for `image` or `user/image` should be okay, anything trying
diff --git a/pkg/downloader/util/utils.go b/pkg/downloader/util/utils.go
index ff518be0f6..2167141f87 100644
--- a/pkg/downloader/util/utils.go
+++ b/pkg/downloader/util/utils.go
@@ -3,6 +3,7 @@ package util
 import (
 	"context"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader/http"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader/ipfs"
@@ -12,19 +13,27 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 )
 
-func NewStandardDownloaders(ctx context.Context, ipfsConnect string) (downloader.DownloaderProvider, error) {
-	providers := map[string]downloader.Downloader{
-		models.StorageSourceS3PreSigned: s3signed.NewDownloader(s3signed.DownloaderParams{
+func NewStandardDownloaders(ctx context.Context, cfg types.ResultDownloaders) (downloader.DownloaderProvider, error) {
+	providers := make(map[string]downloader.Downloader)
+
+	if cfg.IsNotDisabled(models.StorageSourceS3PreSigned) {
+		providers[models.StorageSourceS3PreSigned] = s3signed.NewDownloader(s3signed.DownloaderParams{
 			HTTPDownloader: http.NewHTTPDownloader(),
-		}),
-		models.StorageSourceURL: http.NewHTTPDownloader(),
+		})
+	}
+
+	if cfg.IsNotDisabled(models.StorageSourceURL) {
+		providers[models.StorageSourceURL] = http.NewHTTPDownloader()
 	}
-	if ipfsConnect != "" {
-		ipfsClient, err := ipfs_client.NewClient(ctx, ipfsConnect)
-		if err != nil {
-			return nil, err
+
+	if cfg.IsNotDisabled(models.StorageSourceIPFS) {
+		if cfg.Types.IPFS.Endpoint != "" {
+			ipfsClient, err := ipfs_client.NewClient(ctx, cfg.Types.IPFS.Endpoint)
+			if err != nil {
+				return nil, err
+			}
+			providers[models.StorageSourceIPFS] = ipfs.NewIPFSDownloader(ipfsClient)
 		}
-		providers[models.StorageSourceIPFS] = ipfs.NewIPFSDownloader(ipfsClient)
 	}
 
 	return provider.NewMappedProvider(providers), nil
diff --git a/pkg/executor/docker/bidstrategy/semantic/image_platform.go b/pkg/executor/docker/bidstrategy/semantic/image_platform.go
index c0d713c2de..1cb120801b 100644
--- a/pkg/executor/docker/bidstrategy/semantic/image_platform.go
+++ b/pkg/executor/docker/bidstrategy/semantic/image_platform.go
@@ -5,6 +5,7 @@ import (
 	"sync"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	dockermodels "github.com/bacalhau-project/bacalhau/pkg/executor/docker/models"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 
@@ -12,7 +13,6 @@ import (
 
 	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy"
 	"github.com/bacalhau-project/bacalhau/pkg/cache"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/docker"
 )
 
@@ -23,7 +23,7 @@ var _ bidstrategy.SemanticBidStrategy = (*ImagePlatformBidStrategy)(nil)
 var ManifestCache cache.Cache[docker.ImageManifest]
 var mu sync.Mutex
 
-func NewImagePlatformBidStrategy(client *docker.Client, cfg types.DockerCacheConfig) *ImagePlatformBidStrategy {
+func NewImagePlatformBidStrategy(client *docker.Client, cfg types.DockerManifestCache) *ImagePlatformBidStrategy {
 	mu.Lock()
 	// We will create the local reference to a manifest cache on demand,
 	// ensuring that we lock access to the cache here to avoid race
@@ -63,7 +63,7 @@ func (s *ImagePlatformBidStrategy) ShouldBid(
 	if !found {
 		log.Ctx(ctx).Debug().Str("Image", dockerEngine.Image).Msg("Image not found in manifest cache")
 
-		creds := config.GetDockerCredentials()
+		creds := config_legacy.GetDockerCredentials()
 
 		m, err := s.client.ImageDistribution(ctx, dockerEngine.Image, creds)
 		if err != nil {
diff --git a/pkg/executor/docker/executor.go b/pkg/executor/docker/executor.go
index 31d7fe63aa..3e60657ed4 100644
--- a/pkg/executor/docker/executor.go
+++ b/pkg/executor/docker/executor.go
@@ -18,12 +18,12 @@ import (
 	"go.uber.org/atomic"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	dockermodels "github.com/bacalhau-project/bacalhau/pkg/executor/docker/models"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	pkgUtil "github.com/bacalhau-project/bacalhau/pkg/util"
 
 	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/docker"
 	"github.com/bacalhau-project/bacalhau/pkg/executor"
 	"github.com/bacalhau-project/bacalhau/pkg/executor/docker/bidstrategy/semantic"
@@ -53,12 +53,12 @@ type Executor struct {
 	activeFlags       map[string]chan struct{}
 	complete          map[string]chan struct{}
 	client            *docker.Client
-	dockerCacheConfig types.DockerCacheConfig
+	dockerCacheConfig types.DockerManifestCache
 }
 
 func NewExecutor(
 	id string,
-	dockerCacheCfg types.DockerCacheConfig,
+	dockerCacheCfg types.Docker,
 ) (*Executor, error) {
 	dockerClient, err := docker.NewDockerClient()
 	if err != nil {
@@ -70,7 +70,7 @@ func NewExecutor(
 		client:            dockerClient,
 		activeFlags:       make(map[string]chan struct{}),
 		complete:          make(map[string]chan struct{}),
-		dockerCacheConfig: dockerCacheCfg,
+		dockerCacheConfig: dockerCacheCfg.ManifestCache,
 	}
 
 	return de, nil
@@ -80,7 +80,7 @@ func (e *Executor) Shutdown(ctx context.Context) error {
 	// We have to use a detached context, rather than the one passed in to `NewExecutor`, as it may have already been
 	// canceled and so would prevent us from performing any cleanup work.
 	safeCtx := pkgUtil.NewDetachedContext(ctx)
-	if config.ShouldKeepStack() || !e.client.IsInstalled(safeCtx) {
+	if config_legacy.ShouldKeepStack() || !e.client.IsInstalled(safeCtx) {
 		return nil
 	}
 
@@ -165,7 +165,7 @@ func (e *Executor) Start(ctx context.Context, request *executor.RunCommandReques
 		containerID: containerID,
 		resultsDir:  request.ResultsDir,
 		limits:      request.OutputLimits,
-		keepStack:   config.ShouldKeepStack(),
+		keepStack:   config_legacy.ShouldKeepStack(),
 		waitCh:      make(chan bool),
 		activeCh:    make(chan bool),
 		running:     atomic.NewBool(false),
@@ -363,7 +363,7 @@ func (e *Executor) newDockerJobContainer(ctx context.Context, params *dockerJobC
 	}
 
 	if _, set := os.LookupEnv("SKIP_IMAGE_PULL"); !set {
-		dockerCreds := config.GetDockerCredentials()
+		dockerCreds := config_legacy.GetDockerCredentials()
 		if pullErr := e.client.PullImage(ctx, dockerArgs.Image, dockerCreds); pullErr != nil {
 			return container.CreateResponse{}, docker.NewImagePullError(dockerArgs.Image, dockerCreds, pullErr)
 		}
diff --git a/pkg/executor/docker/network.go b/pkg/executor/docker/network.go
index 62ce85ef92..73c22df42a 100644
--- a/pkg/executor/docker/network.go
+++ b/pkg/executor/docker/network.go
@@ -14,9 +14,9 @@ import (
 	pkgerrors "github.com/pkg/errors"
 	"github.com/rs/zerolog/log"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
 )
 
@@ -104,7 +104,7 @@ func (e *Executor) createHTTPGateway(
 	networkConfig *models.NetworkConfig,
 ) (*network.Inspect, *net.TCPAddr, error) {
 	// Get the gateway image if we don't have it already
-	err := e.client.PullImage(ctx, httpGatewayImage, config.GetDockerCredentials())
+	err := e.client.PullImage(ctx, httpGatewayImage, config_legacy.GetDockerCredentials())
 	if err != nil {
 		return nil, nil, pkgerrors.Wrap(err, "error pulling gateway image")
 	}
diff --git a/pkg/executor/plugins/executors/docker/main.go b/pkg/executor/plugins/executors/docker/main.go
index 760c03db55..b560e1b5f7 100644
--- a/pkg/executor/plugins/executors/docker/main.go
+++ b/pkg/executor/plugins/executors/docker/main.go
@@ -31,14 +31,14 @@ func main() { // Create an hclog.Logger
 		Level:  hclog.Trace,
 	})
 
-	cfg := types.DockerCacheConfig{
-		Size:      1000,
-		Duration:  types.Duration(1 * time.Hour),
-		Frequency: types.Duration(1 * time.Hour),
+	cfg := types.DockerManifestCache{
+		Size:    1000,
+		TTL:     types.Duration(1 * time.Hour),
+		Refresh: types.Duration(1 * time.Hour),
 	}
 	dockerExecutor, err := docker.NewExecutor(
 		"bacalhau-pluggable-executor-docker",
-		cfg,
+		types.Docker{ManifestCache: cfg},
 	)
 	if err != nil {
 		logger.Error(err.Error())
diff --git a/pkg/executor/util/utils.go b/pkg/executor/util/utils.go
index c02304d1a6..ba2f7ef71e 100644
--- a/pkg/executor/util/utils.go
+++ b/pkg/executor/util/utils.go
@@ -34,59 +34,61 @@ type StandardExecutorOptions struct {
 	DockerID string
 }
 
-func NewStandardStorageProvider(
-	getVolumeTimeout time.Duration,
-	urlDownloadTimeout time.Duration,
-	urlMaxRetries int,
-	options StandardStorageProviderOptions,
-) (storage.StorageProvider, error) {
-	urlDownloadStorage := urldownload.NewStorage(urlDownloadTimeout, urlMaxRetries)
-
-	inlineStorage := inline.NewStorage()
-
-	s3Storage, err := configureS3StorageProvider(getVolumeTimeout)
-	if err != nil {
-		return nil, err
-	}
-
-	localDirectoryStorage, err := localdirectory.NewStorageProvider(localdirectory.StorageProviderParams{
-		AllowedPaths: localdirectory.ParseAllowPaths(options.AllowListedLocalPaths),
-	})
-	if err != nil {
-		return nil, err
+func NewStandardStorageProvider(cfg types.Bacalhau) (storage.StorageProvider, error) {
+	providers := make(map[string]storage.Storage)
+
+	if cfg.InputSources.IsNotDisabled(models.StorageSourceURL) {
+		providers[models.StorageSourceURL] = tracing.Wrap(urldownload.NewStorage(
+			time.Duration(cfg.InputSources.ReadTimeout),
+			cfg.InputSources.MaxRetryCount,
+		))
 	}
 
-	providers := map[string]storage.Storage{
-		models.StorageSourceURL:            tracing.Wrap(urlDownloadStorage),
-		models.StorageSourceInline:         tracing.Wrap(inlineStorage),
-		models.StorageSourceS3:             tracing.Wrap(s3Storage),
-		models.StorageSourceLocalDirectory: tracing.Wrap(localDirectoryStorage),
+	if cfg.InputSources.IsNotDisabled(models.StorageSourceInline) {
+		providers[models.StorageSourceInline] = tracing.Wrap(inline.NewStorage())
 	}
 
-	if options.IPFSConnect != "" {
-		ipfsClient, err := ipfs.NewClient(context.Background(), options.IPFSConnect)
+	if cfg.InputSources.IsNotDisabled(models.StorageSourceS3) {
+		s3Cfg, err := s3helper.DefaultAWSConfig()
 		if err != nil {
 			return nil, err
 		}
-		ipfsStorage, err := ipfs_storage.NewStorage(*ipfsClient, getVolumeTimeout)
+		clientProvider := s3helper.NewClientProvider(s3helper.ClientProviderParams{
+			AWSConfig: s3Cfg,
+		})
+		providers[models.StorageSourceS3] = tracing.Wrap(s3.NewStorage(
+			time.Duration(cfg.InputSources.ReadTimeout),
+			clientProvider,
+		))
+	}
+
+	if cfg.InputSources.IsNotDisabled(models.StorageSourceLocalDirectory) {
+		var err error
+		providers[models.StorageSourceLocalDirectory], err = localdirectory.NewStorageProvider(
+			localdirectory.StorageProviderParams{
+				AllowedPaths: localdirectory.ParseAllowPaths(cfg.Compute.AllowListedLocalPaths),
+			})
 		if err != nil {
 			return nil, err
 		}
-		providers[models.StorageSourceIPFS] = tracing.Wrap(ipfsStorage)
 	}
-	return provider.NewMappedProvider(providers), nil
-}
 
-func configureS3StorageProvider(getVolumeTimeout time.Duration) (*s3.StorageProvider, error) {
-	cfg, err := s3helper.DefaultAWSConfig()
-	if err != nil {
-		return nil, err
+	if cfg.InputSources.IsNotDisabled(models.StorageSourceIPFS) {
+		if cfg.InputSources.Types.IPFS.Endpoint != "" {
+			ipfsClient, err := ipfs.NewClient(context.Background(), cfg.InputSources.Types.IPFS.Endpoint)
+			if err != nil {
+				return nil, err
+			}
+			ipfsStorage, err := ipfs_storage.NewStorage(*ipfsClient, time.Duration(cfg.InputSources.ReadTimeout))
+			if err != nil {
+				return nil, err
+			}
+			providers[models.StorageSourceIPFS] = tracing.Wrap(ipfsStorage)
+
+		}
 	}
-	clientProvider := s3helper.NewClientProvider(s3helper.ClientProviderParams{
-		AWSConfig: cfg,
-	})
-	s3Storage := s3.NewStorage(getVolumeTimeout, clientProvider)
-	return s3Storage, nil
+
+	return provider.NewMappedProvider(providers), nil
 }
 
 func NewNoopStorageProvider(
@@ -99,23 +101,28 @@ func NewNoopStorageProvider(
 }
 
 func NewStandardExecutorProvider(
-	dockerCacheCfg types.DockerCacheConfig,
+	cfg types.EngineConfig,
 	executorOptions StandardExecutorOptions,
 ) (executor.ExecutorProvider, error) {
-	dockerExecutor, err := docker.NewExecutor(executorOptions.DockerID, dockerCacheCfg)
-	if err != nil {
-		return nil, err
+	providers := make(map[string]executor.Executor)
+
+	if cfg.IsNotDisabled(models.EngineDocker) {
+		var err error
+		providers[models.EngineDocker], err = docker.NewExecutor(executorOptions.DockerID, cfg.Types.Docker)
+		if err != nil {
+			return nil, err
+		}
 	}
 
-	wasmExecutor, err := wasm.NewExecutor()
-	if err != nil {
-		return nil, err
+	if cfg.IsNotDisabled(models.EngineWasm) {
+		wasmExecutor, err := wasm.NewExecutor()
+		if err != nil {
+			return nil, err
+		}
+		providers[models.EngineWasm] = wasmExecutor
 	}
 
-	return provider.NewMappedProvider(map[string]executor.Executor{
-		models.EngineDocker: dockerExecutor,
-		models.EngineWasm:   wasmExecutor,
-	}), nil
+	return provider.NewMappedProvider(providers), nil
 }
 
 // return noop executors for all engines
diff --git a/pkg/job/parser.go b/pkg/job/parser.go
index bbcca7f7a4..c80ce47a30 100644
--- a/pkg/job/parser.go
+++ b/pkg/job/parser.go
@@ -20,6 +20,7 @@ const (
 // roundtrip through legacy structures.
 func ParsePublisherString(publisher string) (*models.SpecConfig, error) {
 	publisher = strings.Trim(publisher, " '\"")
+	publisher = strings.ToLower(publisher)
 	csvReader := csv.NewReader(strings.NewReader(publisher))
 	fields, err := csvReader.Read()
 	if err != nil {
diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go
index 13689ddbd4..c053cd9b94 100644
--- a/pkg/logger/logger.go
+++ b/pkg/logger/logger.go
@@ -39,7 +39,7 @@ const (
 func ParseLogMode(s string) (LogMode, error) {
 	lm := []LogMode{LogModeDefault, LogModeStation, LogModeJSON, LogModeCombined, LogModeEvent}
 	for _, logMode := range lm {
-		if s == string(logMode) {
+		if strings.ToLower(s) == strings.ToLower(string(logMode)) {
 			return logMode, nil
 		}
 	}
@@ -57,11 +57,12 @@ func init() { //nolint:gochecknoinits
 		strings.HasSuffix(os.Args[0], ".test") ||
 		flag.Lookup("test.v") != nil ||
 		flag.Lookup("test.run") != nil {
-		configureLogging(defaultLogging())
+		configureLogging(zerolog.DebugLevel, defaultLogging())
 		return
 	}
 
-	configureLogging(bufferLogs())
+	// the default log level when not running a test is ERROR
+	configureLogging(zerolog.ErrorLevel, bufferLogs())
 }
 
 func ErrOrDebug(err error) zerolog.Level {
@@ -81,15 +82,25 @@ type tTesting interface {
 func ConfigureTestLogging(t tTesting) {
 	oldLogger := log.Logger
 	oldContextLogger := zerolog.DefaultContextLogger
-	configureLogging(zerolog.NewConsoleWriter(zerolog.ConsoleTestWriter(t), defaultLogFormat))
+	configureLogging(zerolog.DebugLevel, zerolog.NewConsoleWriter(zerolog.ConsoleTestWriter(t), defaultLogFormat))
 	t.Cleanup(func() {
 		log.Logger = oldLogger
 		zerolog.DefaultContextLogger = oldContextLogger
 	})
 }
 
-func ConfigureLogging(mode LogMode) {
+func ConfigureLogging(modeStr, levelStr string) error {
 	logModeConfig := defaultLogging()
+
+	mode, err := ParseLogMode(modeStr)
+	if err != nil {
+		return fmt.Errorf("invalid log mode: %w", err)
+	}
+	level, err := zerolog.ParseLevel(levelStr)
+	if err != nil {
+		return fmt.Errorf("invalid log level: %w", err)
+	}
+
 	switch mode {
 	case LogModeDefault:
 		logModeConfig = defaultLogging()
@@ -102,29 +113,15 @@ func ConfigureLogging(mode LogMode) {
 	case LogModeCombined:
 		logModeConfig = combinedLogging()
 	}
-	configureLogging(logModeConfig)
+	configureLogging(level, logModeConfig)
 
 	LogBufferedLogs(logModeConfig)
+	return nil
 }
 
-func configureLogging(logWriter io.Writer) {
+func configureLogging(level zerolog.Level, logWriter io.Writer) {
 	zerolog.TimeFieldFormat = time.RFC3339Nano
-	logLevelString := strings.ToLower(os.Getenv("LOG_LEVEL"))
-
-	switch {
-	case logLevelString == "trace":
-		zerolog.SetGlobalLevel(zerolog.TraceLevel)
-	case logLevelString == "debug":
-		zerolog.SetGlobalLevel(zerolog.DebugLevel)
-	case logLevelString == "error":
-		zerolog.SetGlobalLevel(zerolog.ErrorLevel)
-	case logLevelString == "warn":
-		zerolog.SetGlobalLevel(zerolog.WarnLevel)
-	case logLevelString == "fatal":
-		zerolog.SetGlobalLevel(zerolog.FatalLevel)
-	default:
-		zerolog.SetGlobalLevel(zerolog.InfoLevel)
-	}
+	zerolog.SetGlobalLevel(level)
 
 	info, ok := debug.ReadBuildInfo()
 	if ok && info.Main.Path != "" {
diff --git a/pkg/models/spec_config.go b/pkg/models/spec_config.go
index c5766e38e4..ef126383e4 100644
--- a/pkg/models/spec_config.go
+++ b/pkg/models/spec_config.go
@@ -13,10 +13,10 @@ import (
 
 type SpecConfig struct {
 	// Type of the config
-	Type string `json:"Type"`
+	Type string `json:"Type" yaml:"Type,omitempty"`
 
 	// Params is a map of the config params
-	Params map[string]interface{} `json:"Params,omitempty"`
+	Params map[string]interface{} `json:"Params,omitempty" yaml:"Params,omitempty"`
 }
 
 func (s *SpecConfig) MarshalZerologObject(e *zerolog.Event) {
diff --git a/pkg/node/compute.go b/pkg/node/compute.go
index 62e5ad4346..3f76582a67 100644
--- a/pkg/node/compute.go
+++ b/pkg/node/compute.go
@@ -40,6 +40,7 @@ type Compute struct {
 	ExecutionStore     store.ExecutionStore
 	Executors          executor.ExecutorProvider
 	Storages           storage.StorageProvider
+	Publishers         publisher.PublisherProvider
 	Bidder             compute.Bidder
 	ManagementClient   *compute.ManagementClient
 	cleanupFunc        func(ctx context.Context)
@@ -53,7 +54,7 @@ func NewComputeNode(
 	ctx context.Context,
 	nodeID string,
 	apiServer *publicapi.Server,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	config ComputeConfig,
 	storages storage.StorageProvider,
 	executors executor.ExecutorProvider,
@@ -255,6 +256,7 @@ func NewComputeNode(
 		ExecutionStore:     executionStore,
 		Executors:          executors,
 		Storages:           storages,
+		Publishers:         publishers,
 		Bidder:             bidder,
 		cleanupFunc:        cleanupFunc,
 		nodeInfoDecorator:  nodeInfoDecorator,
@@ -286,9 +288,8 @@ func NewBidder(
 		semanticBidStrats = []bidstrategy.SemanticBidStrategy{
 			semantic.NewNetworkingStrategy(config.JobSelectionPolicy.AcceptNetworkedJobs),
 			semantic.NewTimeoutStrategy(semantic.TimeoutStrategyParams{
-				MaxJobExecutionTimeout:                config.MaxJobExecutionTimeout,
-				MinJobExecutionTimeout:                config.MinJobExecutionTimeout,
-				JobExecutionTimeoutClientIDBypassList: config.JobExecutionTimeoutClientIDBypassList,
+				MaxJobExecutionTimeout: config.MaxJobExecutionTimeout,
+				MinJobExecutionTimeout: config.MinJobExecutionTimeout,
 			}),
 			semantic.NewStatelessJobStrategy(semantic.StatelessJobStrategyParams{
 				RejectStatelessJobs: config.JobSelectionPolicy.RejectStatelessJobs,
diff --git a/pkg/node/config_compute.go b/pkg/node/config_compute.go
index 6b2d016cf5..20eea4e70b 100644
--- a/pkg/node/config_compute.go
+++ b/pkg/node/config_compute.go
@@ -15,6 +15,7 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/compute/capacity"
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 )
 
@@ -42,10 +43,11 @@ type JobSelectionPolicy struct {
 
 type ComputeConfigParams struct {
 	// Capacity config
-	TotalResourceLimits          models.Resources
-	JobResourceLimits            models.Resources
-	DefaultJobResourceLimits     models.Resources
-	PhysicalResourcesProvider    capacity.Provider
+	TotalResourceLimits       models.Resources
+	JobResourceLimits         models.Resources
+	DefaultJobResourceLimits  models.Resources
+	PhysicalResourcesProvider capacity.Provider
+	// Deprecated: this feature is no longer supported, but still used in several tests and thus preserved
 	IgnorePhysicalResourceLimits bool
 
 	// Timeout config
@@ -54,8 +56,6 @@ type ComputeConfigParams struct {
 	MaxJobExecutionTimeout     time.Duration
 	DefaultJobExecutionTimeout time.Duration
 
-	JobExecutionTimeoutClientIDBypassList []string
-
 	// Bid strategies config
 	JobSelectionPolicy JobSelectionPolicy
 
@@ -72,9 +72,9 @@ type ComputeConfigParams struct {
 
 	ExecutionStore store.ExecutionStore
 
-	LocalPublisher types.LocalPublisherConfig
+	LocalPublisher types.LocalPublisher
 
-	ControlPlaneSettings types.ComputeControlPlaneConfig
+	ControlPlaneSettings legacy_types.ComputeControlPlaneConfig
 }
 
 type ComputeConfig struct {
@@ -96,10 +96,6 @@ type ComputeConfig struct {
 	// no timeout requirement defined.
 	DefaultJobExecutionTimeout time.Duration
 
-	// JobExecutionTimeoutClientIDBypassList is the list of clients that are allowed to bypass the job execution timeout
-	// check.
-	JobExecutionTimeoutClientIDBypassList []string
-
 	// Bid strategies config
 	JobSelectionPolicy JobSelectionPolicy
 
@@ -117,9 +113,9 @@ type ComputeConfig struct {
 
 	ExecutionStore store.ExecutionStore
 
-	LocalPublisher types.LocalPublisherConfig
+	LocalPublisher types.LocalPublisher
 
-	ControlPlaneSettings types.ComputeControlPlaneConfig
+	ControlPlaneSettings legacy_types.ComputeControlPlaneConfig
 }
 
 func NewComputeConfigWithDefaults(executionDir string) (ComputeConfig, error) {
@@ -151,6 +147,9 @@ func NewComputeConfigWith(executionDir string, params ComputeConfigParams) (Comp
 	if params.LocalPublisher.Address == "" {
 		params.LocalPublisher.Address = defaults.LocalPublisher.Address
 	}
+	if params.LocalPublisher.Port <= 0 {
+		params.LocalPublisher.Port = defaults.LocalPublisher.Port
+	}
 	if params.LocalPublisher.Directory == "" {
 		params.LocalPublisher.Directory = defaults.LocalPublisher.Directory
 		if err := os.MkdirAll(params.LocalPublisher.Directory, localPublishFolderPerm); err != nil {
@@ -206,8 +205,6 @@ func NewComputeConfigWith(executionDir string, params ComputeConfigParams) (Comp
 		MaxJobExecutionTimeout:     params.MaxJobExecutionTimeout,
 		DefaultJobExecutionTimeout: params.DefaultJobExecutionTimeout,
 
-		JobExecutionTimeoutClientIDBypassList: params.JobExecutionTimeoutClientIDBypassList,
-
 		JobSelectionPolicy: params.JobSelectionPolicy,
 
 		LogRunningExecutionsInterval: params.LogRunningExecutionsInterval,
diff --git a/pkg/node/config_defaults.go b/pkg/node/config_defaults.go
index 30a0dfcb5c..213c889156 100644
--- a/pkg/node/config_defaults.go
+++ b/pkg/node/config_defaults.go
@@ -8,8 +8,8 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
 	compute_system "github.com/bacalhau-project/bacalhau/pkg/compute/capacity/system"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
-	"github.com/bacalhau-project/bacalhau/pkg/orchestrator/transformer"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
 )
 
@@ -28,23 +28,21 @@ func NewDefaultComputeParam(storagePath string) ComputeConfigParams {
 
 		LogRunningExecutionsInterval: 10 * time.Second,
 		JobSelectionPolicy:           NewDefaultJobSelectionPolicy(),
-		LocalPublisher: types.LocalPublisherConfig{
+		LocalPublisher: types.LocalPublisher{
+			Address:   "127.0.0.1",
+			Port:      6001,
 			Directory: path.Join(storagePath, "bacalhau-local-publisher"),
 		},
-		ControlPlaneSettings: types.ComputeControlPlaneConfig{
-			InfoUpdateFrequency:     types.Duration(60 * time.Second), //nolint:gomnd
-			ResourceUpdateFrequency: types.Duration(30 * time.Second), //nolint:gomnd
-			HeartbeatFrequency:      types.Duration(15 * time.Second), //nolint:gomnd
+		ControlPlaneSettings: legacy_types.ComputeControlPlaneConfig{
+			InfoUpdateFrequency:     legacy_types.Duration(60 * time.Second), //nolint:gomnd
+			ResourceUpdateFrequency: legacy_types.Duration(30 * time.Second), //nolint:gomnd
+			HeartbeatFrequency:      legacy_types.Duration(15 * time.Second), //nolint:gomnd
 			HeartbeatTopic:          "heartbeat",
 		},
 	}
 }
 
 var DefaultRequesterConfig = RequesterConfigParams{
-	JobDefaults: transformer.JobDefaults{
-		TotalTimeout: models.NoTimeout,
-	},
-
 	HousekeepingBackgroundTaskInterval: 30 * time.Second,
 	HousekeepingTimeoutBuffer:          2 * time.Minute,
 	NodeRankRandomnessRange:            5,
@@ -64,15 +62,17 @@ var DefaultRequesterConfig = RequesterConfigParams{
 	WorkerEvalDequeueBaseBackoff: 1 * time.Second,
 	WorkerEvalDequeueMaxBackoff:  30 * time.Second,
 
+	NodeOverSubscriptionFactor: 1.5,
+
 	S3PreSignedURLDisabled:   false,
 	S3PreSignedURLExpiration: 30 * time.Minute,
 
 	TranslationEnabled: false,
 
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second), //nolint:gomnd
+	ControlPlaneSettings: legacy_types.RequesterControlPlaneConfig{
+		HeartbeatCheckFrequency: legacy_types.Duration(30 * time.Second), //nolint:gomnd
 		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second), //nolint:gomnd
+		NodeDisconnectedAfter:   legacy_types.Duration(30 * time.Second), //nolint:gomnd
 	},
 
 	NodeInfoStoreTTL:     10 * time.Minute,
@@ -80,9 +80,6 @@ var DefaultRequesterConfig = RequesterConfigParams{
 }
 
 var TestRequesterConfig = RequesterConfigParams{
-	JobDefaults: transformer.JobDefaults{
-		TotalTimeout: 30 * time.Second,
-	},
 	HousekeepingBackgroundTaskInterval: 30 * time.Second,
 	HousekeepingTimeoutBuffer:          100 * time.Millisecond,
 	NodeRankRandomnessRange:            5,
@@ -109,10 +106,10 @@ var TestRequesterConfig = RequesterConfigParams{
 	S3PreSignedURLDisabled:   false,
 	S3PreSignedURLExpiration: 30 * time.Minute,
 
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second), //nolint:gomnd
+	ControlPlaneSettings: legacy_types.RequesterControlPlaneConfig{
+		HeartbeatCheckFrequency: legacy_types.Duration(30 * time.Second), //nolint:gomnd
 		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second), //nolint:gomnd
+		NodeDisconnectedAfter:   legacy_types.Duration(30 * time.Second), //nolint:gomnd
 	},
 
 	DefaultApprovalState: models.NodeMembership.APPROVED,
diff --git a/pkg/node/config_requester.go b/pkg/node/config_requester.go
index 0584adf10e..65bc727839 100644
--- a/pkg/node/config_requester.go
+++ b/pkg/node/config_requester.go
@@ -9,15 +9,15 @@ import (
 	"github.com/rs/zerolog/log"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/jobstore"
 
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/orchestrator"
-	"github.com/bacalhau-project/bacalhau/pkg/orchestrator/transformer"
 )
 
 type RequesterConfigParams struct {
-	JobDefaults transformer.JobDefaults
+	JobDefaults types.JobDefaults
 
 	HousekeepingBackgroundTaskInterval time.Duration
 	HousekeepingTimeoutBuffer          time.Duration
@@ -54,17 +54,16 @@ type RequesterConfigParams struct {
 	S3PreSignedURLDisabled   bool
 	S3PreSignedURLExpiration time.Duration
 
-	JobStore         jobstore.Store
+	JobStore jobstore.Store
+	// TODO(review): we don't use this field for anything, maybe we can delete it
 	NodeInfoStoreTTL time.Duration
 
-	DefaultPublisher string
-
 	// When new nodes join the cluster, what state do they have? By default, APPROVED, and
 	// for tests, APPROVED. We will provide an option to set this to PENDING for production
 	// or for when operators are ready to control node approval.
 	DefaultApprovalState models.NodeMembershipState
 
-	ControlPlaneSettings types.RequesterControlPlaneConfig
+	ControlPlaneSettings legacy_types.RequesterControlPlaneConfig
 }
 
 type RequesterConfig struct {
diff --git a/pkg/node/factories.go b/pkg/node/factories.go
index e4ec741daf..ee5bd5df3e 100644
--- a/pkg/node/factories.go
+++ b/pkg/node/factories.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"time"
 
 	"github.com/bacalhau-project/bacalhau/pkg/authn"
 	"github.com/bacalhau-project/bacalhau/pkg/authn/ask"
@@ -48,20 +47,15 @@ type (
 )
 
 // Standard implementations used in prod and when testing prod behavior
-func NewStandardStorageProvidersFactory(cfg types.BacalhauConfig) StorageProvidersFactory {
+func NewStandardStorageProvidersFactory(cfg types.Bacalhau) StorageProvidersFactory {
 	return StorageProvidersFactoryFunc(func(
 		ctx context.Context,
 		nodeConfig NodeConfig,
 	) (storage.StorageProvider, error) {
-		pr, err := executor_util.NewStandardStorageProvider(
-			time.Duration(cfg.Node.VolumeSizeRequestTimeout),
-			time.Duration(cfg.Node.DownloadURLRequestTimeout),
-			cfg.Node.DownloadURLRequestRetries,
-			executor_util.StandardStorageProviderOptions{
-				IPFSConnect:           cfg.Node.IPFS.Connect,
-				AllowListedLocalPaths: nodeConfig.AllowListedLocalPaths,
-			},
-		)
+		if len(cfg.Compute.AllowListedLocalPaths) == 0 {
+			cfg.Compute.AllowListedLocalPaths = nodeConfig.AllowListedLocalPaths
+		}
+		pr, err := executor_util.NewStandardStorageProvider(cfg)
 		if err != nil {
 			return nil, err
 		}
@@ -69,7 +63,7 @@ func NewStandardStorageProvidersFactory(cfg types.BacalhauConfig) StorageProvide
 	})
 }
 
-func NewStandardExecutorsFactory(cfg types.DockerCacheConfig) ExecutorsFactory {
+func NewStandardExecutorsFactory(cfg types.EngineConfig) ExecutorsFactory {
 	return ExecutorsFactoryFunc(
 		func(ctx context.Context, nodeConfig NodeConfig) (executor.ExecutorProvider, error) {
 			pr, err := executor_util.NewStandardExecutorProvider(
@@ -118,7 +112,7 @@ func NewPluginExecutorFactory(pluginPath string) ExecutorsFactory {
 		})
 }
 
-func NewStandardPublishersFactory(cfg types.BacalhauConfig) PublishersFactory {
+func NewStandardPublishersFactory(cfg types.Bacalhau) PublishersFactory {
 	return PublishersFactoryFunc(
 		func(
 			ctx context.Context,
@@ -131,8 +125,8 @@ func NewStandardPublishersFactory(cfg types.BacalhauConfig) PublishersFactory {
 				ctx,
 				executionDir,
 				nodeConfig.CleanupManager,
-				cfg.Node.IPFS.Connect,
-				&nodeConfig.ComputeConfig.LocalPublisher,
+				cfg.Publishers,
+				nodeConfig.ComputeConfig.LocalPublisher,
 			)
 			if err != nil {
 				return nil, err
@@ -149,7 +143,7 @@ func NewStandardAuthenticatorsFactory(userKey *baccrypto.UserKey) Authenticators
 			authns := make(map[string]authn.Authenticator, len(nodeConfig.AuthConfig.Methods))
 			for name, authnConfig := range nodeConfig.AuthConfig.Methods {
 				switch authnConfig.Type {
-				case authn.MethodTypeChallenge:
+				case string(authn.MethodTypeChallenge):
 					methodPolicy, err := policy.FromPathOrDefault(authnConfig.PolicyPath, challenge.AnonymousModePolicy)
 					if err != nil {
 						allErr = errors.Join(allErr, err)
@@ -162,7 +156,7 @@ func NewStandardAuthenticatorsFactory(userKey *baccrypto.UserKey) Authenticators
 						userKey.PrivateKey(),
 						nodeConfig.NodeID,
 					)
-				case authn.MethodTypeAsk:
+				case string(authn.MethodTypeAsk):
 					methodPolicy, err := policy.FromPath(authnConfig.PolicyPath)
 					if err != nil {
 						allErr = errors.Join(allErr, err)
diff --git a/pkg/node/node.go b/pkg/node/node.go
index cada452495..a9f2e5bf2f 100644
--- a/pkg/node/node.go
+++ b/pkg/node/node.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"os"
 
 	"github.com/imdario/mergo"
 	"github.com/labstack/echo/v4"
@@ -13,6 +14,7 @@ import (
 
 	"github.com/bacalhau-project/bacalhau/pkg/authz"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	baccrypto "github.com/bacalhau-project/bacalhau/pkg/lib/crypto"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/policy"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
@@ -76,7 +78,7 @@ type NodeDependencyInjector struct {
 }
 
 func NewExecutorPluginNodeDependencyInjector(
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	userKey *baccrypto.UserKey,
 	pluginPath string,
 ) NodeDependencyInjector {
@@ -88,10 +90,10 @@ func NewExecutorPluginNodeDependencyInjector(
 	}
 }
 
-func NewStandardNodeDependencyInjector(cfg types.BacalhauConfig, userKey *baccrypto.UserKey) NodeDependencyInjector {
+func NewStandardNodeDependencyInjector(cfg types.Bacalhau, userKey *baccrypto.UserKey) NodeDependencyInjector {
 	return NodeDependencyInjector{
 		StorageProvidersFactory: NewStandardStorageProvidersFactory(cfg),
-		ExecutorsFactory:        NewStandardExecutorsFactory(cfg.Node.Compute.ManifestCache),
+		ExecutorsFactory:        NewStandardExecutorsFactory(cfg.Engines),
 		PublishersFactory:       NewStandardPublishersFactory(cfg),
 		AuthenticatorsFactory:   NewStandardAuthenticatorsFactory(userKey),
 	}
@@ -113,7 +115,7 @@ func (n *Node) Start(ctx context.Context) error {
 //nolint:funlen,gocyclo // Should be simplified when moving to FX
 func NewNode(
 	ctx context.Context,
-	bacalhauConfig types.BacalhauConfig,
+	bacalhauConfig types.Bacalhau,
 	config NodeConfig,
 	fsr *repo.FsRepo,
 ) (*Node, error) {
@@ -166,7 +168,10 @@ func NewNode(
 			config.NodeID,
 			apiServer,
 			config,
-			bacalhauConfig.Metrics,
+			// TODO: we not longer have a config for this, and the default was always DevNull - remove this
+			legacy_types.MetricsConfig{
+				EventTracerPath: os.DevNull,
+			},
 			config.RequesterNodeConfig,
 			transportLayer,
 			transportLayer.ComputeProxy(),
@@ -327,7 +332,7 @@ func NewNode(
 	return node, nil
 }
 
-func prepareConfig(config *NodeConfig, bacalhauConfig types.BacalhauConfig) error {
+func prepareConfig(config *NodeConfig, bacalhauConfig types.Bacalhau) error {
 	userKeyPath, err := bacalhauConfig.UserKeyPath()
 	if err != nil {
 		return err
diff --git a/pkg/node/requester.go b/pkg/node/requester.go
index 511f4b0382..1e8515f223 100644
--- a/pkg/node/requester.go
+++ b/pkg/node/requester.go
@@ -8,8 +8,7 @@ import (
 	"github.com/rs/zerolog/log"
 	"go.opentelemetry.io/otel/attribute"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/job"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/backoff"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/ncl"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
@@ -60,7 +59,7 @@ func NewRequesterNode(
 	nodeID string,
 	apiServer *publicapi.Server,
 	nodeConfig NodeConfig,
-	metricsConfig types.MetricsConfig,
+	metricsConfig legacy_types.MetricsConfig,
 	requesterConfig RequesterConfig,
 	transportLayer *nats_transport.NATSTransport,
 	computeProxy compute.Endpoint,
@@ -217,16 +216,6 @@ func NewRequesterNode(
 		transformer.RequesterInfo(nodeID),
 	}
 
-	if requesterConfig.DefaultPublisher != "" {
-		// parse the publisher to generate a models.SpecConfig and add it to each job
-		// which is without a publisher
-		config, err := job.ParsePublisherString(requesterConfig.DefaultPublisher)
-		if err != nil {
-			return nil, fmt.Errorf("parsing default publisher spec (%s): %w", requesterConfig.DefaultPublisher, err)
-		}
-		jobTransformers = append(jobTransformers, transformer.DefaultPublisher(config))
-	}
-
 	endpointV2 := orchestrator.NewBaseEndpoint(&orchestrator.BaseEndpointParams{
 		ID:                nodeID,
 		Store:             jobStore,
diff --git a/pkg/orchestrator/transformer/job.go b/pkg/orchestrator/transformer/job.go
index f6a6532ea4..2f1616b0f9 100644
--- a/pkg/orchestrator/transformer/job.go
+++ b/pkg/orchestrator/transformer/job.go
@@ -2,8 +2,10 @@ package transformer
 
 import (
 	"context"
+	"fmt"
 	"time"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/util/idgen"
 )
@@ -16,32 +18,24 @@ func IDGenerator(_ context.Context, job *models.Job) error {
 	return nil
 }
 
-type JobDefaults struct {
-	TotalTimeout     time.Duration
-	ExecutionTimeout time.Duration
-	QueueTimeout     time.Duration
-}
-
 // DefaultsApplier is a transformer that applies default values to the job.
-func DefaultsApplier(defaults JobDefaults) JobTransformer {
+func DefaultsApplier(defaults types.JobDefaults) JobTransformer {
 	f := func(ctx context.Context, job *models.Job) error {
-		for _, task := range job.Tasks {
-			// only apply default execution timeout to non-long running jobs
-			if !job.IsLongRunning() {
-				if task.Timeouts.TotalTimeout <= 0 {
-					task.Timeouts.TotalTimeout = int64(defaults.TotalTimeout.Seconds())
-				}
-				if task.Timeouts.ExecutionTimeout <= 0 {
-					task.Timeouts.ExecutionTimeout = int64(defaults.ExecutionTimeout.Seconds())
-				}
+		switch job.Type {
+		case models.JobTypeBatch:
+			if err := applyBatchJobDefaults(defaults.Batch, job); err != nil {
+				return err
 			}
-
-			// only apply default queue timeout to batch and service jobs
-			if job.Type == models.JobTypeBatch || job.Type == models.JobTypeService {
-				if task.Timeouts.GetQueueTimeout() <= 0 {
-					task.Timeouts.QueueTimeout = int64(defaults.QueueTimeout.Seconds())
-				}
+		case models.JobTypeOps:
+			if err := applyBatchJobDefaults(defaults.Ops, job); err != nil {
+				return err
 			}
+		case models.JobTypeService:
+			applyLongRunningJobDefaults(defaults.Service, job)
+		case models.JobTypeDaemon:
+			applyLongRunningJobDefaults(defaults.Daemon, job)
+		default:
+			return fmt.Errorf("unknown job type: %s", job.Type)
 		}
 
 		return nil
@@ -49,6 +43,69 @@ func DefaultsApplier(defaults JobDefaults) JobTransformer {
 	return JobFn(f)
 }
 
+func applyBatchJobDefaults(defaults types.BatchJobDefaultsConfig, job *models.Job) error {
+	if job.Priority == 0 {
+		job.Priority = defaults.Priority
+	}
+	for _, task := range job.Tasks {
+		if err := applyBatchTaskDefaults(defaults.Task, task); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func applyBatchTaskDefaults(defaults types.BatchTaskDefaultConfig, task *models.Task) error {
+	if task.ResourcesConfig.CPU == "" {
+		task.ResourcesConfig.CPU = defaults.Resources.CPU
+	}
+	if task.ResourcesConfig.Memory == "" {
+		task.ResourcesConfig.Memory = defaults.Resources.Memory
+	}
+	if task.ResourcesConfig.Disk == "" {
+		task.ResourcesConfig.Disk = defaults.Resources.Disk
+	}
+	if task.ResourcesConfig.GPU == "" {
+		task.ResourcesConfig.GPU = defaults.Resources.GPU
+	}
+	// if the user didn't provide a publisher, and a default transformer is set - use it.
+	if task.Publisher.IsEmpty() && !defaults.Publisher.Config.IsEmpty() {
+		task.Publisher = &defaults.Publisher.Config
+	}
+	if task.Timeouts.ExecutionTimeout <= 0 {
+		task.Timeouts.ExecutionTimeout = int64(time.Duration(defaults.Timeouts.ExecutionTimeout).Seconds())
+	}
+	if task.Timeouts.TotalTimeout <= 0 {
+		task.Timeouts.TotalTimeout = int64(time.Duration(defaults.Timeouts.TotalTimeout).Seconds())
+	}
+
+	return nil
+}
+
+func applyLongRunningJobDefaults(defaults types.LongRunningJobDefaultsConfig, job *models.Job) {
+	if job.Priority == 0 {
+		job.Priority = defaults.Priority
+	}
+	for _, task := range job.Tasks {
+		applyLongRunningTaskDefaults(defaults.Task, task)
+	}
+}
+
+func applyLongRunningTaskDefaults(defaults types.LongRunningTaskDefaultConfig, task *models.Task) {
+	if task.ResourcesConfig.CPU == "" {
+		task.ResourcesConfig.CPU = defaults.Resources.CPU
+	}
+	if task.ResourcesConfig.Memory == "" {
+		task.ResourcesConfig.Memory = defaults.Resources.Memory
+	}
+	if task.ResourcesConfig.Disk == "" {
+		task.ResourcesConfig.Disk = defaults.Resources.Disk
+	}
+	if task.ResourcesConfig.GPU == "" {
+		task.ResourcesConfig.GPU = defaults.Resources.GPU
+	}
+}
+
 // RequesterInfo is a transformer that sets the requester ID in the job meta.
 func RequesterInfo(requesterNodeID string) JobTransformer {
 	f := func(ctx context.Context, job *models.Job) error {
diff --git a/pkg/publicapi/endpoint/agent/endpoint.go b/pkg/publicapi/endpoint/agent/endpoint.go
index a38142b4da..ce00e1012c 100644
--- a/pkg/publicapi/endpoint/agent/endpoint.go
+++ b/pkg/publicapi/endpoint/agent/endpoint.go
@@ -17,14 +17,14 @@ type EndpointParams struct {
 	Router             *echo.Echo
 	NodeStateProvider  models.NodeStateProvider
 	DebugInfoProviders []models.DebugInfoProvider
-	BacalhauConfig     types.BacalhauConfig
+	BacalhauConfig     types.Bacalhau
 }
 
 type Endpoint struct {
 	router             *echo.Echo
 	nodeStateProvider  models.NodeStateProvider
 	debugInfoProviders []models.DebugInfoProvider
-	bacalhauConfig     types.BacalhauConfig
+	bacalhauConfig     types.Bacalhau
 }
 
 func NewEndpoint(params EndpointParams) *Endpoint {
diff --git a/pkg/publisher/local/publisher.go b/pkg/publisher/local/publisher.go
index 0498ca658f..c323ed979c 100644
--- a/pkg/publisher/local/publisher.go
+++ b/pkg/publisher/local/publisher.go
@@ -14,6 +14,7 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/publisher"
+	"github.com/bacalhau-project/bacalhau/pkg/storage/util"
 )
 
 type Publisher struct {
@@ -24,18 +25,30 @@ type Publisher struct {
 	server        *LocalPublisherServer
 }
 
-func NewLocalPublisher(ctx context.Context, directory string, host string, port int) *Publisher {
+func NewLocalPublisher(ctx context.Context, directory string, host string, port int) (*Publisher, error) {
 	p := &Publisher{
 		baseDirectory: directory,
-		host:          ResolveAddress(ctx, host),
-		port:          port,
-		urlPrefix:     fmt.Sprintf("http://%s:%d", host, port),
+		// TODO: this field is only written to, never read. It could be deleted.
+		host:      ResolveAddress(ctx, host),
+		port:      port,
+		urlPrefix: fmt.Sprintf("http://%s:%d", host, port),
 	}
 
+	if info, err := os.Stat(p.baseDirectory); err != nil {
+		if !os.IsNotExist(err) {
+			return nil, fmt.Errorf("failed to create local pubisher with path %s: path could not be read: %w", directory, err)
+		}
+		log.Warn().Msgf("local publisher was configured with a directory that doesn't exits. attempting to create one at %s", directory)
+		if err := os.MkdirAll(p.baseDirectory, util.OS_USER_RWX); err != nil {
+			return nil, fmt.Errorf("failed to create directory for local publisher: %w", err)
+		}
+	} else if !info.IsDir() {
+		return nil, fmt.Errorf("failed to create local publisher with path: %s: path is not a directoy", directory)
+	}
 	p.server = NewLocalPublisherServer(ctx, p.baseDirectory, p.port)
 	go p.server.Run(ctx)
 
-	return p
+	return p, nil
 }
 
 // IsInstalled checks if the publisher is installed and it determines
@@ -44,9 +57,9 @@ func (p *Publisher) IsInstalled(ctx context.Context) (bool, error) {
 	fileInfo, err := os.Stat(p.baseDirectory)
 	if err != nil {
 		if os.IsNotExist(err) {
-			log.Ctx(ctx).Debug().Msg("local publisher not installed because the base directory does not exist")
+			log.Ctx(ctx).Error().Err(err).Msgf("local publisher not installed because the base directory %s does not exist", p.baseDirectory)
 		} else {
-			log.Ctx(ctx).Error().Err(err).Msg("local publisher failed to check if the base directory exists")
+			log.Ctx(ctx).Error().Err(err).Msgf("local publisher failed to check if the base directory %s exists", p.baseDirectory)
 		}
 
 		return false, nil
diff --git a/pkg/publisher/util/utils.go b/pkg/publisher/util/utils.go
index a4a5a89dc9..59168baf54 100644
--- a/pkg/publisher/util/utils.go
+++ b/pkg/publisher/util/utils.go
@@ -23,35 +23,63 @@ func NewPublisherProvider(
 	ctx context.Context,
 	storagePath string,
 	cm *system.CleanupManager,
-	ipfsConnect string,
-	localConfig *types.LocalPublisherConfig,
+	cfg types.PublishersConfig,
+	defaultLocalPublisher types.LocalPublisher,
 ) (publisher.PublisherProvider, error) {
-	noopPublisher := noop.NewNoopPublisher()
-	s3Publisher, err := configureS3Publisher(storagePath, cm)
-	if err != nil {
-		return nil, err
-	}
+	providers := make(map[string]publisher.Publisher)
 
-	localPublisher := local.NewLocalPublisher(ctx, localConfig.Directory, localConfig.Address, localConfig.Port)
-
-	providers := map[string]publisher.Publisher{
-		models.PublisherNoop:  tracing.Wrap(noopPublisher),
-		models.PublisherS3:    tracing.Wrap(s3Publisher),
-		models.PublisherLocal: tracing.Wrap(localPublisher),
+	if cfg.IsNotDisabled(models.PublisherNoop) {
+		providers[models.PublisherNoop] = noop.NewNoopPublisher()
 	}
 
-	if ipfsConnect != "" {
-		ipfsClient, err := ipfs_client.NewClient(ctx, ipfsConnect)
+	if cfg.IsNotDisabled(models.PublisherS3) {
+		s3Publisher, err := configureS3Publisher(storagePath, cm)
 		if err != nil {
 			return nil, err
 		}
-		ipfsPublisher, err := ipfs.NewIPFSPublisher(ctx, *ipfsClient)
+		providers[models.PublisherS3] = tracing.Wrap(s3Publisher)
+	}
+
+	if cfg.IsNotDisabled(models.PublisherLocal) {
+		// use the defaults, and override any values provided by the user.
+		address := defaultLocalPublisher.Address
+		port := defaultLocalPublisher.Port
+		directory := defaultLocalPublisher.Directory
+		if cfg.Types.Local.Address != "" {
+			address = cfg.Types.Local.Address
+		}
+		if cfg.Types.Local.Port != 0 {
+			port = cfg.Types.Local.Port
+		}
+		if cfg.Types.Local.Directory != "" {
+			directory = cfg.Types.Local.Directory
+		}
+		localPublisher, err := local.NewLocalPublisher(
+			ctx,
+			directory,
+			address,
+			port,
+		)
 		if err != nil {
 			return nil, err
 		}
+		providers[models.PublisherLocal] = tracing.Wrap(localPublisher)
+	}
 
-		providers[models.PublisherIPFS] = ipfsPublisher
+	if cfg.IsNotDisabled(models.PublisherIPFS) {
+		if cfg.Types.IPFS.Endpoint != "" {
+			ipfsClient, err := ipfs_client.NewClient(ctx, cfg.Types.IPFS.Endpoint)
+			if err != nil {
+				return nil, err
+			}
+			ipfsPublisher, err := ipfs.NewIPFSPublisher(ctx, *ipfsClient)
+			if err != nil {
+				return nil, err
+			}
+			providers[models.PublisherIPFS] = tracing.Wrap(ipfsPublisher)
+		}
 	}
+
 	return provider.NewMappedProvider(providers), nil
 }
 
diff --git a/pkg/repo/fs.go b/pkg/repo/fs.go
index 298c4e8c47..42bac4d330 100644
--- a/pkg/repo/fs.go
+++ b/pkg/repo/fs.go
@@ -5,14 +5,17 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"time"
 
-	"github.com/google/uuid"
 	"github.com/mitchellh/go-homedir"
 	"github.com/rs/zerolog/log"
+	"github.com/samber/lo"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/telemetry"
+	"github.com/bacalhau-project/bacalhau/pkg/util/idgen"
 )
 
 const (
@@ -82,39 +85,43 @@ func (fsr *FsRepo) Version() (int, error) {
 }
 
 // Init initializes a new repo, returning an error if the repo already exists.
-func (fsr *FsRepo) Init(c config.ReadWriter) error {
+func (fsr *FsRepo) Init(cfg types.Bacalhau) error {
 	if exists, err := fsr.Exists(); err != nil {
 		return err
 	} else if exists {
 		return fmt.Errorf("cannot init repo: repo already exists")
 	}
 
-	log.Info().Msgf("Initializing repo at '%s' for environment '%s'", fsr.path, config.GetConfigEnvironment())
+	log.Info().Msgf("Initializing repo at %s", fsr.path)
 
-	// 0755: Owner can read, write, execute. Others can read and execute.
-	if err := os.MkdirAll(fsr.path, repoPermission); err != nil && !os.IsExist(err) {
-		return err
-	}
-
-	cfg, err := c.Current()
+	// if it takes longer than 5 seconds to get the node name from a provider, fail
+	nameCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+	nodeName, err := getNodeID(nameCtx, cfg.NameProvider)
 	if err != nil {
 		return err
 	}
 
-	// in the event a user has provided a config without a path we need to set it here based on what the repo was
-	// initialized with.
-	if cfg.DataDir == "" {
-		cfg.DataDir = fsr.path
-		c.Set("DataDir", fsr.path)
+	// 0755: Owner can read, write, execute. Others can read and execute.
+	if err := os.MkdirAll(fsr.path, repoPermission); err != nil && !os.IsExist(err) {
+		return err
 	}
 
 	// TODO this should be a part of the config.
 	telemetry.SetupFromEnvs()
-	return fsr.WriteVersion(Version4)
+
+	if err := fsr.WriteVersion(Version4); err != nil {
+		return fmt.Errorf("failed to persist repo version: %w", err)
+	}
+
+	if err := fsr.WriteNodeName(nodeName); err != nil {
+		return fmt.Errorf("failed to persist node name: %w", err)
+	}
+	return nil
 }
 
 // Open opens an existing repo, returning an error if the repo is uninitialized.
-func (fsr *FsRepo) Open(c config.ReadWriter) error {
+func (fsr *FsRepo) Open() error {
 	// if the repo does not exist we cannot open it.
 	if exists, err := fsr.Exists(); err != nil {
 		return err
@@ -128,25 +135,6 @@ func (fsr *FsRepo) Open(c config.ReadWriter) error {
 		}
 	}
 
-	cfg, err := c.Current()
-	if err != nil {
-		return err
-	}
-
-	// in the event a user has provided a config without a path we need to set it here based on what the repo was
-	// initialized with.
-	if cfg.DataDir == "" {
-		cfg.DataDir = fsr.path
-		c.Set("DataDir", fsr.path)
-	}
-
-	// derive an installationID from the client ID loaded from the repo.
-	if cfg.User.InstallationID == "" {
-		ID, _ := config.GetClientID(cfg.User.KeyPath)
-		uuidFromUserID := uuid.NewSHA1(uuid.New(), []byte(ID))
-		c.Set(types.UserInstallationID, uuidFromUserID.String())
-	}
-
 	// TODO this should be a part of the config.
 	telemetry.SetupFromEnvs()
 
@@ -209,22 +197,44 @@ func (fsr *FsRepo) WriteRunInfo(ctx context.Context, summaryShellVariablesString
 }
 
 // EnsureRepoPathsConfigured modifies the config to include keys for accessing repo paths
-func (fsr *FsRepo) EnsureRepoPathsConfigured(c config.ReadWriter) {
-	c.SetIfAbsent(types.AuthTokensPath, fsr.join(config.TokensPath))
-	c.SetIfAbsent(types.UserKeyPath, fsr.join(config.UserPrivateKeyFileName))
-	c.SetIfAbsent(types.NodeExecutorPluginPath, fsr.join(config.PluginsPath))
+func (fsr *FsRepo) EnsureRepoPathsConfigured(c config_legacy.ReadWriter) {
+	c.SetIfAbsent(legacy_types.AuthTokensPath, fsr.join(config_legacy.TokensPath))
+	c.SetIfAbsent(legacy_types.UserKeyPath, fsr.join(config_legacy.UserPrivateKeyFileName))
+	c.SetIfAbsent(legacy_types.NodeExecutorPluginPath, fsr.join(config_legacy.PluginsPath))
 
 	// NB(forrest): pay attention to the subtle name difference here
-	c.SetIfAbsent(types.NodeComputeStoragePath, fsr.join(config.ComputeStoragesPath))
+	c.SetIfAbsent(legacy_types.NodeComputeStoragePath, fsr.join(config_legacy.ComputeStoragesPath))
 
-	c.SetIfAbsent(types.NodeClientAPITLSAutoCertCachePath, fsr.join(config.AutoCertCachePath))
-	c.SetIfAbsent(types.NodeNetworkStoreDir, fsr.join(config.OrchestratorStorePath, config.NetworkTransportStore))
+	c.SetIfAbsent(legacy_types.NodeClientAPITLSAutoCertCachePath, fsr.join(config_legacy.AutoCertCachePath))
+	c.SetIfAbsent(legacy_types.NodeNetworkStoreDir, fsr.join(config_legacy.OrchestratorStorePath, config_legacy.NetworkTransportStore))
 
-	c.SetIfAbsent(types.NodeRequesterJobStorePath, fsr.join(config.OrchestratorStorePath, "jobs.db"))
-	c.SetIfAbsent(types.NodeComputeExecutionStorePath, fsr.join(config.ComputeStorePath, "executions.db"))
+	c.SetIfAbsent(legacy_types.NodeRequesterJobStorePath, fsr.join(config_legacy.OrchestratorStorePath, "jobs.db"))
+	c.SetIfAbsent(legacy_types.NodeComputeExecutionStorePath, fsr.join(config_legacy.ComputeStorePath, "executions.db"))
 }
 
 // join joins path elements with fsr.path
 func (fsr *FsRepo) join(paths ...string) string {
 	return filepath.Join(append([]string{fsr.path}, paths...)...)
 }
+
+func getNodeID(ctx context.Context, nodeNameProviderType string) (string, error) {
+	nodeNameProviders := map[string]idgen.NodeNameProvider{
+		"hostname": idgen.HostnameProvider{},
+		"aws":      idgen.NewAWSNodeNameProvider(),
+		"gcp":      idgen.NewGCPNodeNameProvider(),
+		"uuid":     idgen.UUIDNodeNameProvider{},
+		"puuid":    idgen.PUUIDNodeNameProvider{},
+	}
+	nodeNameProvider, ok := nodeNameProviders[nodeNameProviderType]
+	if !ok {
+		return "", fmt.Errorf(
+			"unknown node name provider: %s. Supported providers are: %s", nodeNameProviderType, lo.Keys(nodeNameProviders))
+	}
+
+	nodeName, err := nodeNameProvider.GenerateNodeName(ctx)
+	if err != nil {
+		return "", err
+	}
+
+	return nodeName, nil
+}
diff --git a/pkg/repo/migrations/helpers.go b/pkg/repo/migrations/helpers.go
index 19b6cf867c..22915b4265 100644
--- a/pkg/repo/migrations/helpers.go
+++ b/pkg/repo/migrations/helpers.go
@@ -11,8 +11,8 @@ import (
 	"github.com/libp2p/go-libp2p/core/peer"
 	"github.com/spf13/viper"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 )
 
@@ -24,7 +24,7 @@ func getViper(r repo.FsRepo) (*viper.Viper, error) {
 		return nil, err
 	}
 
-	configFile := filepath.Join(repoPath, config.FileName)
+	configFile := filepath.Join(repoPath, config_legacy.FileName)
 	v := viper.New()
 	v.SetTypeByDefaultValue(true)
 	v.SetConfigFile(configFile)
@@ -44,7 +44,7 @@ func configExists(r repo.FsRepo) (bool, error) {
 		return false, err
 	}
 
-	configFile := filepath.Join(repoPath, config.FileName)
+	configFile := filepath.Join(repoPath, config_legacy.FileName)
 	_, err = os.Stat(configFile)
 	if os.IsNotExist(err) {
 		return false, nil
@@ -52,14 +52,14 @@ func configExists(r repo.FsRepo) (bool, error) {
 	return err == nil, err
 }
 
-func readConfig(r repo.FsRepo) (*viper.Viper, types.BacalhauConfig, error) {
+func readConfig(r repo.FsRepo) (*viper.Viper, legacy_types.BacalhauConfig, error) {
 	v, err := getViper(r)
 	if err != nil {
-		return nil, types.BacalhauConfig{}, err
+		return nil, legacy_types.BacalhauConfig{}, err
 	}
-	var fileCfg types.BacalhauConfig
-	if err := v.Unmarshal(&fileCfg, config.DecoderHook); err != nil {
-		return v, types.BacalhauConfig{}, fmt.Errorf("failed to unmarshal config file: %w", err)
+	var fileCfg legacy_types.BacalhauConfig
+	if err := v.Unmarshal(&fileCfg, config_legacy.DecoderHook); err != nil {
+		return v, legacy_types.BacalhauConfig{}, fmt.Errorf("failed to unmarshal config file: %w", err)
 	}
 	return v, fileCfg, nil
 }
diff --git a/pkg/repo/migrations/v2_3.go b/pkg/repo/migrations/v2_3.go
index 497ec4626b..d96b07522e 100644
--- a/pkg/repo/migrations/v2_3.go
+++ b/pkg/repo/migrations/v2_3.go
@@ -9,8 +9,8 @@ import (
 
 	"github.com/spf13/viper"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 	"github.com/bacalhau-project/bacalhau/pkg/storage/util"
 )
@@ -35,16 +35,16 @@ var V2Migration = repo.NewMigration(
 		// we load the config to resolve the libp2p node id. Loading the config this way will also
 		// use default values, args and env vars to fill in the config, so we can be sure we are
 		// reading the correct libp2p key in case the user is overriding the default value.
-		opts := []config.Option{config.WithValues(viper.AllSettings())}
-		if _, err := os.Stat(filepath.Join(repoPath, config.FileName)); err != nil {
+		opts := []config_legacy.Option{config_legacy.WithValues(viper.AllSettings())}
+		if _, err := os.Stat(filepath.Join(repoPath, config_legacy.FileName)); err != nil {
 			// if the config doesn't exist that's okay, just means we read a repo without a config in it.
 			if !errors.Is(err, os.ErrNotExist) {
 				return fmt.Errorf("loading config from repo: %w", err)
 			}
 		} else {
-			opts = append(opts, config.WithPaths(filepath.Join(repoPath, config.FileName)))
+			opts = append(opts, config_legacy.WithPaths(filepath.Join(repoPath, config_legacy.FileName)))
 		}
-		c, err := config.New(
+		c, err := config_legacy.New(
 			opts...,
 		)
 		if err != nil {
@@ -89,7 +89,7 @@ var V2Migration = repo.NewMigration(
 			} else if err = os.MkdirAll(newStorePath, util.OS_USER_RWX); err != nil {
 				return err
 			}
-			set(types.NodeComputeExecutionStore, executionStore)
+			set(legacy_types.NodeComputeExecutionStore, executionStore)
 		}
 
 		if fileCfg.Node.Requester.JobStore.Path == "" {
@@ -112,11 +112,11 @@ var V2Migration = repo.NewMigration(
 			} else if err = os.MkdirAll(newStorePath, util.OS_USER_RWX); err != nil {
 				return err
 			}
-			set(types.NodeRequesterJobStore, jobStore)
+			set(legacy_types.NodeRequesterJobStore, jobStore)
 		}
 
 		if fileCfg.Node.Name == "" {
-			set(types.NodeName, libp2pNodeID)
+			set(legacy_types.NodeName, libp2pNodeID)
 		}
 
 		if doWrite {
diff --git a/pkg/repo/migrations/v3_4.go b/pkg/repo/migrations/v3_4.go
index dea0b50362..d212d63379 100644
--- a/pkg/repo/migrations/v3_4.go
+++ b/pkg/repo/migrations/v3_4.go
@@ -6,8 +6,14 @@ import (
 	"path/filepath"
 	"time"
 
+	"gopkg.in/yaml.v3"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
+	"github.com/bacalhau-project/bacalhau/pkg/storage/util"
 )
 
 // V3Migration updates the repo, replacing repo.version and update.json with system_metadata.yaml.
@@ -90,11 +96,54 @@ var V3Migration = repo.NewMigration(
 				return err
 			}
 		}
+
+		// iff there is a config file in the repo, try and move it to $XDG_CONFIG_HOME/bacalhau
+		{
+			oldConfigFilePath := filepath.Join(repoPath, config_legacy.FileName)
+			if _, err := os.Stat(oldConfigFilePath); err == nil {
+				if err := r.WriteInstallationID(fileCfg.User.InstallationID); err != nil {
+					return fmt.Errorf("migrating installation id: %w", err)
+				}
+				if err := r.WriteNodeName(fileCfg.Node.Name); err != nil {
+					return fmt.Errorf("migrating node name: %w", err)
+				}
+				newConfigType, err := config.MigrateV1(fileCfg)
+				if err != nil {
+					return fmt.Errorf("migrating to new config: %w", err)
+				}
+				// ensure the repo path of the config points to the repo
+				newConfigType.DataDir = repoPath
+				userConfigDir, err := os.UserConfigDir()
+				if err == nil {
+					newConfigDir := filepath.Join(userConfigDir, "bacalhau")
+					if err := os.Mkdir(newConfigDir, util.OS_USER_RWX); err != nil {
+						return err
+					}
+					newConfigFilePath := filepath.Join(newConfigDir, config_legacy.FileName)
+					if err := os.Rename(oldConfigFilePath, newConfigFilePath); err != nil {
+						return err
+					}
+					newConfigBytes, err := yaml.Marshal(&newConfigType)
+					if err != nil {
+						return err
+					}
+					newConfigFile, err := os.OpenFile(newConfigFilePath, os.O_RDWR|os.O_TRUNC, util.OS_USER_RWX)
+					if err != nil {
+						return err
+					}
+					defer newConfigFile.Close()
+					if _, err := newConfigFile.Write(newConfigBytes); err != nil {
+						return err
+					}
+				}
+			}
+
+		}
 		return nil
 	},
 )
 
-func migrateComputeStore(repoPath string, config types.JobStoreConfig) error {
+func migrateComputeStore(repoPath string, config legacy_types.JobStoreConfig) error {
 	oldComputeDir := filepath.Join(repoPath, "compute_store")
 	oldExecutionStorePath := config.Path
 	if oldExecutionStorePath == "" {
@@ -118,7 +167,7 @@ func migrateComputeStore(repoPath string, config types.JobStoreConfig) error {
 	return nil
 }
 
-func migrateOrchestratorStore(repoPath string, config types.JobStoreConfig) error {
+func migrateOrchestratorStore(repoPath string, config legacy_types.JobStoreConfig) error {
 	oldOrchestratorDir := filepath.Join(repoPath, "orchestrator_store")
 	oldJobStorePath := config.Path
 	if oldJobStorePath == "" {
diff --git a/pkg/repo/sysmeta.go b/pkg/repo/sysmeta.go
index 48fb8614c7..0e700431df 100644
--- a/pkg/repo/sysmeta.go
+++ b/pkg/repo/sysmeta.go
@@ -35,6 +35,7 @@ type SystemMetadata struct {
 	RepoVersion     int       `yaml:"RepoVersion"`
 	InstallationID  string    `yaml:"InstallationID"`
 	LastUpdateCheck time.Time `yaml:"LastUpdateCheck"`
+	NodeName        string    `yaml:"NodeName"`
 }
 
 // WriteVersion updates the RepoVersion in the SystemMetadataFile.
@@ -97,6 +98,20 @@ func (fsr *FsRepo) WriteInstallationID(id string) error {
 	})
 }
 
+func (fsr *FsRepo) ReadNodeName() (string, error) {
+	sysmeta, err := fsr.readMetadata()
+	if err != nil {
+		return "", err
+	}
+	return sysmeta.NodeName, nil
+}
+
+func (fsr *FsRepo) WriteNodeName(name string) error {
+	return fsr.updateExistingMetadata(func(sysmeta *SystemMetadata) {
+		sysmeta.NodeName = name
+	})
+}
+
 // readMetadata unmarshals the content of SystemMedataFile into SystemMetadata and returns it.
 // If fails if the metadata file doesn't exist.
 func (fsr *FsRepo) readMetadata() (*SystemMetadata, error) {
diff --git a/pkg/setup/setup.go b/pkg/setup/setup.go
index 5c3ece5250..23d68b6c1f 100644
--- a/pkg/setup/setup.go
+++ b/pkg/setup/setup.go
@@ -7,12 +7,9 @@ import (
 	"testing"
 	"time"
 
-	"github.com/pkg/errors"
-	"github.com/spf13/viper"
-
 	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/repo/migrations"
 
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
@@ -27,13 +24,16 @@ func SetupMigrationManager() (*repo.MigrationManager, error) {
 }
 
 // SetupBacalhauRepo ensures that a bacalhau repo and config exist and are initialized.
-func SetupBacalhauRepo(repoDir string, c config.ReadWriter) (*repo.FsRepo, error) {
+func SetupBacalhauRepo(cfg types.Bacalhau) (*repo.FsRepo, error) {
+	if err := logger.ConfigureLogging(cfg.Logging.Mode, cfg.Logging.Level); err != nil {
+		return nil, fmt.Errorf("failed to configure logging: %w", err)
+	}
 	migrationManger, err := SetupMigrationManager()
 	if err != nil {
 		return nil, fmt.Errorf("failed to create migration manager: %w", err)
 	}
 	fsRepo, err := repo.NewFS(repo.FsRepoParams{
-		Path:       repoDir,
+		Path:       cfg.DataDir,
 		Migrations: migrationManger,
 	})
 	if err != nil {
@@ -46,60 +46,65 @@ func SetupBacalhauRepo(repoDir string, c config.ReadWriter) (*repo.FsRepo, error
 
 		return nil, fmt.Errorf("failed to check if repo exists: %w", err)
 	} else if !exists {
-		if err := fsRepo.Init(c); err != nil {
+		if err := fsRepo.Init(cfg); err != nil {
 			return nil, fmt.Errorf("failed to initialize repo: %w", err)
 		}
 	} else {
-		if err := fsRepo.Open(c); err != nil {
+		if err := fsRepo.Open(); err != nil {
 			return nil, fmt.Errorf("failed to open repo: %w", err)
 		}
 	}
 	return fsRepo, nil
 }
 
-func SetupBacalhauRepoForTesting(t testing.TB) (*repo.FsRepo, types.BacalhauConfig) {
-	// reset the global viper instance used by cmds pkg.
-	viper.Reset()
-	// create a specific viper instance for testing
-	v := viper.New()
-	// init a config with this viper instance using the local configuration as default
-	cfg, err := config.New(config.WithDefault(configenv.Local))
-	if err != nil {
-		t.Fatal(err)
-	}
-
+func SetupBacalhauRepoForTesting(t testing.TB) (*repo.FsRepo, types.Bacalhau) {
 	// create a temporary dir to serve as bacalhau repo whose name includes the current time to avoid collisions with
 	/// other tests
 	tmpDir, err := os.MkdirTemp("", "")
 	if err != nil {
-		t.Fatal(errors.Wrap(err, "failed to create temporary directory in test setup"))
+		t.Fatal(err)
 	}
 	path := filepath.Join(tmpDir, fmt.Sprint(time.Now().UnixNano()))
-	// configure the repo on the testing viper insance
-	v.Set("repo", path)
 
-	t.Logf("creating repo for testing at: %s", path)
-	t.Setenv("BACALHAU_ENVIRONMENT", "local")
-	t.Setenv("BACALHAU_DIR", path)
+	// disable update checks in testing.
+	t.Setenv(config.KeyAsEnvVar(types.UpdateConfigIntervalKey), "0")
+	cfgValues := map[string]any{
+		types.DataDirKey: path,
+	}
 
-	// create the repo used for testing
-	fsRepo, err := SetupBacalhauRepo(path, cfg)
+	// the BACALHAU_NODE_IPFS_CONNECT env var is only bound if it's corresponding flags are registered.
+	// This is because viper cannot bind its value to any existing keys via viper.AutomaticEnv() since the
+	// environment variable doesn't map to a key in the config, so we add special handling here until we move away
+	// from this flag to the dedicated flags like "BACALHAU_PUBLISHER_IPFS_ENDPOINT",
+	// "BACALHAU_INPUTSOURCES_IPFS_ENDPOINT", etc which have a direct mapping to the config key based on their name.
+	if connect := os.Getenv("BACALHAU_NODE_IPFS_CONNECT"); connect != "" {
+		cfgValues[types.PublishersTypesIPFSEndpointKey] = connect
+		cfgValues[types.ResultDownloadersTypesIPFSEndpointKey] = connect
+		cfgValues[types.InputSourcesTypesIPFSEndpointKey] = connect
+	}
+
+	// init a config with this viper instance using the local configuration as default
+	c, err := config.New(config.WithValues(cfgValues))
 	if err != nil {
 		t.Fatal(err)
 	}
 
+	t.Logf("creating repo for testing at: %s", path)
 	t.Cleanup(func() {
-		// This may fail on windows, and if so then we'll log the error but not fail the test.
+		// This may fail to clean up due to nats store, log an error, don't fail testing
 		if err := os.RemoveAll(tmpDir); err != nil {
 			t.Logf("failed to clean up repo at: %s: %s", path, err)
 		}
 	})
-
-	// load the config with merged in settings from repo.
-	bcfg, err := cfg.Current()
+	var cfg types.Bacalhau
+	if err := c.Unmarshal(&cfg); err != nil {
+		t.Fatal(err)
+	}
+	// create the repo used for testing
+	fsRepo, err := SetupBacalhauRepo(cfg)
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	return fsRepo, bcfg
+	return fsRepo, cfg
 }
diff --git a/pkg/version/update.go b/pkg/version/update.go
index c5e6898930..f6b164b79d 100644
--- a/pkg/version/update.go
+++ b/pkg/version/update.go
@@ -105,6 +105,7 @@ func LogUpdateResponse(ctx context.Context, ucr *UpdateCheckResponse) {
 type UpdateStore interface {
 	ReadLastUpdateCheck() (time.Time, error)
 	WriteLastUpdateCheck(time.Time) error
+	ReadInstallationID() (string, error)
 }
 
 // RunUpdateChecker starts a goroutine that will periodically make an update
@@ -114,14 +115,14 @@ type UpdateStore interface {
 // (e.g. because the node running the update check is the server).
 func RunUpdateChecker(
 	ctx context.Context,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	store UpdateStore,
 	getServerVersion func(context.Context) (*models.BuildVersionInfo, error),
 	responseCallback func(context.Context, *UpdateCheckResponse),
 ) {
-	updateFrequency := time.Duration(cfg.Update.CheckFrequency)
+	updateFrequency := time.Duration(cfg.UpdateConfig.Interval)
 	if updateFrequency <= 0 {
-		log.Ctx(ctx).Warn().Dur(types.UpdateCheckFrequency, updateFrequency).Msg("Update frequency is zero or less so no update checks will run")
+		log.Ctx(ctx).Debug().Dur("interval", updateFrequency).Msg("Update frequency is zero or less so no update checks will run")
 		return
 	}
 
@@ -138,11 +139,6 @@ func RunUpdateChecker(
 	}
 
 	runUpdateCheck := func() {
-		if cfg.Update.SkipChecks {
-			log.Debug().Msg("skipping update check")
-			return
-		}
-
 		// The server may update itself between checks, so always ask the server
 		// for its current version.
 		// TODO(forrest): [correctness] this should be a local only call to get the version of the binary running this code
@@ -154,7 +150,14 @@ func RunUpdateChecker(
 			serverVersion = nil
 		}
 
-		updateResponse, err := CheckForUpdate(ctx, clientVersion, serverVersion, userKey.ClientID(), cfg.User.InstallationID)
+		installationID, err := store.ReadInstallationID()
+		if err != nil {
+			log.Ctx(ctx).Error().Err(err).Msg("failed to read user installationID")
+			// we can continue here and still use an empty string
+			// a failure here indicates the system metadata file is un-readable
+		}
+
+		updateResponse, err := CheckForUpdate(ctx, clientVersion, serverVersion, userKey.ClientID(), installationID)
 		if err != nil {
 			log.Ctx(ctx).Error().Err(err).Msg("Failed to perform update check")
 		}


Test patch:
diff --git a/cmd/cli/config/set_test.go b/cmd/cli/config/set_test.go
index a14ae8887d..9f65cdb717 100644
--- a/cmd/cli/config/set_test.go
+++ b/cmd/cli/config/set_test.go
@@ -7,180 +7,73 @@ import (
 	"os"
 	"path/filepath"
 	"testing"
-	"time"
 
-	"github.com/spf13/viper"
 	"github.com/stretchr/testify/require"
 	"sigs.k8s.io/yaml"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-	"github.com/bacalhau-project/bacalhau/pkg/setup"
 )
 
 // TestAdditiveSet calls sets on the config system sequentially with different values
 // and asserts that after each set only the newly set value was added to the config.
 // Essentially we are testing two different things:
-//   - custom type setting logger.LogMode, types.StorageType, model.JobSelectionDataLocality, etc.
-//   - only set values are added to the config.
 func TestAdditiveSet(t *testing.T) {
-	// this initializes the global viper configuration system
-	r, _ := setup.SetupBacalhauRepoForTesting(t)
-	repoPath, err := r.Path()
-	require.NoError(t, err)
-	viper.Set("repo", repoPath)
+	cfgFilePath := filepath.Join(t.TempDir(), "config.yaml")
 
-	err = setConfig("node.loggingmode", "json")
+	err := setConfig(cfgFilePath, "api.host", "127.0.0.1")
 	require.NoError(t, err)
-
-	expected := types.BacalhauConfig{Node: types.NodeConfig{LoggingMode: logger.LogModeJSON}}
-	actual := unmarshalConfigFile(t, repoPath)
-
-	require.Equal(t, expected, actual)
-
-	err = setConfig("node.compute.executionstore.type", "boltdb")
+	err = setConfig(cfgFilePath, "api.port", "1234")
 	require.NoError(t, err)
 
-	expected = types.BacalhauConfig{Node: types.NodeConfig{
-		LoggingMode: logger.LogModeJSON,
-		Compute: types.ComputeConfig{
-			ExecutionStore: types.JobStoreConfig{
-				Type: types.BoltDB,
-			},
-		},
-	}}
-	actual = unmarshalConfigFile(t, repoPath)
-
-	require.Equal(t, expected, actual)
-
-	err = setConfig("node.compute.jobselection.locality", "anywhere")
-	require.NoError(t, err)
-
-	expected = types.BacalhauConfig{Node: types.NodeConfig{
-		LoggingMode: logger.LogModeJSON,
-		Compute: types.ComputeConfig{
-			ExecutionStore: types.JobStoreConfig{
-				Type: types.BoltDB,
-			},
-			JobSelection: models.JobSelectionPolicy{
-				Locality: models.Anywhere,
-			},
-		},
-	}}
-	actual = unmarshalConfigFile(t, repoPath)
-
-	require.Equal(t, expected, actual)
-
-	err = setConfig("node.compute.jobtimeouts.jobnegotiationtimeout", "120s")
-	require.NoError(t, err)
-
-	expected = types.BacalhauConfig{Node: types.NodeConfig{
-		LoggingMode: logger.LogModeJSON,
-		Compute: types.ComputeConfig{
-			ExecutionStore: types.JobStoreConfig{
-				Type: types.BoltDB,
-			},
-			JobSelection: models.JobSelectionPolicy{
-				Locality: models.Anywhere,
-			},
-			JobTimeouts: types.JobTimeoutConfig{
-				JobNegotiationTimeout: types.Duration(time.Second * 120),
-			},
-		},
+	expected := types.Bacalhau{API: types.API{
+		Host: "127.0.0.1",
+		Port: 1234,
 	}}
-	actual = unmarshalConfigFile(t, repoPath)
+	actual := unmarshalConfigFile(t, cfgFilePath)
 
 	require.Equal(t, expected, actual)
 
-	err = setConfig("node.labels", "foo=bar", "bar=buz", "buz=baz")
+	err = setConfig(cfgFilePath, "compute.enabled", "true")
 	require.NoError(t, err)
-
-	expected = types.BacalhauConfig{Node: types.NodeConfig{
-		LoggingMode: logger.LogModeJSON,
-		Compute: types.ComputeConfig{
-			ExecutionStore: types.JobStoreConfig{
-				Type: types.BoltDB,
-			},
-			JobSelection: models.JobSelectionPolicy{
-				Locality: models.Anywhere,
-			},
-			JobTimeouts: types.JobTimeoutConfig{
-				JobNegotiationTimeout: types.Duration(time.Second * 120),
-			},
-		},
-		Labels: map[string]string{
-			"foo": "bar",
-			"bar": "buz",
-			"buz": "baz",
-		},
-	}}
-	actual = unmarshalConfigFile(t, repoPath)
-
-	require.Equal(t, expected, actual)
-
-	err = setConfig("node.clientapi.host", "0.0.0.0")
+	err = setConfig(cfgFilePath, "compute.orchestrators", "http://127.0.0.1:1234", "http://1.1.1.1:1234")
 	require.NoError(t, err)
 
-	expected = types.BacalhauConfig{Node: types.NodeConfig{
-		ClientAPI: types.APIConfig{
-			Host: "0.0.0.0",
+	expected = types.Bacalhau{
+		API: types.API{
+			Host: "127.0.0.1",
+			Port: 1234,
 		},
-		LoggingMode: logger.LogModeJSON,
-		Compute: types.ComputeConfig{
-			ExecutionStore: types.JobStoreConfig{
-				Type: types.BoltDB,
-			},
-			JobSelection: models.JobSelectionPolicy{
-				Locality: models.Anywhere,
-			},
-			JobTimeouts: types.JobTimeoutConfig{
-				JobNegotiationTimeout: types.Duration(time.Second * 120),
+		Compute: types.Compute{
+			Enabled: true,
+			Orchestrators: []string{
+				"http://127.0.0.1:1234",
+				"http://1.1.1.1:1234",
 			},
 		},
-		Labels: map[string]string{
-			"foo": "bar",
-			"bar": "buz",
-			"buz": "baz",
-		},
-	}}
-	actual = unmarshalConfigFile(t, repoPath)
+	}
+	actual = unmarshalConfigFile(t, cfgFilePath)
 
 	require.Equal(t, expected, actual)
 
 }
 
 func TestSetFailure(t *testing.T) {
-	// this initializes the global viper configuration system
-	r, _ := setup.SetupBacalhauRepoForTesting(t)
-	repoPath, err := r.Path()
-	require.NoError(t, err)
-	viper.Set("repo", repoPath)
-
-	// fails as there are too many values, we expect 1
-	err = setConfig("node.loggingmode", "json", "jayson", "mayson", "grayson")
-	require.Error(t, err)
-
-	// fails as baeson is not a valid type
-	err = setConfig("node.loggingmode", "baeson")
-	require.Error(t, err)
-
+	cfgFilePath := filepath.Join(t.TempDir(), "config.yaml")
 	// fails as the key isn't a valid config key
-	err = setConfig("not.a.config.key", "porkchop sandwiches")
+	err := setConfig(cfgFilePath, "not.a.config.key", "porkchop sandwiches")
 	require.Error(t, err)
 }
 
-func unmarshalConfigFile(t testing.TB, repoPath string) types.BacalhauConfig {
+func unmarshalConfigFile(t testing.TB, path string) types.Bacalhau {
 
-	configPath := filepath.Join(repoPath, "config.yaml")
-	configFile, err := os.Open(configPath)
+	configFile, err := os.Open(path)
 	require.NoError(t, err)
 	t.Cleanup(func() {
 		configFile.Close()
 	})
 	configData, err := io.ReadAll(configFile)
 	require.NoError(t, err)
-	var cfg types.BacalhauConfig
+	var cfg types.Bacalhau
 	err = yaml.Unmarshal(configData, &cfg)
 	require.NoError(t, err)
 	return cfg
diff --git a/cmd/cli/docker/docker_run_cli_test.go b/cmd/cli/docker/docker_run_cli_test.go
index acbd56505c..9f5f8d2539 100644
--- a/cmd/cli/docker/docker_run_cli_test.go
+++ b/cmd/cli/docker/docker_run_cli_test.go
@@ -13,6 +13,8 @@ import (
 	"github.com/stretchr/testify/require"
 	"sigs.k8s.io/yaml"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	dm "github.com/bacalhau-project/bacalhau/pkg/executor/docker/models"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	publisher_s3 "github.com/bacalhau-project/bacalhau/pkg/s3"
@@ -51,6 +53,9 @@ var (
 )
 
 func TestJobFlagParsing(t *testing.T) {
+	// disable the update checker in testing
+	t.Setenv(config.KeyAsEnvVar(types.UpdateConfigIntervalKey), "0")
+
 	repoPath := t.TempDir()
 	viper.Set("repo", repoPath)
 	tests := []struct {
diff --git a/cmd/cli/docker/docker_run_test.go b/cmd/cli/docker/docker_run_test.go
index 19a93cc7ea..28ba90b89c 100644
--- a/cmd/cli/docker/docker_run_test.go
+++ b/cmd/cli/docker/docker_run_test.go
@@ -505,7 +505,7 @@ func (s *DockerRunSuite) TestRun_Timeout_DefaultValue() {
 
 	j := testutils.GetJobFromTestOutput(ctx, s.T(), s.ClientV2, out)
 
-	s.Require().Equal(node.TestRequesterConfig.JobDefaults.TotalTimeout, j.Task().Timeouts.GetTotalTimeout(),
+	s.Require().EqualValues(node.TestRequesterConfig.JobDefaults.Batch.Task.Timeouts.TotalTimeout, j.Task().Timeouts.GetTotalTimeout(),
 		"Did not fall back to default timeout value")
 }
 
diff --git a/cmd/cli/job/get_test.go b/cmd/cli/job/get_test.go
index 35f98f46da..4d56d35ade 100644
--- a/cmd/cli/job/get_test.go
+++ b/cmd/cli/job/get_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/stretchr/testify/suite"
 
 	"github.com/bacalhau-project/bacalhau/cmd/util"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
 	testutils "github.com/bacalhau-project/bacalhau/pkg/test/utils"
@@ -43,7 +44,7 @@ func (s *GetSuite) SetupTest() {
 }
 
 func (s *GetSuite) TestGetSingleFileFromOutputBadChoice() {
-	testutils.MustHaveIPFS(s.T(), s.Config.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(s.T(), s.Config)
 	args := s.getDockerRunArgs([]string{
 		"--wait",
 		"--publisher", "ipfs",
@@ -53,7 +54,7 @@ func (s *GetSuite) TestGetSingleFileFromOutputBadChoice() {
 	jobID := system.FindJobIDInTestOutput(out)
 
 	_, getoutput, err := s.ExecuteTestCobraCommand("job", "get",
-		"--ipfs-connect", s.Config.Node.IPFS.Connect,
+		"--config", fmt.Sprintf("%s=%s", types.ResultDownloadersTypesIPFSEndpointKey, s.Config.ResultDownloaders.Types.IPFS.Endpoint),
 		fmt.Sprintf("%s/missing", jobID),
 	)
 
@@ -62,7 +63,7 @@ func (s *GetSuite) TestGetSingleFileFromOutputBadChoice() {
 }
 
 func (s *GetSuite) TestGetSingleFileFromOutput() {
-	testutils.MustHaveIPFS(s.T(), s.Config.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(s.T(), s.Config)
 	tempDir, cleanup := setupTempWorkingDir(s.T())
 	defer cleanup()
 
@@ -76,7 +77,7 @@ func (s *GetSuite) TestGetSingleFileFromOutput() {
 	hostID := s.Node.ID
 
 	_, getOutput, err := s.ExecuteTestCobraCommand("job", "get",
-		"--ipfs-connect", s.Config.Node.IPFS.Connect,
+		"--config", fmt.Sprintf("%s=%s", types.ResultDownloadersTypesIPFSEndpointKey, s.Config.ResultDownloaders.Types.IPFS.Endpoint),
 		fmt.Sprintf("%s/stdout", jobID),
 	)
 	require.NoError(s.T(), err, "Error getting results")
@@ -86,7 +87,7 @@ func (s *GetSuite) TestGetSingleFileFromOutput() {
 }
 
 func (s *GetSuite) TestGetSingleNestedFileFromOutput() {
-	testutils.MustHaveIPFS(s.T(), s.Config.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(s.T(), s.Config)
 	tempDir, cleanup := setupTempWorkingDir(s.T())
 	defer cleanup()
 
@@ -100,7 +101,7 @@ func (s *GetSuite) TestGetSingleNestedFileFromOutput() {
 	hostID := s.Node.ID
 
 	_, getOutput, err := s.ExecuteTestCobraCommand("job", "get",
-		"--ipfs-connect", s.Config.Node.IPFS.Connect,
+		"--config", fmt.Sprintf("%s=%s", types.ResultDownloadersTypesIPFSEndpointKey, s.Config.ResultDownloaders.Types.IPFS.Endpoint),
 		"--api-host", s.Node.APIServer.Address,
 		"--api-port", fmt.Sprintf("%d", s.Node.APIServer.Port),
 		fmt.Sprintf("%s/data/apples/file.txt", jobID),
diff --git a/cmd/cli/serve/serve_test.go b/cmd/cli/serve/serve_test.go
index 586887f548..9029fb8549 100644
--- a/cmd/cli/serve/serve_test.go
+++ b/cmd/cli/serve/serve_test.go
@@ -15,19 +15,19 @@ import (
 	"github.com/stretchr/testify/suite"
 	"golang.org/x/sync/errgroup"
 
+	cfgtypes "github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
 	clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
 	apitest "github.com/bacalhau-project/bacalhau/pkg/publicapi/test"
+	"github.com/bacalhau-project/bacalhau/pkg/setup"
 
 	"github.com/bacalhau-project/bacalhau/pkg/docker"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/marshaller"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 
 	cmd2 "github.com/bacalhau-project/bacalhau/cmd/cli"
-	cfgtypes "github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/setup"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
 	"github.com/bacalhau-project/bacalhau/pkg/types"
 	"github.com/bacalhau-project/bacalhau/pkg/util/closer"
@@ -45,7 +45,7 @@ type ServeSuite struct {
 	ctx      context.Context
 	repoPath string
 	protocol string
-	config   cfgtypes.BacalhauConfig
+	config   cfgtypes.Bacalhau
 }
 
 func TestServeSuite(t *testing.T) {
@@ -181,24 +181,9 @@ func (s *ServeSuite) TestHealthcheck() {
 	s.Require().Equal(http.StatusOK, statusCode, "Did not return 200 OK.")
 }
 
-func (s *ServeSuite) TestAPIPrintedForComputeNode() {
-	s.T().Skip("bacalhau is no longer used by station")
-	port, _ := s.serve("--node-type", "compute,requester", "--log-mode", string(logger.LogModeStation))
-	expectedURL := fmt.Sprintf("API: http://0.0.0.0:%d/api/v1/compute/debug", port)
-	actualUrl := s.out.String()
-
-	s.Require().Contains(actualUrl, expectedURL)
-}
-
-func (s *ServeSuite) TestAPINotPrintedForRequesterNode() {
-	port, _ := s.serve("--node-type", "requester", "--log-mode", string(logger.LogModeStation))
-	expectedURL := fmt.Sprintf("API: http://0.0.0.0:%d/compute/debug", port)
-	s.Require().NotContains(s.out.String(), expectedURL)
-}
-
 func (s *ServeSuite) TestCanSubmitJob() {
 	docker.MustHaveDocker(s.T())
-	port, err := s.serve("--node-type", "requester,compute")
+	port, err := s.serve("--orchestrator", "--compute")
 	s.Require().NoError(err)
 
 	client := clientv2.New(fmt.Sprintf("http://127.0.0.1:%d", port))
@@ -227,7 +212,7 @@ func (s *ServeSuite) TestCanSubmitJob() {
 
 func (s *ServeSuite) TestSelfSignedRequester() {
 	s.protocol = "https"
-	_, err := s.serve("--node-type", "requester", "--self-signed")
+	_, err := s.serve("--orchestrator", "--self-signed")
 	s.Require().NoError(err)
 }
 
@@ -248,23 +233,10 @@ func (s *ServeSuite) Test200ForRoot() {
 	if err != nil {
 		s.T().Fatal(err, "Could not get port for web-ui")
 	}
-	_, err = s.serve("--web-ui", "--web-ui-port", fmt.Sprintf("%d", webUIPort))
+	_, err = s.serve("-c", "webui.enabled=true", "-c", fmt.Sprintf("webui.listen=127.0.0.1:%d", webUIPort))
 	s.Require().NoError(err, "Error starting server")
 
 	_, statusCode, err := s.curlEndpoint(fmt.Sprintf("http://127.0.0.1:%d/", webUIPort))
 	s.Require().NoError(err, "Error curling root endpoint")
 	s.Require().Equal(http.StatusOK, statusCode, "Did not return 200 OK.")
 }
-
-// TODO: Can't figure out how to make this test work, it spits out the help text
-// func (s *ServeSuite) TestBadBacalhauDir() {
-// 	badDirString := "/BADDIR"
-
-// 	// if we set the peer connect to "env" it should return the peers from the env
-// 	originalEnv := os.Getenv("BACALHAU_ENVIRONMENT")
-// 	defer os.Setenv("BACALHAU_ENVIRONMENT", originalEnv)
-// 	os.Setenv("BACALHAU_DIR", badDirString)
-// 	_, err := s.serve("--node-type", "requester", "--node-type", "compute", RETURN_ERROR_FLAG)
-// 	s.Require().Contains(s.out.String(), "Could not write to")
-// 	s.Error(err)
-// }
diff --git a/cmd/testing/base.go b/cmd/testing/base.go
index d0e491c623..96c3a1811a 100644
--- a/cmd/testing/base.go
+++ b/cmd/testing/base.go
@@ -16,7 +16,6 @@ import (
 	"github.com/bacalhau-project/bacalhau/cmd/cli"
 	"github.com/bacalhau-project/bacalhau/cmd/util"
 	"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/devstack"
 	noop_executor "github.com/bacalhau-project/bacalhau/pkg/executor/noop"
@@ -31,7 +30,7 @@ type BaseSuite struct {
 	suite.Suite
 	Node            *node.Node
 	ClientV2        clientv2.API
-	Config          types.BacalhauConfig
+	Config          types.Bacalhau
 	Host            string
 	Port            uint16
 	AllowListedPath string
@@ -44,10 +43,6 @@ func (s *BaseSuite) SetupTest() {
 	fsr, cfg := setup.SetupBacalhauRepoForTesting(s.T())
 	s.Config = cfg
 
-	// TODO: Update checker is configured with production default configs
-	//  and not respecting the test environment. This is a temporary fix
-	os.Setenv(config.KeyAsEnvVar(types.UpdateSkipChecks), "true")
-
 	s.AllowListedPath = s.T().TempDir()
 
 	executionDir, err := cfg.ExecutionDir()
@@ -57,7 +52,7 @@ func (s *BaseSuite) SetupTest() {
 		JobSelectionPolicy: node.JobSelectionPolicy{
 			Locality: semantic.Anywhere,
 		},
-		LocalPublisher: types.LocalPublisherConfig{
+		LocalPublisher: types.LocalPublisher{
 			Address: "127.0.0.1",
 		},
 	})
@@ -74,7 +69,7 @@ func (s *BaseSuite) SetupTest() {
 		devstack.WithComputeConfig(computeConfig),
 		devstack.WithRequesterConfig(requesterConfig),
 		devstack.WithAllowListedLocalPaths([]string{s.AllowListedPath}),
-		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Node.Compute.ManifestCache),
+		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Engines),
 	)
 	s.Node = stack.Nodes[0]
 	s.Host = s.Node.APIServer.Address
@@ -134,6 +129,9 @@ func (s *BaseSuite) ExecuteTestCobraCommandWithStdin(stdin io.Reader, args ...st
 	buf := new(bytes.Buffer)
 	root := cli.NewRootCmd()
 	root.SetOut(buf)
+	// TODO(forrest): we should separate the ouputs from a command into different buffers for stderr and sdtout, otherwise
+	// log lines and other outputs (like the update checker) will be included in the returned buffer, and commands
+	// that make assertions on the output containing specific values, or being marshaller-able to yaml will fail.
 	root.SetErr(buf)
 	root.SetIn(stdin)
 
@@ -145,6 +143,7 @@ func (s *BaseSuite) ExecuteTestCobraCommandWithStdin(stdin io.Reader, args ...st
 	if !slices.Contains(args, "--api-port") {
 		arguments = append(arguments, "--api-port", fmt.Sprintf("%d", s.Port))
 	}
+
 	arguments = append(arguments, args...)
 
 	root.SetArgs(arguments)
diff --git a/cmd/testing/basetls.go b/cmd/testing/basetls.go
index 537e4a92a5..41058575a8 100644
--- a/cmd/testing/basetls.go
+++ b/cmd/testing/basetls.go
@@ -65,7 +65,7 @@ func (s *BaseTLSSuite) SetupTest() {
 		devstack.WithComputeConfig(computeConfig),
 		devstack.WithRequesterConfig(requesterConfig),
 		devstack.WithSelfSignedCertificate(serverCertPath, serverKeyPath),
-		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Node.Compute.ManifestCache),
+		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Engines),
 	)
 	s.Node = stack.Nodes[0]
 	s.Host = s.Node.APIServer.Address // NOTE: 0.0.0.0 will not work because we're testing TLS validation
diff --git a/cmd/util/flags/cliflags/config_test.go b/cmd/util/flags/cliflags/config_test.go
index 474aded256..c15c21b992 100644
--- a/cmd/util/flags/cliflags/config_test.go
+++ b/cmd/util/flags/cliflags/config_test.go
@@ -11,31 +11,9 @@ import (
 	"github.com/spf13/viper"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
-)
-
-// TestConfig represents our application's configuration structure
-
-// a subset of the whole bacalhau config
-type Config struct {
-	Node Node `yaml:"Node"`
-}
-
-type Node struct {
-	Name         string    `yaml:"Name,omitempty"`
-	NameProvider string    `yaml:"NameProvider,omitempty"`
-	ClientAPI    ClientAPI `yaml:"ClientAPI,omitempty"`
-	WebUI        WebUI     `yaml:"WebUI,omitempty"`
-}
-
-type WebUI struct {
-	Enabled bool `yaml:"Enabled,omitempty"`
-	Port    int  `yaml:"Port,omitempty"`
-}
 
-type ClientAPI struct {
-	Host string `yaml:"Host,omitempty"`
-	Port int    `yaml:"Port,omitempty"`
-}
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
 
 // createTempConfig creates a temporary config file with the given content
 func createTempConfig(content string) (string, error) {
@@ -63,7 +41,7 @@ func setupTestCommand() *cobra.Command {
 }
 
 // loadConfig loads the configuration from viper
-func loadConfig() (*Config, error) {
+func loadConfig() (*types.Bacalhau, error) {
 	configFiles := viper.GetStringSlice(RootCommandConfigFiles)
 	for _, f := range configFiles {
 		viper.SetConfigFile(f)
@@ -79,7 +57,7 @@ func loadConfig() (*Config, error) {
 	if err := viper.MergeConfigMap(base); err != nil {
 		return nil, err
 	}
-	var config Config
+	var config types.Bacalhau
 	if err := viper.Unmarshal(&config); err != nil {
 		return nil, err
 	}
@@ -91,12 +69,11 @@ func TestConfigMerging(t *testing.T) {
 	t.Run("SingleConfigFile", func(t *testing.T) {
 		viper.Reset()
 		content := `
-Node:
-  Name: the_name
-  NameProvider: the_provider
-  ClientAPI:
-    Host: 1.1.1.1
-    Port: 1111
+DataDir: the_name
+NameProvider: the_provider
+API:
+  Host: 1.1.1.1
+  Port: 1111
 `
 		configFile, err := createTempConfig(content)
 		require.NoError(t, err)
@@ -110,27 +87,26 @@ Node:
 		config, err := loadConfig()
 		require.NoError(t, err)
 
-		assert.Equal(t, "the_name", config.Node.Name)
-		assert.Equal(t, "the_provider", config.Node.NameProvider)
-		assert.Equal(t, "1.1.1.1", config.Node.ClientAPI.Host)
-		assert.Equal(t, 1111, config.Node.ClientAPI.Port)
+		assert.Equal(t, "the_name", config.DataDir)
+		assert.Equal(t, "the_provider", config.NameProvider)
+		assert.Equal(t, "1.1.1.1", config.API.Host)
+		assert.Equal(t, 1111, config.API.Port)
 	})
 
 	// Test case 2: Multiple config files with override
 	t.Run("MultipleConfigFiles", func(t *testing.T) {
 		viper.Reset()
 		baseContent := `
-Node:
-  Name: the_name
+  DataDir: the_name
   NameProvider: the_provider
-  ClientAPI:
+  API:
     Host: 1.1.1.1
     Port: 1111
 `
 		overrideContent := `
-Node:
-  Name: override
-  ClientAPI:
+
+  DataDir: override
+  API:
     Host: 2.2.2.2
 `
 		baseConfig, err := createTempConfig(baseContent)
@@ -149,21 +125,20 @@ Node:
 		config, err := loadConfig()
 		require.NoError(t, err)
 
-		assert.Equal(t, 1111, config.Node.ClientAPI.Port)
-		assert.Equal(t, "the_provider", config.Node.NameProvider)
+		assert.Equal(t, 1111, config.API.Port)
+		assert.Equal(t, "the_provider", config.NameProvider)
 		// This field was overridden by the second config
-		assert.Equal(t, "override", config.Node.Name)
-		assert.Equal(t, "2.2.2.2", config.Node.ClientAPI.Host)
+		assert.Equal(t, "override", config.DataDir)
+		assert.Equal(t, "2.2.2.2", config.API.Host)
 	})
 
 	// Test case 3: Config file with dot notation override
 	t.Run("ConfigFileWithDotNotation", func(t *testing.T) {
 		viper.Reset()
 		content := `
-Node:
-  Name: the_name
+  DataDir: the_name
   NameProvider: the_provider
-  ClientAPI:
+  API:
     Host: 1.1.1.1
     Port: 1111
 `
@@ -172,31 +147,31 @@ Node:
 		defer os.Remove(configFile)
 
 		cmd := setupTestCommand()
-		cmd.SetArgs([]string{"-c", configFile, "-c", "Node.Name=override", "-c", "Node.ClientAPI.Host=2.2.2.2"})
+		cmd.SetArgs([]string{"-c", configFile, "-c", "DataDir=override", "-c", "API.Host=2.2.2.2"})
 		err = cmd.Execute()
 		require.NoError(t, err)
 
 		config, err := loadConfig()
 		require.NoError(t, err)
 
-		assert.Equal(t, "the_provider", config.Node.NameProvider)
-		assert.Equal(t, 1111, config.Node.ClientAPI.Port)
+		assert.Equal(t, "the_provider", config.NameProvider)
+		assert.Equal(t, 1111, config.API.Port)
 		// overrides by flag
-		assert.Equal(t, "override", config.Node.Name)
-		assert.Equal(t, "2.2.2.2", config.Node.ClientAPI.Host)
+		assert.Equal(t, "override", config.DataDir)
+		assert.Equal(t, "2.2.2.2", config.API.Host)
 	})
 
 	// Test case 4: Dot notation without value (boolean true)
 	t.Run("DotNotationWithoutValue", func(t *testing.T) {
 		viper.Reset()
 		cmd := setupTestCommand()
-		cmd.SetArgs([]string{"-c", "Node.WebUI.Enabled"})
+		cmd.SetArgs([]string{"-c", "WebUI.Enabled"})
 		err := cmd.Execute()
 		require.NoError(t, err)
 
 		config, err := loadConfig()
 		require.NoError(t, err)
-		assert.True(t, config.Node.WebUI.Enabled)
+		assert.True(t, config.WebUI.Enabled)
 	})
 
 	// Test case 5: Multiple dot notation values
@@ -204,10 +179,10 @@ Node:
 		viper.Reset()
 		cmd := setupTestCommand()
 		cmd.SetArgs([]string{
-			"-c", "Node.WebUI.Enabled=true",
-			"-c", "Node.WebUI.Port=9090",
-			"-c", "Node.Name=node2",
-			"-c", "Node.NameProvider=the_provider",
+			"-c", "WebUI.Enabled=true",
+			"-c", "WebUI.Listen=0.0.0.0:9090",
+			"-c", "DataDir=node2",
+			"-c", "NameProvider=the_provider",
 		})
 		err := cmd.Execute()
 		require.NoError(t, err)
@@ -215,10 +190,10 @@ Node:
 		config, err := loadConfig()
 		require.NoError(t, err)
 
-		assert.True(t, config.Node.WebUI.Enabled)
-		assert.Equal(t, 9090, config.Node.WebUI.Port)
-		assert.Equal(t, "node2", config.Node.Name)
-		assert.Equal(t, "the_provider", config.Node.NameProvider)
+		assert.True(t, config.WebUI.Enabled)
+		assert.Equal(t, "0.0.0.0:9090", config.WebUI.Listen)
+		assert.Equal(t, "node2", config.DataDir)
+		assert.Equal(t, "the_provider", config.NameProvider)
 	})
 
 	// Test case 6: Mixing config file and multiple dot notation values
@@ -226,15 +201,14 @@ Node:
 	t.Run("MixedConfigFileAndDotNotation", func(t *testing.T) {
 		viper.Reset()
 		content := `
-Node:
-  Name: the_name
+  DataDir: the_name
   NameProvider: the_provider
-  ClientAPI:
+  API:
     Host: 1.1.1.1
     Port: 1111
   WebUI:
     Enabled: false
-    Port: 8888
+    Listen: 0.0.0.0:8888
 `
 		configFile, err := createTempConfig(content)
 		require.NoError(t, err)
@@ -243,9 +217,9 @@ Node:
 		cmd := setupTestCommand()
 		cmd.SetArgs([]string{
 			"-c", configFile,
-			"-c", "Node.WebUI.Enabled=true",
-			"-c", "Node.WebUI.Port=9090",
-			"-c", "Node.ClientAPI.Host=192.168.1.5",
+			"-c", "WebUI.Enabled=true",
+			"-c", "WebUI.Listen=0.0.0.0:9090",
+			"-c", "API.Host=192.168.1.5",
 		})
 		err = cmd.Execute()
 		require.NoError(t, err)
@@ -253,14 +227,14 @@ Node:
 		config, err := loadConfig()
 		require.NoError(t, err)
 
-		assert.Equal(t, "the_name", config.Node.Name)
-		assert.Equal(t, "the_provider", config.Node.NameProvider)
-		assert.Equal(t, 1111, config.Node.ClientAPI.Port)
+		assert.Equal(t, "the_name", config.DataDir)
+		assert.Equal(t, "the_provider", config.NameProvider)
+		assert.Equal(t, 1111, config.API.Port)
 
 		// overrider from flag
-		assert.True(t, config.Node.WebUI.Enabled)
-		assert.Equal(t, 9090, config.Node.WebUI.Port)
-		assert.Equal(t, "192.168.1.5", config.Node.ClientAPI.Host)
+		assert.True(t, config.WebUI.Enabled)
+		assert.Equal(t, "0.0.0.0:9090", config.WebUI.Listen)
+		assert.Equal(t, "192.168.1.5", config.API.Host)
 	})
 
 }
diff --git a/cmd/util/repo_test.go b/cmd/util/repo_test.go
deleted file mode 100644
index 77bb13932d..0000000000
--- a/cmd/util/repo_test.go
+++ /dev/null
@@ -1,180 +0,0 @@
-//go:build unit || !integration
-
-package util_test
-
-import (
-	"os"
-	"path/filepath"
-	"runtime"
-	"testing"
-
-	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-
-	"github.com/bacalhau-project/bacalhau/cmd/util"
-	"github.com/bacalhau-project/bacalhau/cmd/util/flags/cliflags"
-	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
-)
-
-func TestSetupConfig(t *testing.T) {
-	t.Setenv("BACALHAU_ENVIRONMENT", "production")
-
-	testCases := []struct {
-		name               string
-		repoConfig         string
-		xdgConfig          string
-		flagConfig         string
-		expectedClientHost string
-	}{
-		{
-			name:               "No Parameters",
-			expectedClientHost: configenv.Production.Node.ClientAPI.Host,
-		},
-		{
-			name: "Config in Repo",
-			repoConfig: `
-Node:
-  ClientAPI:
-    Host: 1.1.1.1
-`,
-			expectedClientHost: "1.1.1.1",
-		},
-		{
-			name: "Config in $XDG_CONFIG_HOME/bacalhau/config.yaml",
-			xdgConfig: `
-Node:
-  ClientAPI:
-    Host: 2.2.2.2
-`,
-			expectedClientHost: "2.2.2.2",
-		},
-		{
-			name: "config in repo and $XDG_CONFIG_HOME/bacalhau/config.yaml",
-			repoConfig: `
-Node:
-  ClientAPI:
-    Host: 1.1.1.1
-`,
-			xdgConfig: `
-Node:
-  ClientAPI:
-    Host: 2.2.2.2
-`,
-			expectedClientHost: "2.2.2.2",
-		},
-		{
-			name: "config in repo and $XDG_CONFIG_HOME/bacalhau/config.yaml and flag",
-			repoConfig: `
-Node:
-  ClientAPI:
-    Host: 1.1.1.1
-`,
-			xdgConfig: `
-Node:
-  ClientAPI:
-    Host: 2.2.2.2
-`,
-			flagConfig: `
-Node:
-  ClientAPI:
-    Host: 3.3.3.3
-`,
-			expectedClientHost: "3.3.3.3",
-		},
-		{
-			name: "config only from flag",
-			flagConfig: `
-Node:
-  ClientAPI:
-    Host: 3.3.3.3
-`,
-			expectedClientHost: "3.3.3.3",
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			// reset viper for each test run
-			viper.Reset()
-			defer viper.Reset()
-
-			// ensure the repo path is always present
-			v := viper.GetViper()
-			repoPath := t.TempDir()
-			v.Set("repo", repoPath)
-
-			// create config files for test case if provided
-			if tc.repoConfig != "" {
-				_, err := createTempConfig(repoPath, tc.repoConfig)
-				require.NoError(t, err)
-			}
-
-			if tc.xdgConfig != "" {
-				xdgDir := t.TempDir()
-				setXDGConfigEnv(t, xdgDir)
-				_, err := createTempConfig(xdgDir, tc.xdgConfig)
-				require.NoError(t, err)
-			}
-
-			cmd, err := setupTestCommand()
-			require.NoError(t, err)
-
-			if tc.flagConfig != "" {
-				flagConfigDir := t.TempDir()
-				flagConfigFile, err := createTempConfig(flagConfigDir, tc.flagConfig)
-				require.NoError(t, err)
-				cmd.SetArgs([]string{"--config", flagConfigFile})
-			}
-
-			// invoke the command to trigger flag parsing
-			require.NoError(t, cmd.Execute())
-
-			cfg, err := util.SetupConfig(cmd)
-			require.NoError(t, err)
-			require.NotNil(t, cfg)
-			bacalhauCfg, err := cfg.Current()
-			require.NoError(t, err)
-
-			assert.Equal(t, tc.expectedClientHost, bacalhauCfg.Node.ClientAPI.Host)
-		})
-	}
-}
-
-func setupTestCommand() (*cobra.Command, error) {
-	cmd := &cobra.Command{
-		Use: "test",
-		Run: func(cmd *cobra.Command, args []string) {},
-	}
-	cmd.PersistentFlags().VarP(cliflags.NewConfigFlag(), "config", "c", "config file(s) or dot separated path(s) to config values")
-	return cmd, nil
-}
-
-func createTempConfig(path, content string) (string, error) {
-	tmpfile, err := os.Create(filepath.Join(path, config.FileName))
-	if err != nil {
-		return "", err
-	}
-	if _, err := tmpfile.Write([]byte(content)); err != nil {
-		return "", err
-	}
-	if err := tmpfile.Close(); err != nil {
-		return "", err
-	}
-	return tmpfile.Name(), nil
-}
-
-func setXDGConfigEnv(t *testing.T, xdgDir string) {
-	switch runtime.GOOS {
-	case "windows":
-		t.Setenv("AppData", xdgDir)
-	case "darwin", "ios":
-		t.Setenv("HOME", xdgDir)
-	case "plan9":
-		t.Setenv("home", xdgDir)
-	default: // Unix
-		t.Setenv("XDG_CONFIG_HOME", xdgDir)
-	}
-}
diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go
index 2d922f0b09..680ac345e0 100644
--- a/pkg/config/config_test.go
+++ b/pkg/config/config_test.go
@@ -3,78 +3,581 @@
 package config_test
 
 import (
-	"fmt"
-	"path/filepath"
+	"os"
 	"testing"
-	"time"
 
+	"github.com/spf13/pflag"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
-func TestConfig(t *testing.T) {
-	// Cleanup viper settings after each test
+func TestConfigWithValueOverrides(t *testing.T) {
+	overrideRepo := "overrideRepo"
+	overrideName := "puuid"
+	overrideClientAddress := "1.1.1.1"
+	overrideClientPort := 1234
 
-	// Testing Set and Get
-	t.Run("NewWriteRead", func(t *testing.T) {
-		// create a testing config instance
-		expectedConfig := configenv.Testing
-		wc, err := config.New(config.WithDefault(expectedConfig))
-		require.NoError(t, err)
+	defaultConfig := types.Bacalhau{
+		DataDir: "defaultRepo",
+		API: types.API{
+			Host: "0.0.0.0",
+			Port: 1234,
+		},
+		Logging: types.Logging{
+			Level: "info",
+		},
+	}
+	overrideValues := map[string]any{
+		"datadir":      overrideRepo,
+		"nameprovider": overrideName,
+		"api.host":     overrideClientAddress,
+		"api.port":     overrideClientPort,
+	}
+
+	cfg, err := config.New(
+		config.WithDefault(defaultConfig),
+		config.WithValues(overrideValues),
+	)
+	require.NoError(t, err)
+
+	var actual types.Bacalhau
+	err = cfg.Unmarshal(&actual)
+	require.NoError(t, err)
+
+	assert.Equal(t, overrideRepo, actual.DataDir)
+	assert.Equal(t, overrideClientAddress, actual.API.Host)
+	assert.Equal(t, overrideClientPort, actual.API.Port)
+	assert.Empty(t, actual.Orchestrator)
+	assert.Empty(t, actual.Compute)
+}
+
+type TestConfig struct {
+	StringValue string
+	IntValue    int
+	BoolValue   bool
+}
+
+func (c TestConfig) Validate() error {
+	return nil
+}
 
-		// write the config file to disk
-		cfgFilePath := filepath.Join(t.TempDir(), fmt.Sprintf("%d_config.yaml", time.Now().UnixNano()))
-		err = wc.Write(cfgFilePath)
+func TestNew(t *testing.T) {
+	t.Run("Default Configuration", func(t *testing.T) {
+		cfg, err := config.New(config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    42,
+			BoolValue:   true,
+		}))
 		require.NoError(t, err)
 
-		// read the file we wrote from disk
-		rc, err := config.New(config.WithDefault(expectedConfig))
+		var testCfg TestConfig
+		err = cfg.Unmarshal(&testCfg)
 		require.NoError(t, err)
-		err = rc.Load(cfgFilePath)
+
+		assert.Equal(t, "default", testCfg.StringValue)
+		assert.Equal(t, 42, testCfg.IntValue)
+		assert.True(t, testCfg.BoolValue)
+	})
+
+	t.Run("With Configuration File", func(t *testing.T) {
+		tempFile, err := os.CreateTemp("", "config*.yaml")
 		require.NoError(t, err)
+		defer os.Remove(tempFile.Name())
 
-		wCfg, err := wc.Current()
+		_, err = tempFile.WriteString(`
+stringValue: "from_file"
+intValue: 100
+boolValue: false
+`)
 		require.NoError(t, err)
-		rCfg, err := rc.Current()
+		tempFile.Close()
+
+		cfg, err := config.New(
+			config.WithDefault(TestConfig{
+				StringValue: "default",
+				IntValue:    42,
+				BoolValue:   true,
+			}),
+			config.WithPaths(tempFile.Name()),
+		)
 		require.NoError(t, err)
 
-		assert.Equal(t, expectedConfig.Node.Network, wCfg.Node.Network)
-		assert.Equal(t, expectedConfig.Node.Network, rCfg.Node.Network)
+		var testCfg TestConfig
+		err = cfg.Unmarshal(&testCfg)
+		require.NoError(t, err)
 
+		assert.Equal(t, "from_file", testCfg.StringValue)
+		assert.Equal(t, 100, testCfg.IntValue)
+		assert.False(t, testCfg.BoolValue)
 	})
 
-	t.Run("SetAndWrite", func(t *testing.T) {
-		// create a testing config instance
-		expectedConfig := configenv.Testing
-		expectedConfig.Node.Name = "unexpected_name"
-		wc, err := config.New(config.WithDefault(expectedConfig))
+	t.Run("With Flags", func(t *testing.T) {
+		flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
+		flagSet.String("stringValue", "default", "test string value")
+		flagSet.Int("intValue", 42, "test int value")
+		flagSet.Bool("boolValue", true, "test bool value")
+
+		err := flagSet.Parse([]string{"--stringValue=from_flag", "--intValue=200", "--boolValue=false"})
 		require.NoError(t, err)
 
-		const expectedName = "bacalhau_testing"
-		wc.Set(types.NodeName, expectedName)
-		// write the config file to disk
-		cfgFilePath := filepath.Join(t.TempDir(), fmt.Sprintf("%d_config.yaml", time.Now().UnixNano()))
-		err = wc.Write(cfgFilePath)
+		flags := make(map[string][]*pflag.Flag)
+		flagSet.VisitAll(func(f *pflag.Flag) {
+			flags[f.Name] = []*pflag.Flag{f}
+		})
+
+		cfg, err := config.New(
+			config.WithDefault(TestConfig{
+				StringValue: "default",
+				IntValue:    42,
+				BoolValue:   true,
+			}),
+			config.WithFlags(flags),
+		)
 		require.NoError(t, err)
 
-		// read the file we wrote from disk
-		rc, err := config.New(config.WithDefault(expectedConfig))
+		var testCfg TestConfig
+		err = cfg.Unmarshal(&testCfg)
 		require.NoError(t, err)
-		err = rc.Load(cfgFilePath)
+
+		assert.Equal(t, "from_flag", testCfg.StringValue)
+		assert.Equal(t, 200, testCfg.IntValue)
+		assert.False(t, testCfg.BoolValue)
+	})
+
+	t.Run("With Environment Variables", func(t *testing.T) {
+		os.Setenv("BACALHAU_STRING_VALUE", "from_env")
+		os.Setenv("BACALHAU_INT_VALUE", "300")
+		os.Setenv("BACALHAU_BOOL_VALUE", "true")
+		defer func() {
+			os.Unsetenv("BACALHAU_STRING_VALUE")
+			os.Unsetenv("BACALHAU_INT_VALUE")
+			os.Unsetenv("BACALHAU_BOOL_VALUE")
+		}()
+
+		envVars := map[string][]string{
+			"stringValue": {"BACALHAU_STRING_VALUE"},
+			"intValue":    {"BACALHAU_INT_VALUE"},
+			"boolValue":   {"BACALHAU_BOOL_VALUE"},
+		}
+
+		cfg, err := config.New(
+			config.WithDefault(TestConfig{
+				StringValue: "default",
+				IntValue:    42,
+				BoolValue:   false,
+			}),
+			config.WithEnvironmentVariables(envVars),
+		)
 		require.NoError(t, err)
 
-		wCfg, err := wc.Current()
+		var testCfg TestConfig
+		err = cfg.Unmarshal(&testCfg)
 		require.NoError(t, err)
-		rCfg, err := rc.Current()
+
+		assert.Equal(t, "from_env", testCfg.StringValue)
+		assert.Equal(t, 300, testCfg.IntValue)
+		assert.True(t, testCfg.BoolValue)
+	})
+
+	t.Run("With Values", func(t *testing.T) {
+		values := map[string]interface{}{
+			"stringValue": "from_values",
+			"intValue":    400,
+			"boolValue":   false,
+		}
+
+		cfg, err := config.New(
+			config.WithDefault(TestConfig{
+				StringValue: "default",
+				IntValue:    42,
+				BoolValue:   true,
+			}),
+			config.WithValues(values),
+		)
 		require.NoError(t, err)
 
-		assert.Equal(t, expectedName, rCfg.Node.Name)
-		assert.Equal(t, expectedName, wCfg.Node.Name)
+		var testCfg TestConfig
+		err = cfg.Unmarshal(&testCfg)
+		require.NoError(t, err)
 
+		assert.Equal(t, "from_values", testCfg.StringValue)
+		assert.Equal(t, 400, testCfg.IntValue)
+		assert.False(t, testCfg.BoolValue)
 	})
+}
+
+func TestLoad(t *testing.T) {
+	tempFile, err := os.CreateTemp("", "config*.yaml")
+	require.NoError(t, err)
+	defer os.Remove(tempFile.Name())
+
+	_, err = tempFile.WriteString(`
+stringValue: "loaded"
+intValue: 500
+boolValue: true
+`)
+	require.NoError(t, err)
+	tempFile.Close()
+
+	cfg, err := config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    42,
+			BoolValue:   false,
+		}),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Load(tempFile.Name())
+	require.NoError(t, err)
+
+	var testCfg TestConfig
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "loaded", testCfg.StringValue)
+	assert.Equal(t, 500, testCfg.IntValue)
+	assert.True(t, testCfg.BoolValue)
+}
+
+func TestMerge(t *testing.T) {
+	tempFile1, err := os.CreateTemp("", "config1*.yaml")
+	require.NoError(t, err)
+	defer os.Remove(tempFile1.Name())
+
+	_, err = tempFile1.WriteString(`
+stringValue: "first"
+intValue: 100
+`)
+	require.NoError(t, err)
+	tempFile1.Close()
+
+	tempFile2, err := os.CreateTemp("", "config2*.yaml")
+	require.NoError(t, err)
+	defer os.Remove(tempFile2.Name())
+
+	_, err = tempFile2.WriteString(`
+intValue: 200
+boolValue: true
+`)
+	require.NoError(t, err)
+	tempFile2.Close()
+
+	cfg, err := config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    42,
+			BoolValue:   false,
+		}),
+		config.WithPaths(tempFile1.Name()),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Merge(tempFile2.Name())
+	require.NoError(t, err)
+
+	var testCfg TestConfig
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "first", testCfg.StringValue)
+	assert.Equal(t, 200, testCfg.IntValue)
+	assert.True(t, testCfg.BoolValue)
+}
+
+func TestConfigurationPrecedence(t *testing.T) {
+	// Create a temporary config file
+	tempFile, err := os.CreateTemp("", "config*.yaml")
+	require.NoError(t, err)
+	defer os.Remove(tempFile.Name())
+
+	_, err = tempFile.WriteString(`
+stringValue: "from_file"
+intValue: 100
+boolValue: false
+`)
+	require.NoError(t, err)
+	tempFile.Close()
+
+	// Set up environment variables
+	os.Setenv("BACALHAU_STRING_VALUE", "from_env")
+	os.Setenv("BACALHAU_INT_VALUE", "200")
+	os.Setenv("BACALHAU_BOOL_VALUE", "true")
+	defer func() {
+		os.Unsetenv("BACALHAU_STRING_VALUE")
+		os.Unsetenv("BACALHAU_INT_VALUE")
+		os.Unsetenv("BACALHAU_BOOL_VALUE")
+	}()
+
+	// Set up flags
+	flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
+	flagSet.String("stringValue", "", "test string value")
+	flagSet.Int("intValue", 0, "test int value")
+	flagSet.Bool("boolValue", false, "test bool value")
+
+	err = flagSet.Parse([]string{"--stringValue=from_flag", "--intValue=300", "--boolValue=false"})
+	require.NoError(t, err)
+
+	flags := make(map[string][]*pflag.Flag)
+	flagSet.VisitAll(func(f *pflag.Flag) {
+		flags[f.Name] = []*pflag.Flag{f}
+	})
+
+	// Set up explicit values
+	values := map[string]interface{}{
+		"stringValue": "from_values",
+		"intValue":    400,
+		"boolValue":   true,
+	}
+
+	// Create the configuration
+	cfg, err := config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    50,
+			BoolValue:   false,
+		}),
+		config.WithPaths(tempFile.Name()),
+		config.WithEnvironmentVariables(map[string][]string{
+			"stringValue": {"BACALHAU_STRING_VALUE"},
+			"intValue":    {"BACALHAU_INT_VALUE"},
+			"boolValue":   {"BACALHAU_BOOL_VALUE"},
+		}),
+		config.WithFlags(flags),
+		config.WithValues(values),
+	)
+	require.NoError(t, err)
+
+	var testCfg TestConfig
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	// Assert the final configuration values
+	assert.Equal(t, "from_values", testCfg.StringValue, "StringValue should be overridden by explicit values")
+	assert.Equal(t, 400, testCfg.IntValue, "IntValue should be overridden by explicit values")
+	assert.True(t, testCfg.BoolValue, "BoolValue should be overridden by explicit values")
+
+	// Now, let's remove the explicit values and check the precedence of flags
+	cfg, err = config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    50,
+			BoolValue:   false,
+		}),
+		config.WithPaths(tempFile.Name()),
+		config.WithEnvironmentVariables(map[string][]string{
+			"stringValue": {"BACALHAU_STRING_VALUE"},
+			"intValue":    {"BACALHAU_INT_VALUE"},
+			"boolValue":   {"BACALHAU_BOOL_VALUE"},
+		}),
+		config.WithFlags(flags),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "from_flag", testCfg.StringValue, "StringValue should be overridden by flags")
+	assert.Equal(t, 300, testCfg.IntValue, "IntValue should be overridden by flags")
+	assert.False(t, testCfg.BoolValue, "BoolValue should be overridden by flags")
+
+	// Remove flags and check precedence of environment variables
+	cfg, err = config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    50,
+			BoolValue:   false,
+		}),
+		config.WithPaths(tempFile.Name()),
+		config.WithEnvironmentVariables(map[string][]string{
+			"stringValue": {"BACALHAU_STRING_VALUE"},
+			"intValue":    {"BACALHAU_INT_VALUE"},
+			"boolValue":   {"BACALHAU_BOOL_VALUE"},
+		}),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "from_env", testCfg.StringValue, "StringValue should be overridden by environment variables")
+	assert.Equal(t, 200, testCfg.IntValue, "IntValue should be overridden by environment variables")
+	assert.True(t, testCfg.BoolValue, "BoolValue should be overridden by environment variables")
+
+	// Remove environment variables and check precedence of configuration file
+	os.Unsetenv("BACALHAU_STRING_VALUE")
+	os.Unsetenv("BACALHAU_INT_VALUE")
+	os.Unsetenv("BACALHAU_BOOL_VALUE")
+
+	cfg, err = config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    50,
+			BoolValue:   true,
+		}),
+		config.WithPaths(tempFile.Name()),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "from_file", testCfg.StringValue, "StringValue should be overridden by configuration file")
+	assert.Equal(t, 100, testCfg.IntValue, "IntValue should be overridden by configuration file")
+	assert.False(t, testCfg.BoolValue, "BoolValue should be overridden by configuration file")
+
+	// Finally, check default values
+	cfg, err = config.New(
+		config.WithDefault(TestConfig{
+			StringValue: "default",
+			IntValue:    50,
+			BoolValue:   true,
+		}),
+	)
+	require.NoError(t, err)
+
+	err = cfg.Unmarshal(&testCfg)
+	require.NoError(t, err)
+
+	assert.Equal(t, "default", testCfg.StringValue, "StringValue should be set to default")
+	assert.Equal(t, 50, testCfg.IntValue, "IntValue should be set to default")
+	assert.True(t, testCfg.BoolValue, "BoolValue should be set to default")
+}
+
+type LargeConfig struct {
+	Database struct {
+		Host     string
+		Port     int
+		Username string
+		Password string
+	}
+	Server struct {
+		Host string
+		Port int
+	}
+	Logging struct {
+		Level  string
+		Format string
+	}
+}
+
+func (c LargeConfig) Validate() error {
+	return nil
+}
+
+type DatabaseConfig struct {
+	Database struct {
+		Host     string
+		Port     int
+		Username string
+		Password string
+	}
+}
+
+func (c DatabaseConfig) Validate() error {
+	return nil
+}
+
+type ServerLoggingConfig struct {
+	Server struct {
+		Host string
+		Port int
+	}
+	Logging struct {
+		Level string
+	}
+}
+
+func (c ServerLoggingConfig) Validate() error {
+	return nil
+}
+
+type ExtendedServerConfig struct {
+	Server struct {
+		Host    string
+		Port    int
+		Timeout int // This field is not in the original config
+	}
+}
+
+func (c ExtendedServerConfig) Validate() error {
+	return nil
+}
+
+// TestUnmarshalSubset tests that config.Unmarshal works correctly with subsets of a larger configuration
+func TestUnmarshalSubset(t *testing.T) {
+
+	// Create a temporary config file with all settings
+	tempFile, err := os.CreateTemp("", "large_config*.yaml")
+	require.NoError(t, err)
+	defer os.Remove(tempFile.Name())
+
+	_, err = tempFile.WriteString(`
+database:
+  host: "localhost"
+  port: 5432
+  username: "user"
+  password: "password"
+server:
+  host: "0.0.0.0"
+  port: 8080
+logging:
+  level: "info"
+  format: "json"
+`)
+	require.NoError(t, err)
+	tempFile.Close()
+
+	// Create the configuration
+	cfg, err := config.New(
+		config.WithPaths(tempFile.Name()),
+	)
+	require.NoError(t, err)
+
+	// Test unmarshaling the entire configuration
+	var fullConfig LargeConfig
+	err = cfg.Unmarshal(&fullConfig)
+	require.NoError(t, err)
+	require.NoError(t, fullConfig.Validate())
+
+	assert.Equal(t, "localhost", fullConfig.Database.Host)
+	assert.Equal(t, 5432, fullConfig.Database.Port)
+	assert.Equal(t, "user", fullConfig.Database.Username)
+	assert.Equal(t, "password", fullConfig.Database.Password)
+	assert.Equal(t, "0.0.0.0", fullConfig.Server.Host)
+	assert.Equal(t, 8080, fullConfig.Server.Port)
+	assert.Equal(t, "info", fullConfig.Logging.Level)
+	assert.Equal(t, "json", fullConfig.Logging.Format)
+
+	// dbConfig is a subset, ensure we can unmarshal into it.
+	var dbConfig DatabaseConfig
+	err = cfg.Unmarshal(&dbConfig)
+	require.NoError(t, err)
+	require.NoError(t, dbConfig.Validate())
+
+	assert.Equal(t, "localhost", dbConfig.Database.Host)
+	assert.Equal(t, 5432, dbConfig.Database.Port)
+	assert.Equal(t, "user", dbConfig.Database.Username)
+	assert.Equal(t, "password", dbConfig.Database.Password)
+
+	var slConfig ServerLoggingConfig
+	err = cfg.Unmarshal(&slConfig)
+	require.NoError(t, err)
+	require.NoError(t, slConfig.Validate())
+
+	assert.Equal(t, "0.0.0.0", slConfig.Server.Host)
+	assert.Equal(t, 8080, slConfig.Server.Port)
+	assert.Equal(t, "info", slConfig.Logging.Level)
+
+	var extConfig ExtendedServerConfig
+	err = cfg.Unmarshal(&extConfig)
+	require.NoError(t, err)
+	require.NoError(t, extConfig.Validate())
 
+	assert.Equal(t, "0.0.0.0", extConfig.Server.Host)
+	assert.Equal(t, 8080, extConfig.Server.Port)
+	assert.Zero(t, extConfig.Server.Timeout, "Timeout should be zero as it's not in the original config")
 }
diff --git a/pkg/config/configenv/test.go b/pkg/config/configenv/test.go
deleted file mode 100644
index 472d33f455..0000000000
--- a/pkg/config/configenv/test.go
+++ /dev/null
@@ -1,180 +0,0 @@
-//nolint:gomnd
-package configenv
-
-import (
-	"os"
-	"runtime"
-	"time"
-
-	"github.com/bacalhau-project/bacalhau/pkg/authn"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	"github.com/bacalhau-project/bacalhau/pkg/logger"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-)
-
-var Testing = types.BacalhauConfig{
-	Metrics: types.MetricsConfig{
-		EventTracerPath: os.DevNull,
-	},
-	Update: types.UpdateConfig{
-		SkipChecks: true,
-	},
-	Auth: types.AuthConfig{
-		Methods: map[string]types.AuthenticatorConfig{
-			"ClientKey": {
-				Type: authn.MethodTypeChallenge,
-			},
-		},
-	},
-	Node: types.NodeConfig{
-		NameProvider: "puuid",
-		ClientAPI: types.APIConfig{
-			Host: "test",
-			Port: 9999,
-		},
-		ServerAPI: types.APIConfig{
-			Host: "test",
-			Port: 9999,
-			TLS:  types.TLSConfiguration{},
-		},
-		Network: types.NetworkConfig{
-			Port: 4222,
-		},
-		DownloadURLRequestTimeout: types.Duration(300 * time.Second),
-		VolumeSizeRequestTimeout:  types.Duration(2 * time.Minute),
-		DownloadURLRequestRetries: 3,
-		LoggingMode:               logger.LogModeDefault,
-		Type:                      []string{"requester"},
-		AllowListedLocalPaths:     []string{},
-		Labels:                    map[string]string{},
-		DisabledFeatures: types.FeatureConfig{
-			Engines:    []string{},
-			Publishers: []string{},
-			Storages:   []string{},
-		},
-		IPFS: types.IpfsConfig{
-			Connect: "",
-		},
-		Compute:   TestingComputeConfig,
-		Requester: TestingRequesterConfig,
-		WebUI: types.WebUIConfig{
-			Enabled: false,
-			Port:    8483,
-		},
-		StrictVersionMatch: false,
-	},
-}
-
-var TestingComputeConfig = types.ComputeConfig{
-	Capacity: types.CapacityConfig{
-		IgnorePhysicalResourceLimits: false,
-		TotalResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		JobResourceLimits: models.ResourcesConfig{
-			CPU:    "",
-			Memory: "",
-			Disk:   "",
-			GPU:    "",
-		},
-		DefaultJobResourceLimits: models.ResourcesConfig{
-			CPU:    "100m",
-			Memory: "100Mi",
-			Disk:   "",
-			GPU:    "",
-		},
-	},
-	ExecutionStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	JobTimeouts: types.JobTimeoutConfig{
-		JobExecutionTimeoutClientIDBypassList: []string{},
-		JobNegotiationTimeout:                 types.Duration(3 * time.Minute),
-		MinJobExecutionTimeout:                types.Duration(500 * time.Millisecond),
-		MaxJobExecutionTimeout:                types.Duration(models.NoTimeout),
-		DefaultJobExecutionTimeout:            types.Duration(10 * time.Minute),
-	},
-	JobSelection: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	Logging: types.LoggingConfig{
-		LogRunningExecutionsInterval: types.Duration(10 * time.Second),
-	},
-	ManifestCache: types.DockerCacheConfig{
-		Size:      1000,
-		Duration:  types.Duration(1 * time.Hour),
-		Frequency: types.Duration(1 * time.Hour),
-	},
-	LogStreamConfig: types.LogStreamConfig{
-		ChannelBufferSize: 10,
-	},
-	LocalPublisher: types.LocalPublisherConfig{
-		Address: "private",
-		Port:    6001,
-	},
-	ControlPlaneSettings: types.ComputeControlPlaneConfig{
-		InfoUpdateFrequency:     types.Duration(60 * time.Second),
-		ResourceUpdateFrequency: types.Duration(30 * time.Second),
-		HeartbeatFrequency:      types.Duration(15 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-	},
-}
-
-var TestingRequesterConfig = types.RequesterConfig{
-	ExternalVerifierHook: "",
-	JobSelectionPolicy: models.JobSelectionPolicy{
-		Locality:            models.Anywhere,
-		RejectStatelessJobs: false,
-		AcceptNetworkedJobs: false,
-		ProbeHTTP:           "",
-		ProbeExec:           "",
-	},
-	JobStore: types.JobStoreConfig{
-		Type: types.BoltDB,
-		Path: "",
-	},
-	HousekeepingBackgroundTaskInterval: types.Duration(30 * time.Second),
-	NodeRankRandomnessRange:            5,
-	OverAskForBidsFactor:               3,
-	FailureInjectionConfig: models.FailureInjectionRequesterConfig{
-		IsBadActor: false,
-	},
-	EvaluationBroker: types.EvaluationBrokerConfig{
-		EvalBrokerVisibilityTimeout:    types.Duration(60 * time.Second),
-		EvalBrokerInitialRetryDelay:    types.Duration(1 * time.Second),
-		EvalBrokerSubsequentRetryDelay: types.Duration(30 * time.Second),
-		EvalBrokerMaxRetryCount:        10,
-	},
-	Worker: types.WorkerConfig{
-		WorkerCount:                  runtime.NumCPU(),
-		WorkerEvalDequeueTimeout:     types.Duration(5 * time.Second),
-		WorkerEvalDequeueBaseBackoff: types.Duration(1 * time.Second),
-		WorkerEvalDequeueMaxBackoff:  types.Duration(30 * time.Second),
-	},
-	Scheduler: types.SchedulerConfig{
-		QueueBackoff:               types.Duration(5 * time.Second),
-		NodeOverSubscriptionFactor: 1.5,
-	},
-	JobDefaults: types.JobDefaults{
-		TotalTimeout: types.Duration(30 * time.Second),
-	},
-	StorageProvider: types.StorageProviderConfig{
-		S3: types.S3StorageProviderConfig{
-			PreSignedURLExpiration: types.Duration(30 * time.Minute),
-		},
-	},
-	ControlPlaneSettings: types.RequesterControlPlaneConfig{
-		HeartbeatCheckFrequency: types.Duration(30 * time.Second),
-		HeartbeatTopic:          "heartbeat",
-		NodeDisconnectedAfter:   types.Duration(30 * time.Second),
-	},
-	NodeInfoStoreTTL: types.Duration(10 * time.Minute),
-}
diff --git a/pkg/config/types/parse_test.go b/pkg/config/types/parse_test.go
new file mode 100644
index 0000000000..f80e2cfa4f
--- /dev/null
+++ b/pkg/config/types/parse_test.go
@@ -0,0 +1,185 @@
+//go:build unit || !integration
+
+package types_test
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+)
+
+func TestCastConfigValueForKey(t *testing.T) {
+	tests := []struct {
+		name        string
+		key         string
+		value       interface{}
+		expected    interface{}
+		expectedErr bool
+	}{
+		{
+			name:     "valid string value",
+			key:      types.APIHostKey,
+			value:    "localhost",
+			expected: "localhost",
+		},
+		{
+			name:     "valid int value",
+			key:      types.APIPortKey,
+			value:    "8080",
+			expected: int64(8080),
+		},
+		{
+			name:        "invalid int value",
+			key:         types.APIPortKey,
+			value:       "not an int",
+			expectedErr: true,
+		},
+		{
+			name:     "valid bool value",
+			key:      types.WebUIEnabledKey,
+			value:    "true",
+			expected: true,
+		},
+		{
+			name:        "invalid bool value",
+			key:         types.WebUIEnabledKey,
+			value:       "not a bool",
+			expectedErr: true,
+		},
+		{
+			name:     "valid duration value",
+			key:      types.OrchestratorNodeManagerDisconnectTimeoutKey,
+			value:    "5m",
+			expected: "5m0s",
+		},
+		{
+			name:        "invalid duration value",
+			key:         types.OrchestratorNodeManagerDisconnectTimeoutKey,
+			value:       "not a duration",
+			expectedErr: true,
+		},
+		{
+			name:     "valid single string",
+			key:      types.ComputeOrchestratorsKey,
+			value:    "nats://127.0.0.1:4222",
+			expected: []string{"nats://127.0.0.1:4222"},
+		},
+		{
+			name:     "valid comma-separated string",
+			key:      types.ComputeOrchestratorsKey,
+			value:    "nats://127.0.0.1:4222,nats://127.0.0.1:4223",
+			expected: []string{"nats://127.0.0.1:4222", "nats://127.0.0.1:4223"},
+		},
+		{
+			name:        "invalid string separator ;",
+			key:         types.ComputeOrchestratorsKey,
+			value:       "nats://127.0.0.1:4222;nats://127.0.0.1:4223",
+			expectedErr: true,
+		},
+		{
+			name:        "invalid string separator space",
+			key:         types.ComputeOrchestratorsKey,
+			value:       "nats://127.0.0.1:4222 nats://127.0.0.1:4223",
+			expectedErr: true,
+		},
+		{
+			name:        "mismatched separators and tokens",
+			key:         types.ComputeOrchestratorsKey,
+			value:       "nats://127.0.0.1:4222,nats://127.0.0.1:4223,",
+			expectedErr: true,
+		},
+		{
+			name:     "valid string slice",
+			key:      types.ComputeOrchestratorsKey,
+			value:    []string{"nats://127.0.0.1:4222", "nats://127.0.0.1:4223"},
+			expected: []string{"nats://127.0.0.1:4222", "nats://127.0.0.1:4223"},
+		},
+		{
+			name:     "valid map with single value",
+			key:      types.ComputeLabelsKey,
+			value:    "key1=value1",
+			expected: map[string]string{"key1": "value1"},
+		},
+		{
+			name:     "valid map with values",
+			key:      types.ComputeLabelsKey,
+			value:    "key1=value1,key2=value2",
+			expected: map[string]string{"key1": "value1", "key2": "value2"},
+		},
+		{
+			name:        "invalid map value",
+			key:         types.ComputeLabelsKey,
+			value:       "invalid map format",
+			expectedErr: true,
+		},
+		{
+			name:        "invalid key",
+			key:         "InvalidKey",
+			value:       "some value",
+			expectedErr: true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			result, err := types.CastConfigValueForKey(tt.key, tt.value)
+
+			if tt.expectedErr {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				assert.Equal(t, tt.expected, result)
+			}
+		})
+	}
+}
+
+func TestCastConfigValueForKey_BoolInput(t *testing.T) {
+	result, err := types.CastConfigValueForKey("WebUI.Enabled", true)
+	require.NoError(t, err)
+	assert.Equal(t, true, result)
+
+	result, err = types.CastConfigValueForKey("WebUI.Enabled", false)
+	require.NoError(t, err)
+	assert.Equal(t, false, result)
+}
+
+func TestCastConfigValueForKey_StringSliceInput(t *testing.T) {
+	input := []string{"nats://127.0.0.1:4222", "nats://127.0.0.1:4223"}
+	result, err := types.CastConfigValueForKey("Compute.Orchestrators", input)
+	require.NoError(t, err)
+	assert.Equal(t, input, result)
+}
+
+func TestCastConfigValueForKey_UnsupportedType(t *testing.T) {
+	_, err := types.CastConfigValueForKey("API.Host", 123) // Passing an int instead of a string or []string
+	require.Error(t, err)
+	assert.Contains(t, err.Error(), "DEVELOPER ERROR CastConfigValueForKey called with unsupported type: int")
+}
+
+func TestAllKeys(t *testing.T) {
+	keys := types.AllKeys()
+
+	// Test a few expected keys
+	assert.Contains(t, keys, "api.host")
+	assert.Equal(t, reflect.TypeOf(""), keys["api.host"])
+
+	assert.Contains(t, keys, "api.port")
+	assert.Equal(t, reflect.TypeOf(0), keys["api.port"])
+
+	assert.Contains(t, keys, "webui.enabled")
+	assert.Equal(t, reflect.TypeOf(false), keys["webui.enabled"])
+
+	assert.Contains(t, keys, "orchestrator.nodemanager.disconnecttimeout")
+	assert.Equal(t, reflect.TypeOf(types.Duration(0)), keys["orchestrator.nodemanager.disconnecttimeout"])
+
+	assert.Contains(t, keys, "compute.orchestrators")
+	assert.Equal(t, reflect.TypeOf([]string{}), keys["compute.orchestrators"])
+
+	assert.Contains(t, keys, "compute.labels")
+	assert.Equal(t, reflect.TypeOf(map[string]string{}), keys["compute.labels"])
+}
diff --git a/pkg/config/types/resource_test.go b/pkg/config/types/resource_test.go
new file mode 100644
index 0000000000..a0c50a0c38
--- /dev/null
+++ b/pkg/config/types/resource_test.go
@@ -0,0 +1,173 @@
+//go:build unit || !integration
+
+package types
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/bacalhau-project/bacalhau/pkg/models"
+)
+
+func TestScaler(t *testing.T) {
+	systemCapacity := models.Resources{
+		CPU:    10,
+		Memory: 10,
+		Disk:   10,
+		GPU:    1,
+	}
+
+	scaler := ResourceScaler{
+		CPU:    "80%",
+		Memory: "70%",
+		Disk:   "60%",
+		GPU:    "50%",
+	}
+
+	out, err := scaler.ToResource(systemCapacity)
+	require.NoError(t, err)
+
+	assert.EqualValues(t, 8, out.CPU)
+	assert.EqualValues(t, 7, out.Memory)
+	assert.EqualValues(t, 6, out.Disk)
+	assert.EqualValues(t, 1, out.GPU)
+}
+
+func TestResources(t *testing.T) {
+	systemCapacity := models.Resources{
+		CPU:    10,
+		Memory: 10,
+		Disk:   10,
+		GPU:    1,
+	}
+
+	scaler := ResourceScaler{
+		CPU:    "10000m",
+		Memory: "10GB",
+		Disk:   "100GB",
+		GPU:    "4",
+	}
+
+	out, err := scaler.ToResource(systemCapacity)
+	require.NoError(t, err)
+
+	assert.EqualValues(t, 10, out.CPU)
+	assert.EqualValues(t, 10_000_000_000, out.Memory)
+	assert.EqualValues(t, 100_000_000_000, out.Disk)
+	assert.EqualValues(t, 4, out.GPU)
+}
+
+func TestScaleGPU(t *testing.T) {
+	t.Run("scaling single GPU results in 1 GPU unit", func(t *testing.T) {
+		systemCapacity := models.Resources{
+			CPU:    10,
+			Memory: 10,
+			Disk:   10,
+			GPU:    1,
+		}
+
+		scaler := ResourceScaler{
+			CPU:    "80%",
+			Memory: "70%",
+			Disk:   "60%",
+			GPU:    "50%",
+		}
+
+		out, err := scaler.ToResource(systemCapacity)
+		require.NoError(t, err)
+
+		// ensure 50% of a GPU is still 1 gpu
+		assert.EqualValues(t, 1, out.GPU)
+	})
+
+	t.Run("scaling zero GPU results in 0 GPU unit", func(t *testing.T) {
+		systemCapacity := models.Resources{
+			CPU:    10,
+			Memory: 10,
+			Disk:   10,
+			GPU:    0,
+		}
+
+		scaler := ResourceScaler{
+			CPU:    "80%",
+			Memory: "70%",
+			Disk:   "60%",
+			GPU:    "50%",
+		}
+
+		out, err := scaler.ToResource(systemCapacity)
+		require.NoError(t, err)
+
+		// ensure 50% of a GPU is still 1 gpu
+		assert.EqualValues(t, 0, out.GPU)
+	})
+
+	t.Run("scaling 2 GPU to 50% results in 1 GPU unit", func(t *testing.T) {
+		systemCapacity := models.Resources{
+			CPU:    10,
+			Memory: 10,
+			Disk:   10,
+			GPU:    2,
+		}
+
+		scaler := ResourceScaler{
+			CPU:    "80%",
+			Memory: "70%",
+			Disk:   "60%",
+			GPU:    "50%",
+		}
+
+		out, err := scaler.ToResource(systemCapacity)
+		require.NoError(t, err)
+
+		// ensure 50% of a GPU is still 1 gpu
+		assert.EqualValues(t, 1, out.GPU)
+	})
+
+	t.Run("scaling 2 GPU to 1% results in 1 GPU unit", func(t *testing.T) {
+		systemCapacity := models.Resources{
+			CPU:    10,
+			Memory: 10,
+			Disk:   10,
+			GPU:    2,
+		}
+
+		scaler := ResourceScaler{
+			CPU:    "80%",
+			Memory: "70%",
+			Disk:   "60%",
+			GPU:    "1%",
+		}
+
+		out, err := scaler.ToResource(systemCapacity)
+		require.NoError(t, err)
+
+		// ensure 50% of a GPU is still 1 gpu
+		assert.EqualValues(t, 1, out.GPU)
+	})
+
+	t.Run("scaling 4 GPU to 75% results in 3 GPU unit", func(t *testing.T) {
+		systemCapacity := models.Resources{
+			CPU:    10,
+			Memory: 10,
+			Disk:   10,
+			GPU:    4,
+		}
+
+		scaler := ResourceScaler{
+			CPU:    "80%",
+			Memory: "70%",
+			Disk:   "60%",
+			GPU:    "75%",
+		}
+
+		out, err := scaler.ToResource(systemCapacity)
+		require.NoError(t, err)
+
+		// ensure 50% of a GPU is still 1 gpu
+		assert.EqualValues(t, 3, out.GPU)
+	})
+
+}
diff --git a/pkg/config/config_internal_test.go b/pkg/config_legacy/config_internal_test.go
similarity index 93%
rename from pkg/config/config_internal_test.go
rename to pkg/config_legacy/config_internal_test.go
index 9ce074d117..3716da1e1e 100644
--- a/pkg/config/config_internal_test.go
+++ b/pkg/config_legacy/config_internal_test.go
@@ -1,6 +1,6 @@
 //go:build unit || !integration
 
-package config
+package config_legacy
 
 import (
 	"os"
@@ -12,8 +12,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"gopkg.in/yaml.v3"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 )
 
 func TestConfigWithNoValues(t *testing.T) {
@@ -21,7 +20,7 @@ func TestConfigWithNoValues(t *testing.T) {
 	viper.Reset()
 	defer viper.Reset()
 
-	defaultConfig := configenv.Testing
+	defaultConfig := legacy_types.Testing
 
 	// Create the config without any file
 	cfg, err := New(
@@ -44,12 +43,12 @@ func TestConfigWithNoFile(t *testing.T) {
 	viper.Reset()
 	defer viper.Reset()
 
-	defaultConfig := configenv.Testing
+	defaultConfig := legacy_types.Testing
 
 	// simulate a user setting a value from the command line with goes to the global viper instance
 	// e.g. bacalhau -c node.clientapi.port=123456 -c node.clientapi.host=HOST
-	viper.Set(types.NodeClientAPIPort, 123456)
-	viper.Set(types.NodeClientAPIHost, "HOST")
+	viper.Set(legacy_types.NodeClientAPIPort, 123456)
+	viper.Set(legacy_types.NodeClientAPIHost, "HOST")
 
 	// set and env var to ensure it overrides the default config
 	t.Setenv("BACALHAU_NODE_WEBUI_ENABLED", "true")
@@ -85,12 +84,12 @@ func TestConfigWithSingleFile(t *testing.T) {
 	// Set up temporary directory for config file
 	tempDir := t.TempDir()
 
-	defaultConfig := configenv.Testing
+	defaultConfig := legacy_types.Testing
 
 	// simulate a user setting a value from the command line with goes to the global viper instance
 	// e.g. bacalhau -c node.clientapi.port=123456 -c node.clientapi.host=HOST
-	viper.Set(types.NodeClientAPIPort, 123456)
-	viper.Set(types.NodeClientAPIHost, "HOST")
+	viper.Set(legacy_types.NodeClientAPIPort, 123456)
+	viper.Set(legacy_types.NodeClientAPIHost, "HOST")
 
 	// set and env var to ensure it overrides the default config
 	t.Setenv("BACALHAU_NODE_WEBUI_ENABLED", "true")
@@ -147,12 +146,12 @@ func TestConfigMultipleFiles(t *testing.T) {
 	// Set up temporary directory for config files
 	tempDir := t.TempDir()
 
-	defaultConfig := configenv.Testing
+	defaultConfig := legacy_types.Testing
 
 	// simulate a user setting a value from the command line with goes to the global viper instance
 	// e.g. bacalhau -c node.clientapi.port=123456 -c node.clientapi.host=HOST
-	viper.Set(types.NodeClientAPIPort, 123456)
-	viper.Set(types.NodeClientAPIHost, "HOST")
+	viper.Set(legacy_types.NodeClientAPIPort, 123456)
+	viper.Set(legacy_types.NodeClientAPIHost, "HOST")
 
 	// set and env var to ensure it overrides the default config
 	t.Setenv("BACALHAU_NODE_WEBUI_ENABLED", "true")
diff --git a/pkg/config_legacy/config_test.go b/pkg/config_legacy/config_test.go
new file mode 100644
index 0000000000..9144226a58
--- /dev/null
+++ b/pkg/config_legacy/config_test.go
@@ -0,0 +1,79 @@
+//go:build unit || !integration
+
+package config_legacy_test
+
+import (
+	"fmt"
+	"path/filepath"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
+)
+
+func TestConfig(t *testing.T) {
+	// Cleanup viper settings after each test
+
+	// Testing Set and Get
+	t.Run("NewWriteRead", func(t *testing.T) {
+		// create a testing config instance
+		expectedConfig := types.Testing
+		wc, err := config_legacy.New(config_legacy.WithDefault(expectedConfig))
+		require.NoError(t, err)
+
+		// write the config file to disk
+		cfgFilePath := filepath.Join(t.TempDir(), fmt.Sprintf("%d_config.yaml", time.Now().UnixNano()))
+		err = wc.Write(cfgFilePath)
+		require.NoError(t, err)
+
+		// read the file we wrote from disk
+		rc, err := config_legacy.New(config_legacy.WithDefault(expectedConfig))
+		require.NoError(t, err)
+		err = rc.Load(cfgFilePath)
+		require.NoError(t, err)
+
+		wCfg, err := wc.Current()
+		require.NoError(t, err)
+		rCfg, err := rc.Current()
+		require.NoError(t, err)
+
+		assert.Equal(t, expectedConfig.Node.Network, wCfg.Node.Network)
+		assert.Equal(t, expectedConfig.Node.Network, rCfg.Node.Network)
+
+	})
+
+	t.Run("SetAndWrite", func(t *testing.T) {
+		// create a testing config instance
+		expectedConfig := types.Testing
+		expectedConfig.Node.Name = "unexpected_name"
+		wc, err := config_legacy.New(config_legacy.WithDefault(expectedConfig))
+		require.NoError(t, err)
+
+		const expectedName = "bacalhau_testing"
+		wc.Set(types.NodeName, expectedName)
+		// write the config file to disk
+		cfgFilePath := filepath.Join(t.TempDir(), fmt.Sprintf("%d_config.yaml", time.Now().UnixNano()))
+		err = wc.Write(cfgFilePath)
+		require.NoError(t, err)
+
+		// read the file we wrote from disk
+		rc, err := config_legacy.New(config_legacy.WithDefault(expectedConfig))
+		require.NoError(t, err)
+		err = rc.Load(cfgFilePath)
+		require.NoError(t, err)
+
+		wCfg, err := wc.Current()
+		require.NoError(t, err)
+		rCfg, err := rc.Current()
+		require.NoError(t, err)
+
+		assert.Equal(t, expectedName, rCfg.Node.Name)
+		assert.Equal(t, expectedName, wCfg.Node.Name)
+
+	})
+
+}
diff --git a/pkg/config_legacy/types/testing.go b/pkg/config_legacy/types/testing.go
new file mode 100644
index 0000000000..e8db44a145
--- /dev/null
+++ b/pkg/config_legacy/types/testing.go
@@ -0,0 +1,179 @@
+//nolint:gomnd
+package types
+
+import (
+	"os"
+	"runtime"
+	"time"
+
+	"github.com/bacalhau-project/bacalhau/pkg/authn"
+	"github.com/bacalhau-project/bacalhau/pkg/logger"
+	"github.com/bacalhau-project/bacalhau/pkg/models"
+)
+
+var Testing = BacalhauConfig{
+	Metrics: MetricsConfig{
+		EventTracerPath: os.DevNull,
+	},
+	Update: UpdateConfig{
+		SkipChecks: true,
+	},
+	Auth: AuthConfig{
+		Methods: map[string]AuthenticatorConfig{
+			"ClientKey": {
+				Type: authn.MethodTypeChallenge,
+			},
+		},
+	},
+	Node: NodeConfig{
+		NameProvider: "puuid",
+		ClientAPI: APIConfig{
+			Host: "test",
+			Port: 9999,
+		},
+		ServerAPI: APIConfig{
+			Host: "test",
+			Port: 9999,
+			TLS:  TLSConfiguration{},
+		},
+		Network: NetworkConfig{
+			Port: 4222,
+		},
+		DownloadURLRequestTimeout: Duration(300 * time.Second),
+		VolumeSizeRequestTimeout:  Duration(2 * time.Minute),
+		DownloadURLRequestRetries: 3,
+		LoggingMode:               logger.LogModeDefault,
+		Type:                      []string{"requester"},
+		AllowListedLocalPaths:     []string{},
+		Labels:                    map[string]string{},
+		DisabledFeatures: FeatureConfig{
+			Engines:    []string{},
+			Publishers: []string{},
+			Storages:   []string{},
+		},
+		IPFS: IpfsConfig{
+			Connect: "",
+		},
+		Compute:   TestingComputeConfig,
+		Requester: TestingRequesterConfig,
+		WebUI: WebUIConfig{
+			Enabled: false,
+			Port:    8483,
+		},
+		StrictVersionMatch: false,
+	},
+}
+
+var TestingComputeConfig = ComputeConfig{
+	Capacity: CapacityConfig{
+		IgnorePhysicalResourceLimits: false,
+		TotalResourceLimits: models.ResourcesConfig{
+			CPU:    "",
+			Memory: "",
+			Disk:   "",
+			GPU:    "",
+		},
+		JobResourceLimits: models.ResourcesConfig{
+			CPU:    "",
+			Memory: "",
+			Disk:   "",
+			GPU:    "",
+		},
+		DefaultJobResourceLimits: models.ResourcesConfig{
+			CPU:    "100m",
+			Memory: "100Mi",
+			Disk:   "",
+			GPU:    "",
+		},
+	},
+	ExecutionStore: JobStoreConfig{
+		Type: BoltDB,
+		Path: "",
+	},
+	JobTimeouts: JobTimeoutConfig{
+		JobExecutionTimeoutClientIDBypassList: []string{},
+		JobNegotiationTimeout:                 Duration(3 * time.Minute),
+		MinJobExecutionTimeout:                Duration(500 * time.Millisecond),
+		MaxJobExecutionTimeout:                Duration(models.NoTimeout),
+		DefaultJobExecutionTimeout:            Duration(10 * time.Minute),
+	},
+	JobSelection: models.JobSelectionPolicy{
+		Locality:            models.Anywhere,
+		RejectStatelessJobs: false,
+		AcceptNetworkedJobs: false,
+		ProbeHTTP:           "",
+		ProbeExec:           "",
+	},
+	Logging: LoggingConfig{
+		LogRunningExecutionsInterval: Duration(10 * time.Second),
+	},
+	ManifestCache: DockerCacheConfig{
+		Size:      1000,
+		Duration:  Duration(1 * time.Hour),
+		Frequency: Duration(1 * time.Hour),
+	},
+	LogStreamConfig: LogStreamConfig{
+		ChannelBufferSize: 10,
+	},
+	LocalPublisher: LocalPublisherConfig{
+		Address: "private",
+		Port:    6001,
+	},
+	ControlPlaneSettings: ComputeControlPlaneConfig{
+		InfoUpdateFrequency:     Duration(60 * time.Second),
+		ResourceUpdateFrequency: Duration(30 * time.Second),
+		HeartbeatFrequency:      Duration(15 * time.Second),
+		HeartbeatTopic:          "heartbeat",
+	},
+}
+
+var TestingRequesterConfig = RequesterConfig{
+	ExternalVerifierHook: "",
+	JobSelectionPolicy: models.JobSelectionPolicy{
+		Locality:            models.Anywhere,
+		RejectStatelessJobs: false,
+		AcceptNetworkedJobs: false,
+		ProbeHTTP:           "",
+		ProbeExec:           "",
+	},
+	JobStore: JobStoreConfig{
+		Type: BoltDB,
+		Path: "",
+	},
+	HousekeepingBackgroundTaskInterval: Duration(30 * time.Second),
+	NodeRankRandomnessRange:            5,
+	OverAskForBidsFactor:               3,
+	FailureInjectionConfig: models.FailureInjectionRequesterConfig{
+		IsBadActor: false,
+	},
+	EvaluationBroker: EvaluationBrokerConfig{
+		EvalBrokerVisibilityTimeout:    Duration(60 * time.Second),
+		EvalBrokerInitialRetryDelay:    Duration(1 * time.Second),
+		EvalBrokerSubsequentRetryDelay: Duration(30 * time.Second),
+		EvalBrokerMaxRetryCount:        10,
+	},
+	Worker: WorkerConfig{
+		WorkerCount:                  runtime.NumCPU(),
+		WorkerEvalDequeueTimeout:     Duration(5 * time.Second),
+		WorkerEvalDequeueBaseBackoff: Duration(1 * time.Second),
+		WorkerEvalDequeueMaxBackoff:  Duration(30 * time.Second),
+	},
+	Scheduler: SchedulerConfig{
+		QueueBackoff:               Duration(5 * time.Second),
+		NodeOverSubscriptionFactor: 1.5,
+	},
+	JobDefaults: JobDefaults{
+		TotalTimeout: Duration(30 * time.Second),
+	},
+	StorageProvider: StorageProviderConfig{
+		S3: S3StorageProviderConfig{
+			PreSignedURLExpiration: Duration(30 * time.Minute),
+		},
+	},
+	ControlPlaneSettings: RequesterControlPlaneConfig{
+		HeartbeatCheckFrequency: Duration(30 * time.Second),
+		HeartbeatTopic:          "heartbeat",
+		NodeDisconnectedAfter:   Duration(30 * time.Second),
+	},
+	NodeInfoStoreTTL: Duration(10 * time.Minute),
+}
diff --git a/pkg/docker/cache_test.go b/pkg/docker/cache_test.go
index cf07c9a21c..dcded3ccb4 100644
--- a/pkg/docker/cache_test.go
+++ b/pkg/docker/cache_test.go
@@ -9,7 +9,8 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/docker"
 )
 
@@ -24,7 +25,11 @@ func TestDockerCache(t *testing.T) {
 func (s *DockerCacheTestSuite) TestDefaultsSize() {
 	sampleVal := docker.ImageManifest{}
 
-	mc := docker.NewManifestCache(configenv.Testing.Node.Compute.ManifestCache)
+	mc := docker.NewManifestCache(types.DockerManifestCache{
+		Size:    legacy_types.Testing.Node.Compute.ManifestCache.Size,
+		TTL:     types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Duration),
+		Refresh: types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Frequency),
+	})
 	for i := 0; i < 1000; i++ {
 		err := mc.Set(fmt.Sprintf("k%d", i), sampleVal, 1, 10)
 		require.NoError(s.T(), err)
diff --git a/pkg/downloader/download_test.go b/pkg/downloader/download_test.go
index 90d44415d3..02f61672ab 100644
--- a/pkg/downloader/download_test.go
+++ b/pkg/downloader/download_test.go
@@ -45,9 +45,10 @@ type DownloaderSuite struct {
 func (ds *DownloaderSuite) SetupSuite() {
 	logger.ConfigureTestLogging(ds.T())
 	_, cfg := setup.SetupBacalhauRepoForTesting(ds.T())
-	if testutils.IsIPFSEnabled(cfg.Node.IPFS.Connect) {
+
+	if testutils.IsIPFSEnabled(cfg.ResultDownloaders.Types.IPFS.Endpoint) {
 		var err error
-		ds.ipfsClient, err = ipfs.NewClient(context.Background(), cfg.Node.IPFS.Connect)
+		ds.ipfsClient, err = ipfs.NewClient(context.Background(), cfg.ResultDownloaders.Types.IPFS.Endpoint)
 		require.NoError(ds.T(), err)
 	}
 	ds.HelperSuite.SetupSuite()
diff --git a/pkg/downloader/ipfs/downloader_test.go b/pkg/downloader/ipfs/downloader_test.go
index 6f76c54edc..1acb853886 100644
--- a/pkg/downloader/ipfs/downloader_test.go
+++ b/pkg/downloader/ipfs/downloader_test.go
@@ -32,9 +32,9 @@ func TestIPFSDownload(t *testing.T) {
 	defer cancel()
 
 	_, cfg := setup.SetupBacalhauRepoForTesting(t)
-	testutils.MustHaveIPFS(t, cfg.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(t, cfg)
 
-	client, err := ipfs.NewClient(context.Background(), cfg.Node.IPFS.Connect)
+	client, err := ipfs.NewClient(context.Background(), cfg.ResultDownloaders.Types.IPFS.Endpoint)
 	require.NoError(t, err)
 
 	text := randomText(t)
diff --git a/pkg/executor/docker/bidstrategy/semantic/image_platform_test.go b/pkg/executor/docker/bidstrategy/semantic/image_platform_test.go
index a3f6e50cb5..8c725bd368 100644
--- a/pkg/executor/docker/bidstrategy/semantic/image_platform_test.go
+++ b/pkg/executor/docker/bidstrategy/semantic/image_platform_test.go
@@ -8,7 +8,8 @@ import (
 
 	"github.com/stretchr/testify/require"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	dockermodels "github.com/bacalhau-project/bacalhau/pkg/executor/docker/models"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/test/mock"
@@ -34,7 +35,13 @@ func TestBidsBasedOnImagePlatform(t *testing.T) {
 	client, err := docker.NewDockerClient()
 	require.NoError(t, err)
 
-	strategy := semantic.NewImagePlatformBidStrategy(client, configenv.Testing.Node.Compute.ManifestCache)
+	strategy := semantic.NewImagePlatformBidStrategy(client,
+		types.DockerManifestCache{
+			Size:    legacy_types.Testing.Node.Compute.ManifestCache.Size,
+			TTL:     types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Duration),
+			Refresh: types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Frequency),
+		},
+	)
 
 	t.Run("positive response for supported architecture", func(t *testing.T) {
 		response, err := strategy.ShouldBid(context.Background(), bidstrategy.BidStrategyRequest{
diff --git a/pkg/executor/docker/executor_test.go b/pkg/executor/docker/executor_test.go
index f3a5273f89..ba2d962101 100644
--- a/pkg/executor/docker/executor_test.go
+++ b/pkg/executor/docker/executor_test.go
@@ -20,7 +20,8 @@ import (
 	"github.com/stretchr/testify/suite"
 
 	"github.com/bacalhau-project/bacalhau/pkg/compute/logstream"
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/docker"
 	"github.com/bacalhau-project/bacalhau/pkg/executor"
 	dockermodels "github.com/bacalhau-project/bacalhau/pkg/executor/docker/models"
@@ -57,7 +58,13 @@ func (s *ExecutorTestSuite) SetupTest() {
 
 	s.executor, err = NewExecutor(
 		"bacalhau-executor-unit-test",
-		configenv.Testing.Node.Compute.ManifestCache,
+		types.Docker{
+			ManifestCache: types.DockerManifestCache{
+				Size:    legacy_types.Testing.Node.Compute.ManifestCache.Size,
+				TTL:     types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Duration),
+				Refresh: types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Frequency),
+			},
+		},
 	)
 	require.NoError(s.T(), err)
 	s.T().Cleanup(func() {
diff --git a/pkg/logger/logger_test.go b/pkg/logger/logger_test.go
index a756f4d2d1..ac25c6536d 100644
--- a/pkg/logger/logger_test.go
+++ b/pkg/logger/logger_test.go
@@ -23,7 +23,7 @@ func TestConfigureLogging(t *testing.T) {
 	})
 
 	var logging strings.Builder
-	configureLogging(zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
+	configureLogging(zerolog.InfoLevel, zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) {
 		defaultLogFormat(w)
 		w.Out = &logging
 		w.NoColor = true
diff --git a/pkg/publicapi/test/util_test.go b/pkg/publicapi/test/util_test.go
deleted file mode 100644
index 824531eb9b..0000000000
--- a/pkg/publicapi/test/util_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package test
-
-import (
-	"context"
-	"path/filepath"
-	"testing"
-
-	"github.com/stretchr/testify/require"
-
-	"github.com/bacalhau-project/bacalhau/pkg/compute/store/boltdb"
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
-	boltjobstore "github.com/bacalhau-project/bacalhau/pkg/jobstore/boltdb"
-
-	"github.com/bacalhau-project/bacalhau/pkg/devstack"
-	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
-	"github.com/bacalhau-project/bacalhau/pkg/node"
-	"github.com/bacalhau-project/bacalhau/pkg/publicapi"
-	"github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
-	"github.com/bacalhau-project/bacalhau/pkg/setup"
-	"github.com/bacalhau-project/bacalhau/pkg/system"
-)
-
-func setupNodeForTest(t *testing.T) (*node.Node, types.BacalhauConfig) {
-	// blank config should result in using defaults in node.Node constructor
-	return setupNodeForTestWithConfig(t, publicapi.Config{})
-}
-
-func setupNodeForTestWithConfig(t *testing.T, apiCfg publicapi.Config) (*node.Node, types.BacalhauConfig) {
-	repo, c := setup.SetupBacalhauRepoForTesting(t)
-	ctx := context.Background()
-
-	repoPath, err := repo.Path()
-	require.NoError(t, err)
-
-	cm := system.NewCleanupManager()
-	t.Cleanup(func() { cm.Cleanup(context.Background()) })
-
-	networkPort, err := network.GetFreePort()
-	require.NoError(t, err)
-
-	networkConfig := node.NetworkConfig{
-		AuthSecret: "test",
-		Port:       networkPort,
-	}
-
-	jobStore, err := boltjobstore.NewBoltJobStore(filepath.Join(repoPath, "jobs.db"))
-	require.NoError(t, err)
-
-	executionStore, err := boltdb.NewStore(ctx, filepath.Join(repoPath, "executions.db"))
-	require.NoError(t, err)
-
-	executionDir, err := c.ExecutionDir()
-	require.NoError(t, err)
-
-	computeConfig, err := node.NewComputeConfigWith(executionDir, node.ComputeConfigParams{
-		ExecutionStore: executionStore,
-	})
-	require.NoError(t, err)
-	requesterConfig, err := node.NewRequesterConfigWith(node.RequesterConfigParams{
-		JobStore: jobStore,
-	})
-	require.NoError(t, err)
-
-	nodeConfig := node.NodeConfig{
-		NodeID:              "node-0",
-		CleanupManager:      cm,
-		HostAddress:         "0.0.0.0",
-		APIPort:             0,
-		ComputeConfig:       computeConfig,
-		RequesterNodeConfig: requesterConfig,
-		APIServerConfig:     apiCfg,
-		IsRequesterNode:     true,
-		IsComputeNode:       true,
-		DependencyInjector:  devstack.NewNoopNodeDependencyInjector(),
-		NetworkConfig:       networkConfig,
-	}
-
-	n, err := node.NewNode(ctx, c, nodeConfig, repo)
-	require.NoError(t, err)
-
-	err = n.Start(ctx)
-	require.NoError(t, err)
-
-	apiClient := client.New(n.APIServer.GetURI().String())
-	require.NoError(t, WaitForNodes(ctx, apiClient))
-	return n, c
-}
diff --git a/pkg/publisher/local/publisher_test.go b/pkg/publisher/local/publisher_test.go
index 8067157360..f2946e1a47 100644
--- a/pkg/publisher/local/publisher_test.go
+++ b/pkg/publisher/local/publisher_test.go
@@ -32,7 +32,9 @@ func TestPublisherTestSuite(t *testing.T) {
 func (s *PublisherTestSuite) SetupTest() {
 	s.ctx = context.Background()
 	s.baseDir = s.T().TempDir()
-	s.pub = local.NewLocalPublisher(s.ctx, s.baseDir, defaultHost, defaultPort)
+	var err error
+	s.pub, err = local.NewLocalPublisher(s.ctx, s.baseDir, defaultHost, defaultPort)
+	s.Require().NoError(err)
 }
 
 func (s *PublisherTestSuite) TestAddressResolving() {
diff --git a/pkg/repo/fs_test.go b/pkg/repo/fs_test.go
index 01f842b05f..b7d61a9421 100644
--- a/pkg/repo/fs_test.go
+++ b/pkg/repo/fs_test.go
@@ -8,12 +8,17 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 )
 
 func TestNewFS(t *testing.T) {
 	c, err := config.New()
+	repoPath := t.TempDir() + t.Name()
+	var bacCfg types.Bacalhau
+	require.NoError(t, c.Unmarshal(&bacCfg))
+	bacCfg.DataDir = repoPath
 	require.NoError(t, err)
-	repo, err := NewFS(FsRepoParams{Path: t.TempDir() + t.Name()})
+	repo, err := NewFS(FsRepoParams{Path: repoPath})
 	require.NoError(t, err)
 	require.NotNil(t, repo)
 
@@ -23,13 +28,13 @@ func TestNewFS(t *testing.T) {
 	require.False(t, exists)
 
 	// cannot open uninitialized repo
-	err = repo.Open(c)
+	err = repo.Open()
 	require.Error(t, err)
 
 	// can init a repo
 	// TODO(forrest) [refactor]: assert the repo initializes the expected values
 	// in the config, such as paths and keys.
-	err = repo.Init(c)
+	err = repo.Init(bacCfg)
 	require.NoError(t, err)
 
 	// it better exist now
@@ -38,10 +43,10 @@ func TestNewFS(t *testing.T) {
 	require.True(t, exists)
 
 	// should be able to open
-	err = repo.Open(c)
+	err = repo.Open()
 	require.NoError(t, err)
 
 	// cannot init an already init'ed repo.
-	err = repo.Init(c)
+	err = repo.Init(bacCfg)
 	require.Error(t, err)
 }
diff --git a/pkg/repo/migrations/v2_3_test.go b/pkg/repo/migrations/v2_3_test.go
index 0e4f2db7d0..4f43c07035 100644
--- a/pkg/repo/migrations/v2_3_test.go
+++ b/pkg/repo/migrations/v2_3_test.go
@@ -8,7 +8,7 @@ import (
 
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 )
 
@@ -45,9 +45,7 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWithDefaultRepo() {
 	suite.verifyInitialState(libp2pPeerID)
 
 	// open the repo to trigger the migration
-	c, err := config.New()
-	suite.Require().NoError(err)
-	suite.Require().NoError(suite.repo.Open(c))
+	suite.Require().NoError(suite.repo.Open())
 
 	repoVersion, err := suite.repo.Version()
 	suite.Require().NoError(err)
@@ -56,8 +54,8 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWithDefaultRepo() {
 	// verify configs where updated as expected
 	_, cfg, err := readConfig(*suite.repo)
 	suite.Require().NoError(err)
-	suite.Equal(filepath.Join(suite.TempDir, config.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
-	suite.Equal(filepath.Join(suite.TempDir, config.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
 	suite.Equal(libp2pPeerID, cfg.Node.Name)
 
 	// verify the old directories were renamed
@@ -78,9 +76,7 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWitCustomConfig() {
 	suite.verifyInitialState(libp2pPeerID)
 
 	// open the repo to trigger the migration
-	c, err := config.New()
-	suite.Require().NoError(err)
-	suite.Require().NoError(suite.repo.Open(c))
+	suite.Require().NoError(suite.repo.Open())
 
 	// verify the repo version was updated
 	repoVersion, err := suite.repo.Version()
@@ -90,8 +86,8 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWitCustomConfig() {
 	// verify configs where updated as expected, and that network port was not changed
 	_, cfg, err := readConfig(*suite.repo)
 	suite.Require().NoError(err)
-	suite.Equal(filepath.Join(suite.TempDir, config.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
-	suite.Equal(filepath.Join(suite.TempDir, config.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
 	suite.Equal(libp2pPeerID, cfg.Node.Name)
 	suite.Equal(123456789, cfg.Node.Network.Port)
 
@@ -113,9 +109,7 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWitCustomStores() {
 	suite.verifyInitialState(libp2pPeerID)
 
 	// open the repo to trigger the migration
-	c, err := config.New()
-	suite.Require().NoError(err)
-	suite.Require().NoError(suite.repo.Open(c))
+	suite.Require().NoError(suite.repo.Open())
 
 	// verify the repo version was updated
 	repoVersion, err := suite.repo.Version()
@@ -147,9 +141,7 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWithEmptyStorePaths() {
 	suite.verifyInitialState(libp2pPeerID)
 
 	// open the repo to trigger the migration
-	c, err := config.New()
-	suite.Require().NoError(err)
-	suite.Require().NoError(suite.repo.Open(c))
+	suite.Require().NoError(suite.repo.Open())
 
 	repoVersion, err := suite.repo.Version()
 	suite.Require().NoError(err)
@@ -158,8 +150,8 @@ func (suite *V2MigrationsTestSuite) TestV2MigrationWithEmptyStorePaths() {
 	// verify configs where updated as expected
 	_, cfg, err := readConfig(*suite.repo)
 	suite.Require().NoError(err)
-	suite.Equal(filepath.Join(suite.TempDir, config.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
-	suite.Equal(filepath.Join(suite.TempDir, config.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.ComputeExecutionsStorePath), cfg.Node.Compute.ExecutionStore.Path)
+	suite.Equal(filepath.Join(suite.TempDir, config_legacy.OrchestratorJobStorePath), cfg.Node.Requester.JobStore.Path)
 	suite.Equal(libp2pPeerID, cfg.Node.Name)
 
 	// verify the old directories were renamed
diff --git a/pkg/repo/migrations/v3_4_test.go b/pkg/repo/migrations/v3_4_test.go
index 87a529702e..51acd1a09d 100644
--- a/pkg/repo/migrations/v3_4_test.go
+++ b/pkg/repo/migrations/v3_4_test.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"runtime"
 	"testing"
 	"time"
 
@@ -13,6 +14,7 @@ import (
 
 	"github.com/bacalhau-project/bacalhau/pkg/config"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	"github.com/bacalhau-project/bacalhau/pkg/config_legacy"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 )
 
@@ -39,6 +41,16 @@ func TestV3MigrationsTestSuite(t *testing.T) {
 }
 
 func (suite *V3MigrationsTestSuite) TestV3MigrationWithDefaultRepo() {
+	switch runtime.GOOS {
+	case "windows":
+		suite.T().Setenv("AppData", suite.TempDir)
+	case "darwin", "ios":
+		suite.T().Setenv("HOME", suite.TempDir)
+	case "plan9":
+		suite.T().Setenv("home", suite.TempDir)
+	default: // Unix
+		suite.T().Setenv("XDG_CONFIG_HOME", suite.TempDir)
+	}
 	// Copy test data to the suite's temporary directory
 	testDataPath := filepath.Join("testdata", "v3_defaults")
 	suite.copyRepo(testDataPath)
@@ -55,7 +67,7 @@ func (suite *V3MigrationsTestSuite) TestV3MigrationWithDefaultRepo() {
 	suite.FileExists(filepath.Join(suite.TempDir, "repo.version"))
 	suite.FileExists(filepath.Join(suite.TempDir, "update.json"))
 	suite.FileExists(filepath.Join(suite.TempDir, "user_id.pem"))
-	configPath := filepath.Join(suite.TempDir, config.FileName)
+	configPath := filepath.Join(suite.TempDir, config.DefaultFileName)
 
 	// define a config in the repo we are migrating with the correct paths defined in it
 	// based on the old directory structure.
@@ -68,6 +80,10 @@ func (suite *V3MigrationsTestSuite) TestV3MigrationWithDefaultRepo() {
 	defer f.Close()
 	_, err = createConfig(configPath, fmt.Sprintf(`
 Node:
+    ClientAPI:
+# these are values that will be migrated to the new config API.Address field
+        Host: 1.2.3.4
+        Port: 9999
     Compute:
         ExecutionStore:
             Type: BoltDB
@@ -91,17 +107,24 @@ Auth:
 	suite.Equal(repo.Version3, repoVersion3)
 
 	// open the repo to trigger the migration to version 4
-	cfg, err := config.New()
 	suite.Require().NoError(err)
-	suite.Require().NoError(suite.repo.Open(cfg))
+	suite.Require().NoError(suite.repo.Open())
 
 	// verify the repo's new current version is 4
 	repoVersion4, err := suite.repo.Version()
 	suite.Require().NoError(err)
 	suite.Equal(repo.Version4, repoVersion4)
 
-	// verify the config file remains present
-	suite.FileExists(filepath.Join(suite.TempDir, config.FileName))
+	// verify the config file has been moved to XDG_CONFIG_HOME/bacalhau/config.yaml
+	// and that it contains the values from the the original config that have been migrated
+	newConfigPath := filepath.Join(suite.TempDir, "bacalhau", config_legacy.FileName)
+	suite.FileExists(newConfigPath)
+	c, err := config.New(config.WithPaths(newConfigPath))
+	suite.Require().NoError(err)
+	var bacCfg types.Bacalhau
+	suite.Require().NoError(c.Unmarshal(&bacCfg))
+	suite.Require().Equal("1.2.3.4", bacCfg.API.Host)
+	suite.Require().Equal(9999, bacCfg.API.Port)
 
 	// verify database files are present
 	suite.FileExists(filepath.Join(suite.TempDir, types.OrchestratorDirName, types.JobStoreFileName))
@@ -133,6 +156,11 @@ Auth:
 	actualLastUpdateCheck, err := suite.repo.ReadLastUpdateCheck()
 	suite.Require().NoError(err)
 	suite.Require().Equal(time.UnixMilli(0).UTC(), actualLastUpdateCheck.UTC())
+
+	// the node name was migrated from the old config to system_metadata.yaml
+	actualNodeName, err := suite.repo.ReadNodeName()
+	suite.Require().NoError(err)
+	suite.Require().Equal("n-321fd9bf-3a7c-45f5-9b6b-fb9725ac646d", actualNodeName)
 }
 
 // createConfig creates a config file with the given content
diff --git a/pkg/s3/test/suite.go b/pkg/s3/test/suite.go
index cd6ba26f39..7ec82381c3 100644
--- a/pkg/s3/test/suite.go
+++ b/pkg/s3/test/suite.go
@@ -18,7 +18,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	s3publisher "github.com/bacalhau-project/bacalhau/pkg/publisher/s3"
@@ -81,7 +81,7 @@ func NewTestHelper(t *testing.T, params HelperSuiteParams) *HelperSuite {
 		ClientProvider: clientProvider,
 	})
 
-	storage := s3storage.NewStorage(time.Duration(configenv.Testing.Node.VolumeSizeRequestTimeout), clientProvider)
+	storage := s3storage.NewStorage(time.Duration(legacy_types.Testing.Node.VolumeSizeRequestTimeout), clientProvider)
 
 	return &HelperSuite{
 		Bucket:         params.Bucket,
diff --git a/pkg/storage/ipfs/storage_test.go b/pkg/storage/ipfs/storage_test.go
index 483b777c2f..707acf35e2 100644
--- a/pkg/storage/ipfs/storage_test.go
+++ b/pkg/storage/ipfs/storage_test.go
@@ -33,11 +33,11 @@ func TestStorageSuite(t *testing.T) {
 func (s *StorageSuite) SetupSuite() {
 	logger.ConfigureTestLogging(s.T())
 	_, cfg := setup.SetupBacalhauRepoForTesting(s.T())
-	testutils.MustHaveIPFS(s.T(), cfg.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(s.T(), cfg)
 
 	var err error
-	s.ipfsClient, err = ipfs.NewClient(context.Background(), cfg.Node.IPFS.Connect)
-	s.storage, err = NewStorage(*s.ipfsClient, time.Duration(cfg.Node.VolumeSizeRequestTimeout))
+	s.ipfsClient, err = ipfs.NewClient(context.Background(), cfg.ResultDownloaders.Types.IPFS.Endpoint)
+	s.storage, err = NewStorage(*s.ipfsClient, 5*time.Second)
 	s.Require().NoError(err)
 }
 
diff --git a/pkg/storage/parallel_test.go b/pkg/storage/parallel_test.go
index 6f56cf4afb..1ab01cdb71 100644
--- a/pkg/storage/parallel_test.go
+++ b/pkg/storage/parallel_test.go
@@ -8,12 +8,10 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"testing"
-	"time"
 
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
 	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	executor_util "github.com/bacalhau-project/bacalhau/pkg/executor/util"
 	"github.com/bacalhau-project/bacalhau/pkg/ipfs"
@@ -27,7 +25,7 @@ import (
 
 type ParallelStorageSuite struct {
 	suite.Suite
-	cfg      types.BacalhauConfig
+	cfg      types.Bacalhau
 	provider provider.Provider[storage.Storage]
 }
 
@@ -40,20 +38,15 @@ func (s *ParallelStorageSuite) SetupSuite() {
 	s.cfg = cfg
 
 	var err error
-	s.provider, err = executor_util.NewStandardStorageProvider(
-		time.Duration(configenv.Testing.Node.VolumeSizeRequestTimeout),
-		time.Duration(configenv.Testing.Node.DownloadURLRequestTimeout),
-		configenv.Testing.Node.DownloadURLRequestRetries,
-		executor_util.StandardStorageProviderOptions{IPFSConnect: cfg.Node.IPFS.Connect},
-	)
+	s.provider, err = executor_util.NewStandardStorageProvider(cfg)
 	s.Require().NoError(err)
 }
 
 func (s *ParallelStorageSuite) TestIPFSCleanup() {
-	testutils.MustHaveIPFS(s.T(), s.cfg.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(s.T(), s.cfg)
 
 	ctx := context.Background()
-	client, err := ipfs.NewClient(ctx, s.cfg.Node.IPFS.Connect)
+	client, err := ipfs.NewClient(ctx, s.cfg.InputSources.Types.IPFS.Endpoint)
 	require.NoError(s.T(), err)
 
 	cid, err := client.Put(ctx, "../../testdata/grep_file.txt")
diff --git a/pkg/storage/url/urldownload/storage_test.go b/pkg/storage/url/urldownload/storage_test.go
index 017c648557..c07329a20e 100644
--- a/pkg/storage/url/urldownload/storage_test.go
+++ b/pkg/storage/url/urldownload/storage_test.go
@@ -15,7 +15,7 @@ import (
 	"github.com/spf13/cobra"
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 )
@@ -39,8 +39,8 @@ func (s *StorageSuite) SetupTest() {
 
 func (s *StorageSuite) TestHasStorageLocally() {
 	sp := NewStorage(
-		time.Duration(configenv.Testing.Node.DownloadURLRequestTimeout),
-		configenv.Testing.Node.DownloadURLRequestRetries,
+		time.Duration(legacy_types.Testing.Node.DownloadURLRequestTimeout),
+		legacy_types.Testing.Node.DownloadURLRequestRetries,
 	)
 
 	spec := models.InputSource{
@@ -305,8 +305,8 @@ func (s *StorageSuite) TestPrepareStorageURL() {
 			s.T().Cleanup(ts.Close)
 
 			subject := NewStorage(
-				time.Duration(configenv.Testing.Node.DownloadURLRequestTimeout),
-				configenv.Testing.Node.DownloadURLRequestRetries,
+				time.Duration(legacy_types.Testing.Node.DownloadURLRequestTimeout),
+				legacy_types.Testing.Node.DownloadURLRequestRetries,
 			)
 
 			url := fmt.Sprintf("%s%s", ts.URL, test.requests[0].path)
@@ -371,8 +371,8 @@ func (s *StorageSuite) TestGetVolumeSize_WithServerReturningValidSize() {
 	s.T().Cleanup(ts.Close)
 
 	subject := NewStorage(
-		time.Duration(configenv.Testing.Node.DownloadURLRequestTimeout),
-		configenv.Testing.Node.DownloadURLRequestRetries,
+		time.Duration(legacy_types.Testing.Node.DownloadURLRequestTimeout),
+		legacy_types.Testing.Node.DownloadURLRequestRetries,
 	)
 
 	url := fmt.Sprintf("%s%s", ts.URL, path)
@@ -412,8 +412,8 @@ func (s *StorageSuite) TestGetVolumeSize_WithServerReturningInvalidSize() {
 	s.T().Cleanup(ts.Close)
 
 	subject := NewStorage(
-		time.Duration(configenv.Testing.Node.DownloadURLRequestTimeout),
-		configenv.Testing.Node.DownloadURLRequestRetries,
+		time.Duration(legacy_types.Testing.Node.DownloadURLRequestTimeout),
+		legacy_types.Testing.Node.DownloadURLRequestRetries,
 	)
 
 	url := fmt.Sprintf("%s%s", ts.URL, path)
diff --git a/pkg/test/compute/resourcelimits_test.go b/pkg/test/compute/resourcelimits_test.go
index d49526b8e8..17813ce2ac 100644
--- a/pkg/test/compute/resourcelimits_test.go
+++ b/pkg/test/compute/resourcelimits_test.go
@@ -15,7 +15,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/devstack"
 	noop_executor "github.com/bacalhau-project/bacalhau/pkg/executor/noop"
 	"github.com/bacalhau-project/bacalhau/pkg/logger"
@@ -142,7 +142,7 @@ func (suite *ComputeNodeResourceLimitsSuite) TestTotalResourceLimits() {
 					JobHandler:    jobHandler,
 					GetVolumeSize: getVolumeSizeHandler,
 				},
-			}, c.Node.Compute.ManifestCache),
+			}, c.Engines),
 		)
 
 		for _, jobResources := range testCase.jobs {
@@ -315,8 +315,8 @@ func (suite *ComputeNodeResourceLimitsSuite) TestParallelGPU() {
 			GPUs:   make([]models.GPU, 1),
 		},
 		IgnorePhysicalResourceLimits: true, // we need to pretend that we have GPUs on each node
-		ControlPlaneSettings: types.ComputeControlPlaneConfig{
-			ResourceUpdateFrequency: types.Duration(50 * time.Millisecond),
+		ControlPlaneSettings: legacy_types.ComputeControlPlaneConfig{
+			ResourceUpdateFrequency: legacy_types.Duration(50 * time.Millisecond),
 		},
 	})
 	suite.Require().NoError(err)
@@ -336,7 +336,7 @@ func (suite *ComputeNodeResourceLimitsSuite) TestParallelGPU() {
 				ExternalHooks: noop_executor.ExecutorConfigExternalHooks{
 					JobHandler: jobHandler,
 				},
-			}, c.Node.Compute.ManifestCache),
+			}, c.Engines),
 	)
 
 	// for the requester node to pick up the nodeInfo messages
diff --git a/pkg/test/compute/setup_test.go b/pkg/test/compute/setup_test.go
index efeb179b18..c38d08bab7 100644
--- a/pkg/test/compute/setup_test.go
+++ b/pkg/test/compute/setup_test.go
@@ -15,7 +15,8 @@ import (
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store/boltdb"
 	"github.com/bacalhau-project/bacalhau/pkg/compute/store/resolver"
 	"github.com/bacalhau-project/bacalhau/pkg/config"
-	"github.com/bacalhau-project/bacalhau/pkg/config/configenv"
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	executor_common "github.com/bacalhau-project/bacalhau/pkg/executor"
 	dockerexecutor "github.com/bacalhau-project/bacalhau/pkg/executor/docker"
 	noop_executor "github.com/bacalhau-project/bacalhau/pkg/executor/noop"
@@ -77,7 +78,15 @@ func (s *ComputeSuite) setupNode() {
 	s.completedChannel = make(chan compute.RunResult)
 	s.failureChannel = make(chan compute.ComputeError)
 
-	dockerExecutor, err := dockerexecutor.NewExecutor(nodeID, configenv.Testing.Node.Compute.ManifestCache)
+	dockerExecutor, err := dockerexecutor.NewExecutor(nodeID,
+		types.Docker{
+			ManifestCache: types.DockerManifestCache{
+				Size:    legacy_types.Testing.Node.Compute.ManifestCache.Size,
+				TTL:     types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Duration),
+				Refresh: types.Duration(legacy_types.Testing.Node.Compute.ManifestCache.Frequency),
+			},
+		},
+	)
 	s.Require().NoError(err)
 
 	apiServer, err := publicapi.NewAPIServer(publicapi.ServerParams{
@@ -119,9 +128,10 @@ func (s *ComputeSuite) setupNode() {
 	c, err := config.New()
 	s.Require().NoError(err)
 
-	err = r.Init(c)
-	s.Require().NoError(err)
-	cfg, err := c.Current()
+	var cfg types.Bacalhau
+	s.Require().NoError(c.Unmarshal(&cfg))
+
+	err = r.Init(cfg)
 	s.Require().NoError(err)
 
 	// create the compute node
diff --git a/pkg/test/devstack/default_publisher_test.go b/pkg/test/devstack/default_publisher_test.go
index d8662debdd..2e801f365a 100644
--- a/pkg/test/devstack/default_publisher_test.go
+++ b/pkg/test/devstack/default_publisher_test.go
@@ -10,6 +10,7 @@ import (
 	wasmmodels "github.com/bacalhau-project/bacalhau/pkg/executor/wasm/models"
 	_ "github.com/bacalhau-project/bacalhau/pkg/logger"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
+	"github.com/bacalhau-project/bacalhau/pkg/publisher/local"
 	"github.com/bacalhau-project/bacalhau/pkg/test/scenario"
 	"github.com/bacalhau-project/bacalhau/testdata/wasm/cat"
 
@@ -25,6 +26,11 @@ func TestDefaultPublisherSuite(t *testing.T) {
 }
 
 func (s *DefaultPublisherSuite) TestNoDefaultPublisher() {
+	s.Config.JobDefaults.Batch.Task.Publisher.Config.Type = ""
+	s.Config.JobDefaults.Batch.Task.Publisher.Config.Params = make(map[string]interface{})
+	stack := &scenario.StackConfig{}
+	stack.RequesterConfig.JobDefaults.Batch.Task.Publisher.Config.Type = ""
+	stack.RequesterConfig.JobDefaults.Batch.Task.Publisher.Config.Params = make(map[string]interface{})
 	testcase := scenario.Scenario{
 		Job: &models.Job{
 			Name:  s.T().Name(),
@@ -43,6 +49,7 @@ func (s *DefaultPublisherSuite) TestNoDefaultPublisher() {
 				},
 			},
 		},
+		Stack:          stack,
 		ResultsChecker: expectResultsNone,
 		JobCheckers: []scenario.StateChecks{
 			scenario.WaitForSuccessfulCompletion(),
@@ -53,9 +60,8 @@ func (s *DefaultPublisherSuite) TestNoDefaultPublisher() {
 }
 
 func (s *DefaultPublisherSuite) TestDefaultPublisher() {
-	stack := scenario.StackConfig{}
-	stack.DefaultPublisher = "local"
-
+	stack := &scenario.StackConfig{}
+	stack.JobDefaults.Batch.Task.Publisher.Config = *local.NewSpecConfig()
 	testcase := scenario.Scenario{
 		Job: &models.Job{
 			Name:  s.T().Name(),
@@ -74,7 +80,7 @@ func (s *DefaultPublisherSuite) TestDefaultPublisher() {
 				},
 			},
 		},
-		Stack:          &stack,
+		Stack:          stack,
 		ResultsChecker: expectResultsSome,
 		JobCheckers: []scenario.StateChecks{
 			scenario.WaitForSuccessfulCompletion(),
diff --git a/pkg/test/devstack/jobselection_test.go b/pkg/test/devstack/jobselection_test.go
index b9a686fead..3aed2b53ee 100644
--- a/pkg/test/devstack/jobselection_test.go
+++ b/pkg/test/devstack/jobselection_test.go
@@ -33,6 +33,7 @@ func TestDevstackJobSelectionSuite(t *testing.T) {
 
 // Reuse the docker executor tests but full end to end with transport layer and 3 nodes
 func (suite *DevstackJobSelectionSuite) TestSelectAllJobs() {
+	suite.T().Skip("Test makes assertions on data locality, a feature no longer supported.")
 	type TestCase struct {
 		name      string
 		policy    node.JobSelectionPolicy
diff --git a/pkg/test/devstack/oversubscription_test.go b/pkg/test/devstack/oversubscription_test.go
index 9fe4bbbb8a..f0748c1fc6 100644
--- a/pkg/test/devstack/oversubscription_test.go
+++ b/pkg/test/devstack/oversubscription_test.go
@@ -9,7 +9,7 @@ import (
 
 	"github.com/stretchr/testify/suite"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
+	legacy_types "github.com/bacalhau-project/bacalhau/pkg/config_legacy/types"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
 	clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
@@ -70,8 +70,8 @@ func (s *OverSubscriptionTestSuite) setupStack(overSubscriptionFactor float64) {
 		IgnorePhysicalResourceLimits: true,
 		TotalResourceLimits:          *nodeCapacity,
 		DefaultJobResourceLimits:     *nodeCapacity,
-		ControlPlaneSettings: types.ComputeControlPlaneConfig{
-			ResourceUpdateFrequency: types.Duration(s.resourceUpdateFrequency),
+		ControlPlaneSettings: legacy_types.ComputeControlPlaneConfig{
+			ResourceUpdateFrequency: legacy_types.Duration(s.resourceUpdateFrequency),
 		},
 	})
 	s.Require().NoError(err)
@@ -86,7 +86,7 @@ func (s *OverSubscriptionTestSuite) setupStack(overSubscriptionFactor float64) {
 				ExternalHooks: noop_executor.ExecutorConfigExternalHooks{
 					JobHandler: noop_executor.DelayedJobHandler(s.jobRunDuration),
 				},
-			}, c.Node.Compute.ManifestCache),
+			}, c.Engines),
 	)
 
 	s.requester = stack.Nodes[0]
diff --git a/pkg/test/devstack/submit_test.go b/pkg/test/devstack/submit_test.go
index 70adf0239a..40a19ec638 100644
--- a/pkg/test/devstack/submit_test.go
+++ b/pkg/test/devstack/submit_test.go
@@ -25,7 +25,7 @@ import (
 type DevstackSubmitSuite struct {
 	suite.Suite
 	Repo   *repo.FsRepo
-	Config types.BacalhauConfig
+	Config types.Bacalhau
 }
 
 // In order for 'go test' to run this suite, we need to create
diff --git a/pkg/test/devstack/timeout_test.go b/pkg/test/devstack/timeout_test.go
index ca8221f7bd..42774d8c87 100644
--- a/pkg/test/devstack/timeout_test.go
+++ b/pkg/test/devstack/timeout_test.go
@@ -10,14 +10,12 @@ import (
 
 	"github.com/stretchr/testify/suite"
 
-	baccrypto "github.com/bacalhau-project/bacalhau/pkg/lib/crypto"
-	"github.com/bacalhau-project/bacalhau/pkg/models"
-	"github.com/bacalhau-project/bacalhau/pkg/orchestrator/transformer"
-
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/devstack"
 	"github.com/bacalhau-project/bacalhau/pkg/executor"
 	"github.com/bacalhau-project/bacalhau/pkg/executor/noop"
 	_ "github.com/bacalhau-project/bacalhau/pkg/logger"
+	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/node"
 	"github.com/bacalhau-project/bacalhau/pkg/system"
 	"github.com/bacalhau-project/bacalhau/pkg/test/scenario"
@@ -50,16 +48,19 @@ func (suite *DevstackTimeoutSuite) TestRunningTimeout() {
 
 	runTest := func(testCase TestCase) {
 		computeConfig, err := node.NewComputeConfigWith(suite.T().TempDir(), node.ComputeConfigParams{
-			JobNegotiationTimeout:                 testCase.computeJobNegotiationTimeout,
-			MinJobExecutionTimeout:                testCase.computeMinJobExecutionTimeout,
-			MaxJobExecutionTimeout:                testCase.computeMaxJobExecutionTimeout,
-			JobExecutionTimeoutClientIDBypassList: testCase.computeJobExecutionBypassList,
+			JobNegotiationTimeout:  testCase.computeJobNegotiationTimeout,
+			MinJobExecutionTimeout: testCase.computeMinJobExecutionTimeout,
+			MaxJobExecutionTimeout: testCase.computeMaxJobExecutionTimeout,
 		})
 		suite.Require().NoError(err)
 
 		requesterConfig, err := node.NewRequesterConfigWith(node.RequesterConfigParams{
-			JobDefaults: transformer.JobDefaults{
-				TotalTimeout: testCase.requesterDefaultJobExecutionTimeout,
+			JobDefaults: types.JobDefaults{
+				Batch: types.BatchJobDefaultsConfig{
+					Task: types.BatchTaskDefaultConfig{
+						Timeouts: types.TaskTimeoutConfig{TotalTimeout: types.Duration(testCase.requesterDefaultJobExecutionTimeout)},
+					},
+				},
 			},
 			HousekeepingBackgroundTaskInterval: 100 * time.Millisecond,
 			// we want compute nodes to fail first instead or requesters to cancel
@@ -122,10 +123,6 @@ func (suite *DevstackTimeoutSuite) TestRunningTimeout() {
 		suite.RunScenario(testScenario)
 	}
 
-	userKeyPath, err := suite.Config.UserKeyPath()
-	suite.Require().NoError(err)
-	userKey, err := baccrypto.LoadUserKey(userKeyPath)
-	suite.Require().NoError(err)
 	for _, testCase := range []TestCase{
 		{
 			name:                                "sleep_within_default_timeout",
@@ -223,19 +220,6 @@ func (suite *DevstackTimeoutSuite) TestRunningTimeout() {
 			jobTimeout:                          2 * time.Minute,
 			rejectedCount:                       1,
 		},
-		{
-			name:                                "job_timeout_greater_than_max_but_on_allowed_list",
-			computeJobExecutionBypassList:       []string{userKey.ClientID()},
-			computeJobNegotiationTimeout:        10 * time.Second,
-			computeMinJobExecutionTimeout:       1 * time.Nanosecond,
-			computeMaxJobExecutionTimeout:       1 * time.Minute,
-			requesterDefaultJobExecutionTimeout: 40 * time.Second,
-			nodeCount:                           1,
-			concurrency:                         1,
-			sleepTime:                           1 * time.Second,
-			jobTimeout:                          2 * time.Minute,
-			completedCount:                      1,
-		},
 	} {
 		suite.Run(testCase.name, func() {
 			runTest(testCase)
diff --git a/pkg/test/devstack/url_test.go b/pkg/test/devstack/url_test.go
index 0b6c8aaf17..75b5963fcf 100644
--- a/pkg/test/devstack/url_test.go
+++ b/pkg/test/devstack/url_test.go
@@ -44,7 +44,6 @@ type URLBasedTestCase struct {
 
 func runURLTest(
 	suite *URLTestSuite,
-	cfg types.BacalhauConfig,
 	handler func(w http.ResponseWriter, r *http.Request),
 	testCase URLBasedTestCase,
 ) {
@@ -124,7 +123,7 @@ func (s *URLTestSuite) TestMultipleURLs() {
 			w.Write([]byte(content))
 		}
 	}
-	runURLTest(s, s.Config, handler, testCase)
+	runURLTest(s, handler, testCase)
 }
 
 // both starts should be before both ends if we are downloading in parallel
@@ -159,7 +158,7 @@ func (s *URLTestSuite) TestURLsInParallel() {
 		}
 
 	}
-	runURLTest(s, s.Config, handler, testCase)
+	runURLTest(s, handler, testCase)
 
 	start1, ok := accessTimes["/"+getAccessKey(testCase.file1, "start")]
 	require.True(s.T(), ok)
@@ -192,7 +191,7 @@ func (s *URLTestSuite) TestFlakyURLs() {
 
 	handler := func(w http.ResponseWriter, r *http.Request) {
 		accessCounts := increaseCounter(r.URL.Path)
-		if accessCounts < 3 {
+		if accessCounts < types.Default.InputSources.MaxRetryCount {
 			w.WriteHeader(http.StatusUnauthorized)
 			w.Write([]byte("not found"))
 			return
@@ -207,7 +206,7 @@ func (s *URLTestSuite) TestFlakyURLs() {
 		}
 
 	}
-	runURLTest(s, s.Config, handler, testCase)
+	runURLTest(s, handler, testCase)
 }
 
 func (s *URLTestSuite) TestLocalURLCombo() {
diff --git a/pkg/test/ipfs/ipfs_host_storage_test.go b/pkg/test/ipfs/ipfs_host_storage_test.go
index ce77ee9dc1..7ac8401726 100644
--- a/pkg/test/ipfs/ipfs_host_storage_test.go
+++ b/pkg/test/ipfs/ipfs_host_storage_test.go
@@ -25,7 +25,7 @@ import (
 type IPFSHostStorageSuite struct {
 	suite.Suite
 	client *ipfs.Client
-	Config types.BacalhauConfig
+	Config types.Bacalhau
 }
 
 // In order for 'go test' to run this suite, we need to create
@@ -38,10 +38,10 @@ func TestIPFSHostStorageSuite(t *testing.T) {
 func (suite *IPFSHostStorageSuite) SetupTest() {
 	logger.ConfigureTestLogging(suite.T())
 	_, suite.Config = setup.SetupBacalhauRepoForTesting(suite.T())
-	testutils.MustHaveIPFS(suite.T(), suite.Config.Node.IPFS.Connect)
+	testutils.MustHaveIPFS(suite.T(), suite.Config)
 
 	var err error
-	suite.client, err = ipfs.NewClient(context.Background(), suite.Config.Node.IPFS.Connect)
+	suite.client, err = ipfs.NewClient(context.Background(), suite.Config.InputSources.Types.IPFS.Endpoint)
 	suite.Require().NoError(err)
 
 }
@@ -54,7 +54,7 @@ func (suite *IPFSHostStorageSuite) TestIpfsApiCopyFile() {
 		func(ctx context.Context, api ipfs.Client) (
 			storage.Storage, error) {
 
-			return ipfs_storage.NewStorage(api, time.Duration(suite.Config.Node.VolumeSizeRequestTimeout))
+			return ipfs_storage.NewStorage(api, 3*time.Second)
 		},
 	)
 }
@@ -64,7 +64,7 @@ func (suite *IPFSHostStorageSuite) TestIPFSAPICopyFolder() {
 		func(ctx context.Context, api ipfs.Client) (
 			storage.Storage, error) {
 
-			return ipfs_storage.NewStorage(api, time.Duration(suite.Config.Node.VolumeSizeRequestTimeout))
+			return ipfs_storage.NewStorage(api, 3*time.Second)
 		},
 	)
 }
diff --git a/pkg/test/requester/node_selection_test.go b/pkg/test/requester/node_selection_test.go
index a5b4c2de8d..c0212271f3 100644
--- a/pkg/test/requester/node_selection_test.go
+++ b/pkg/test/requester/node_selection_test.go
@@ -71,7 +71,7 @@ func (s *NodeSelectionSuite) SetupSuite() {
 		devstack.WithNumberOfComputeOnlyNodes(3),
 		devstack.WithNodeOverrides(nodeOverrides...),
 		devstack.WithRequesterConfig(requesterConfig),
-		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Node.Compute.ManifestCache),
+		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Engines),
 	)
 
 	s.requester = stack.Nodes[0]
diff --git a/pkg/test/requester/retries_test.go b/pkg/test/requester/retries_test.go
index 47703abb24..4d32ded5a3 100644
--- a/pkg/test/requester/retries_test.go
+++ b/pkg/test/requester/retries_test.go
@@ -141,7 +141,7 @@ func (s *RetriesSuite) SetupSuite() {
 		devstack.WithNumberOfComputeOnlyNodes(len(nodeOverrides)-1),
 		devstack.WithNodeOverrides(nodeOverrides...),
 		devstack.WithRequesterConfig(requesterConfig),
-		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Node.Compute.ManifestCache),
+		teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}, cfg.Engines),
 	)
 
 	s.requester = stack.Nodes[0]
diff --git a/pkg/test/scenario/suite.go b/pkg/test/scenario/suite.go
index 1789166581..b6704cfd41 100644
--- a/pkg/test/scenario/suite.go
+++ b/pkg/test/scenario/suite.go
@@ -7,12 +7,12 @@ import (
 
 	"github.com/stretchr/testify/suite"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/downloader/http"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
 	clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
 	"github.com/bacalhau-project/bacalhau/pkg/repo"
 
-	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/provider"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/setup"
@@ -46,7 +46,7 @@ type ScenarioTestSuite interface {
 type ScenarioRunner struct {
 	suite.Suite
 	Ctx    context.Context
-	Config types.BacalhauConfig
+	Config types.Bacalhau
 	Repo   *repo.FsRepo
 }
 
@@ -77,8 +77,6 @@ func (s *ScenarioRunner) setupStack(config *StackConfig) (*devstack.DevStack, *s
 		config = &StackConfig{}
 	}
 
-	defaultPublisher := config.RequesterConfig.DefaultPublisher
-
 	if config.DevStackOptions == nil {
 		config.DevStackOptions = &devstack.DevStackOptions{}
 	}
@@ -87,16 +85,19 @@ func (s *ScenarioRunner) setupStack(config *StackConfig) (*devstack.DevStack, *s
 		config.DevStackOptions.NumberOfHybridNodes = 1
 	}
 
-	if config.RequesterConfig.JobDefaults.TotalTimeout == 0 {
+	if config.RequesterConfig.JobDefaults.Batch.Task.Timeouts.TotalTimeout == 0 {
 		cfg, err := node.NewRequesterConfigWithDefaults()
 		s.Require().NoError(err)
 
+		if !config.RequesterConfig.JobDefaults.Batch.Task.Publisher.Config.IsEmpty() {
+			cfg.JobDefaults.Batch.Task.Publisher.Config = config.RequesterConfig.JobDefaults.Batch.Task.Publisher.Config
+		}
 		config.RequesterConfig = cfg
 	}
 
 	if config.ComputeConfig.TotalResourceLimits.IsZero() {
-		// TODO(forrest): [correctness] if the provided compute config has one `0` field we override the whole thing.
-		// we probably want to merge these instead.
+		// TODO(forrest): [correctness] if the provided compute config has one `0` field we override the entire compute
+		// config settings.
 		executionDir, err := s.Config.ExecutionDir()
 		s.Require().NoError(err)
 		cfg, err := node.NewComputeConfigWithDefaults(executionDir)
@@ -104,13 +105,11 @@ func (s *ScenarioRunner) setupStack(config *StackConfig) (*devstack.DevStack, *s
 		config.ComputeConfig = cfg
 	}
 
-	config.RequesterConfig.DefaultPublisher = defaultPublisher
-
 	stack := testutils.Setup(s.Ctx, s.T(), s.Repo, s.Config,
 		append(config.DevStackOptions.Options(),
 			devstack.WithComputeConfig(config.ComputeConfig),
 			devstack.WithRequesterConfig(config.RequesterConfig),
-			testutils.WithNoopExecutor(config.ExecutorConfig, s.Config.Node.Compute.ManifestCache),
+			testutils.WithNoopExecutor(config.ExecutorConfig, s.Config.Engines),
 		)...,
 	)
 
diff --git a/pkg/test/teststack/stack.go b/pkg/test/teststack/stack.go
index a84c6773d1..bf960b7f87 100644
--- a/pkg/test/teststack/stack.go
+++ b/pkg/test/teststack/stack.go
@@ -41,7 +41,7 @@ func Setup(
 	ctx context.Context,
 	t testing.TB,
 	fsr *repo.FsRepo,
-	cfg types.BacalhauConfig,
+	cfg types.Bacalhau,
 	opts ...devstack.ConfigOption,
 ) *devstack.DevStack {
 	cm := system.NewCleanupManager()
@@ -63,7 +63,7 @@ func Setup(
 	return stack
 }
 
-func WithNoopExecutor(noopConfig noop_executor.ExecutorConfig, cfg types.DockerCacheConfig) devstack.ConfigOption {
+func WithNoopExecutor(noopConfig noop_executor.ExecutorConfig, cfg types.EngineConfig) devstack.ConfigOption {
 	return devstack.WithDependencyInjector(node.NodeDependencyInjector{
 		ExecutorsFactory: &mixedExecutorFactory{
 			standardFactory: node.NewStandardExecutorsFactory(cfg),
diff --git a/pkg/test/utils/utils.go b/pkg/test/utils/utils.go
index 01492214cb..bedf1a400f 100644
--- a/pkg/test/utils/utils.go
+++ b/pkg/test/utils/utils.go
@@ -11,6 +11,7 @@ import (
 	"github.com/nats-io/nats.go"
 	"github.com/stretchr/testify/require"
 
+	"github.com/bacalhau-project/bacalhau/pkg/config/types"
 	"github.com/bacalhau-project/bacalhau/pkg/lib/network"
 	"github.com/bacalhau-project/bacalhau/pkg/models"
 	"github.com/bacalhau-project/bacalhau/pkg/publicapi/apimodels"
@@ -32,8 +33,16 @@ func GetJobFromTestOutput(ctx context.Context, t *testing.T, c clientv2.API, out
 }
 
 // MustHaveIPFS will skip the test if the test is running in an environment that cannot support IPFS.
-func MustHaveIPFS(t testing.TB, ipfsConnect string) {
-	if !IsIPFSEnabled(ipfsConnect) {
+// Otherwise it returns an IPFS connect string
+func MustHaveIPFS(t testing.TB, cfg types.Bacalhau) {
+	downloaderConfigured := cfg.ResultDownloaders.IsNotDisabled(models.StorageSourceIPFS) &&
+		cfg.ResultDownloaders.Types.IPFS.Endpoint != ""
+	inputSourceConfigured := cfg.InputSources.IsNotDisabled(models.StorageSourceIPFS) &&
+		cfg.InputSources.Types.IPFS.Endpoint != ""
+	publisherConfigured := cfg.Publishers.IsNotDisabled(models.PublisherIPFS) &&
+		cfg.Publishers.Types.IPFS.Endpoint != ""
+
+	if !(downloaderConfigured && inputSourceConfigured && publisherConfigured) {
 		t.Skip("Cannot run this test because it IPFS Connect is not configured")
 	}
 }
diff --git a/test/bin/bacalhau.sh b/test/bin/bacalhau.sh
index 91df01818f..f056f6c6b2 100644
--- a/test/bin/bacalhau.sh
+++ b/test/bin/bacalhau.sh
@@ -69,3 +69,17 @@ after_each() {
     teardown_nodes
     clean_repo
 }
+
+start_bacalhau_serve_with_config() {
+  # Start the server in the background
+  $BACALHAU serve $@ > /dev/null 2>&1 &
+
+  SERVER_PID=$!
+
+  # Wait for the server to come online
+  # You can use a loop to check if the server is responding, e.g., using curl
+  while ! curl -s http://localhost:1234/api/v1/agent/alive; do
+    echo "Waiting for bacalhau server to come online..."
+    sleep 1
+  done
+}
diff --git a/test/config.sh b/test/config.sh
deleted file mode 100755
index 8929f6ae34..0000000000
--- a/test/config.sh
+++ /dev/null
@@ -1,145 +0,0 @@
-#!bin/bashtub
-
-source bin/bacalhau.sh
-
-
-testcase_config_set_is_persistent() {
-   TEST_VALUE=$RANDOM
-   subject bacalhau config set 'User.InstallationID' $TEST_VALUE
-   assert_equal 0 $status
-
-   subject file $BACALHAU_DIR/config.yaml
-   assert_equal 0 $status
-
-   # Verify the contents of the config file
-   subject cat "$BACALHAU_DIR/config.yaml | grep installationid"
-   assert_match "${TEST_VALUE}" "$stdout"
-}
-
-# assert we can start bacalhau without a config and the default values are used
-testcase_config_with_no_flags_has_defaults() {
-  start_bacalhau_serve_with_config
-
-  subject curl -s http://localhost:1234/api/v1/agent/config
-  assert_equal 0 $status
-  assert_match "0.0.0.0" $(echo $stdout | jq .Node.ServerAPI.Host)
-  assert_match 1234 $(echo $stdout | jq .Node.ServerAPI.Port)
-  assert_match "requester" $(echo $stdout | jq .Node.Type[])
-  assert_match "bootstrap.production.bacalhau.org" $(echo $stdout | jq .Node.ClientAPI.Host)
-  assert_match "1234" $(echo $stdout | jq .Node.ClientAPI.Port)
-  assert_match "{}" $(echo $stdout | jq .Node.Labels)
-
-  kill $SERVER_PID
-}
-
-# assert we can start bacalhau with a config file via the -c flag
-testcase_config_with_file() {
-  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml
-
-  subject curl -s http://localhost:1234/api/v1/agent/config
-  assert_equal 0 $status
-
-  # These are default values unaffected by the config file
-  assert_match "0.0.0.0" $(echo $stdout | jq .Node.ServerAPI.Host)
-  assert_match 1234 $(echo $stdout | jq .Node.ServerAPI.Port)
-  assert_match "requester" $(echo $stdout | jq .Node.Type[])
-
-  # These are values set in the config file
-  assert_match "1.1.1.1" $(echo $stdout | jq .Node.ClientAPI.Host)
-  assert_match 1111 $(echo $stdout | jq .Node.ClientAPI.Port)
-  assert_match "bar" $(echo $stdout | jq .Node.Labels.foo)
-
-  kill $SERVER_PID
-}
-
-# assert we can start bacalhau with two config files, the latter overriding and merging with the base
-testcase_config_with_override_config_file() {
-  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml
-
-  subject curl -s http://localhost:1234/api/v1/agent/config
-  assert_equal 0 $status > /dev/null
-
-  # These are default values unaffected by the config file
-  assert_match "0.0.0.0" $(echo $stdout | jq .Node.ServerAPI.Host)
-  assert_match 1234 $(echo $stdout | jq .Node.ServerAPI.Port)
-  assert_match "requester" $(echo $stdout | jq .Node.Type[])
-
-  # These are values set in the base config file that were not overridden
-  assert_match 1111 $(echo $stdout | jq .Node.ClientAPI.Port)
-  assert_match "bar" $(echo $stdout | jq .Node.Labels.foo)
-
-
-  # This value overrides the base config
-  assert_match "2.2.2.2" $(echo $stdout | jq .Node.ClientAPI.Host)
-
-  # This value is merged between the configs
-  assert_match "boo" $(echo $stdout | jq .Node.Labels.buz)
-
-  kill $SERVER_PID
-}
-
-# same as test case above, but with addition of --api-host flag that overrides both configs files
-testcase_config_with_override_config_file_with_api_config_flag() {
-  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml --api-host=3.3.3.3
-
-  subject curl -s http://localhost:1234/api/v1/agent/config
-  assert_equal 0 $status
-
-  # These are default values unaffected by the config file
-  assert_match "0.0.0.0" $(echo $stdout | jq .Node.ServerAPI.Host)
-  assert_match 1234 $(echo $stdout | jq .Node.ServerAPI.Port)
-  assert_match "requester" $(echo $stdout | jq .Node.Type[])
-
-  # These are values set in the base config file that were not overridden
-  assert_match 1111 $(echo $stdout | jq .Node.ClientAPI.Port)
-  assert_match "bar" $(echo $stdout | jq .Node.Labels.foo)
-
-
-  # This value overrides the config files from the flag
-  assert_match "3.3.3.3" $(echo $stdout | jq .Node.ClientAPI.Host)
-
-  # This value is merged between the configs
-  assert_match "boo" $(echo $stdout | jq .Node.Labels.buz)
-
-  kill $SERVER_PID
-}
-
-# same as test case above, but with addition of a config flag and the dedicated --api-flag, config flag takes precedence
-testcase_config_with_override_config_file_with_api_config_flag_and_dedicated_flag() {
-  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml --api-host=3.3.3.3 -c node.clientapi.host=4.4.4.4
-
-  subject curl -s http://localhost:1234/api/v1/agent/config
-  assert_equal 0 $status
-
-  # These are default values unaffected by the config file
-  assert_match "0.0.0.0" $(echo $stdout | jq .Node.ServerAPI.Host)
-  assert_match 1234 $(echo $stdout | jq .Node.ServerAPI.Port)
-  assert_match "requester" $(echo $stdout | jq .Node.Type[])
-
-  # These are values set in the base config file that were not overridden
-  assert_match 1111 $(echo $stdout | jq .Node.ClientAPI.Port)
-  assert_match "bar" $(echo $stdout | jq .Node.Labels.foo)
-
-
-  # This value overrides the config files from flag
-  assert_match "4.4.4.4" $(echo $stdout | jq .Node.ClientAPI.Host)
-
-  # This value is merged between the configs
-  assert_match "boo" $(echo $stdout | jq .Node.Labels.buz)
-
-  kill $SERVER_PID
-}
-
-start_bacalhau_serve_with_config() {
-  # Start the server in the background
-  $BACALHAU serve $@ > /dev/null 2>&1 &
-
-  SERVER_PID=$!
-
-  # Wait for the server to come online
-  # You can use a loop to check if the server is responding, e.g., using curl
-  while ! curl -s http://localhost:1234/api/v1/agent/alive; do
-    echo "Waiting for bacalhau server to come online..."
-    sleep 1
-  done
-}
\ No newline at end of file
diff --git a/test/config_set_persistent.sh b/test/config_set_persistent.sh
new file mode 100755
index 0000000000..38a070b5df
--- /dev/null
+++ b/test/config_set_persistent.sh
@@ -0,0 +1,22 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+
+testcase_config_set_is_persistent() {
+   TEST_VALUE=$RANDOM
+   subject bacalhau config set --config=./test-persistent.yaml 'NameProvider' $TEST_VALUE
+   assert_equal 0 $status
+
+   subject file ./test-persistent.yaml
+   assert_equal 0 $status
+
+   # Verify the contents of the config file
+   subject cat "./test-persistent.yaml | grep -i NameProvider"
+   assert_match "${TEST_VALUE}" "$stdout"
+   rm ./test-persistent.yaml
+}
+
+
+
+
diff --git a/test/config_with_defaults.sh b/test/config_with_defaults.sh
new file mode 100644
index 0000000000..28cea068b2
--- /dev/null
+++ b/test/config_with_defaults.sh
@@ -0,0 +1,21 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+# assert we can start bacalhau without a config and the default values are used
+testcase_config_with__defaults() {
+  start_bacalhau_serve_with_config
+
+  subject curl -s http://localhost:1234/api/v1/agent/config
+  assert_equal 0 $status
+
+  assert_match "puuid" $(echo $stdout | jq .NameProvider)
+  assert_match "0.0.0.0" $(echo $stdout | jq .API.Host)
+  assert_match 1234 $(echo $stdout | jq .API.Port)
+  assert_match "true" $(echo $stdout | jq .Orchestrator.Enabled)
+  assert_match "false" $(echo $stdout | jq .Compute.Enabled)
+  assert_match "null" $(echo $stdout | jq .Compute.Labels)
+
+  kill $SERVER_PID
+}
+
diff --git a/test/config_with_file.sh b/test/config_with_file.sh
new file mode 100644
index 0000000000..2f1331ca50
--- /dev/null
+++ b/test/config_with_file.sh
@@ -0,0 +1,23 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+testcase_config_with_file() {
+  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml
+
+  subject curl -s http://localhost:1234/api/v1/agent/config
+  assert_equal 0 $status
+
+  # These are default values unaffected by the config file
+  assert_match "0.0.0.0" $(echo $stdout | jq .API.Host)
+  assert_match 1234 $(echo $stdout | jq .API.Port)
+  assert_match "true" $(echo $stdout | jq .Orchestrator.Enabled)
+  assert_match "false" $(echo $stdout | jq .Compute.Enabled)
+
+  # These are values set in the config file
+  assert_match "uuid" $(echo $stdout | jq .NameProvider)
+  assert_match "bar" $(echo $stdout | jq .Compute.Labels.foo)
+
+  kill $SERVER_PID
+}
+
diff --git a/test/config_with_file_override.sh b/test/config_with_file_override.sh
new file mode 100644
index 0000000000..2454b139f1
--- /dev/null
+++ b/test/config_with_file_override.sh
@@ -0,0 +1,29 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+# assert we can start bacalhau with two config files, the latter overriding and merging with the base
+testcase_config_with_override_file() {
+  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml
+
+  subject curl -s http://localhost:1234/api/v1/agent/config
+  assert_equal 0 $status > /dev/null
+
+  # These are default values unaffected by the config file
+  assert_match "0.0.0.0" $(echo $stdout | jq .API.Host)
+  assert_match 1234 $(echo $stdout | jq .API.Port)
+  assert_match "true" $(echo $stdout | jq .Orchestrator.Enabled)
+  assert_match "false" $(echo $stdout | jq .Compute.Enabled)
+
+  # These are values set in the base config file that were not overridden
+  assert_match "bar" $(echo $stdout | jq .Compute.Labels.foo)
+
+
+  # This value overrides the base config
+  assert_match "hostname" $(echo $stdout | jq .NameProvider)
+
+  # This value is merged between the configs
+  assert_match "boo" $(echo $stdout | jq .Compute.Labels.buz)
+
+  kill $SERVER_PID
+}
diff --git a/test/config_with_file_override_and_flag.sh b/test/config_with_file_override_and_flag.sh
new file mode 100644
index 0000000000..d4934b5c66
--- /dev/null
+++ b/test/config_with_file_override_and_flag.sh
@@ -0,0 +1,29 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+testcase_config_with_override_config_file_and_flag() {
+  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml --labels=apple=banana
+
+  subject curl -s http://localhost:1234/api/v1/agent/config
+  assert_equal 0 $status > /dev/null
+
+  # These are default values unaffected by the config file
+  assert_match "0.0.0.0" $(echo $stdout | jq .API.Host)
+  assert_match 1234 $(echo $stdout | jq .API.Port)
+  assert_match "true" $(echo $stdout | jq .Orchestrator.Enabled)
+  assert_match "false" $(echo $stdout | jq .Compute.Enabled)
+
+  # set in the override
+  assert_match "hostname" $(echo $stdout | jq .NameProvider)
+
+  # overritten by the flag
+  assert_match "null" $(echo $stdout | jq .Compute.Labels.foo)
+  assert_match "null" $(echo $stdout | jq .Compute.Labels.buz)
+
+
+  # This value is merged between the configs
+  assert_match "banana" $(echo $stdout | jq .Compute.Labels.apple)
+
+  kill $SERVER_PID
+}
diff --git a/test/config_with_file_override_and_flag_and_config_flag.sh b/test/config_with_file_override_and_flag_and_config_flag.sh
new file mode 100644
index 0000000000..96faf91910
--- /dev/null
+++ b/test/config_with_file_override_and_flag_and_config_flag.sh
@@ -0,0 +1,32 @@
+#!bin/bashtub
+
+source bin/bacalhau.sh
+
+testcase_config_with_override_config_file_with_api_config_flag_and_dedicated_flag() {
+  start_bacalhau_serve_with_config -c $ROOT/testdata/config/base.yaml -c $ROOT/testdata/config/override.yaml --web-ui=false --config webui.enabled=true
+
+  subject curl -s http://localhost:1234/api/v1/agent/config
+  assert_equal 0 $status > /dev/null
+
+  # These are default values unaffected by the config file
+  assert_match "0.0.0.0" $(echo $stdout | jq .API.Host)
+  assert_match 1234 $(echo $stdout | jq .API.Port)
+  assert_match "true" $(echo $stdout | jq .Orchestrator.Enabled)
+  assert_match "false" $(echo $stdout | jq .Compute.Enabled)
+
+  # These are values set in the base config file that were not overridden
+  assert_match "bar" $(echo $stdout | jq .Compute.Labels.foo)
+
+
+  # This value overrides the base config
+  assert_match "hostname" $(echo $stdout | jq .NameProvider)
+
+  # This value is merged between the configs
+  assert_match "boo" $(echo $stdout | jq .Compute.Labels.buz)
+
+  assert_match "true" $(echo $stdout | jq .WebUI.Enabled)
+
+
+  kill $SERVER_PID
+}
+
diff --git a/testdata/config/base.yaml b/testdata/config/base.yaml
index 28075a3c89..0afbb54f0a 100644
--- a/testdata/config/base.yaml
+++ b/testdata/config/base.yaml
@@ -1,6 +1,4 @@
-Node:
-  ClientAPI:
-    Host: "1.1.1.1"
-    Port: 1111
+NameProvider: "uuid"
+Compute:
   Labels:
     "foo": bar
\ No newline at end of file
diff --git a/testdata/config/override.yaml b/testdata/config/override.yaml
index c1a890fa13..341c1338d1 100644
--- a/testdata/config/override.yaml
+++ b/testdata/config/override.yaml
@@ -1,5 +1,4 @@
-Node:
-  ClientAPI:
-    Host: "2.2.2.2"
+NameProvider: "hostname"
+Compute:
   Labels:
     "buz": boo
\ No newline at end of file