diff --git a/src/config.go b/src/config.go index 4a99c87..37b0c75 100644 --- a/src/config.go +++ b/src/config.go @@ -309,19 +309,17 @@ func PrintConfigEnvVars() { }) } -func Configure(tomlPath string) (config *Config, err error) { - // start with an all-default configuration - config = new(Config) - defaults.MustSet(config) - - // inject values from `config.toml` +func ReadConfigFile(config *Config, tomlPath string) (err error) { if tomlPath != "" { var file *os.File file, err = os.Open(tomlPath) if err != nil { return } - defer file.Close() + + defer func(file *os.File) { + err = file.Close() + }(file) decoder := toml.NewDecoder(file) decoder.DisallowUnknownFields() @@ -330,6 +328,21 @@ func Configure(tomlPath string) (config *Config, err error) { return } } + return nil +} + +func Configure(tomlPaths ...string) (config *Config, err error) { + // start with an all-default configuration + config = new(Config) + defaults.MustSet(config) + + // inject values from each toml file + for _, tomlPath := range tomlPaths { + err := ReadConfigFile(config, tomlPath) + if err != nil { + return nil, err + } + } // inject values from the environment, overriding everything else err = walkConfig(config, func(envName string, reflValue reflect.Value) error { diff --git a/src/main.go b/src/main.go index facb66c..4ad92f2 100644 --- a/src/main.go +++ b/src/main.go @@ -204,6 +204,8 @@ func Main(versionInfo string) { flag.Usage = usage configTomlPath := flag.String("config", "", "load configuration from `filename` (default: 'config.toml')") + secretTomlPath := flag.String("secrets", "", + "load additional configuration values from `filename` (default: '$CREDENTIALS_DIRECTORY/secrets.toml' if it exists)") noConfig := flag.Bool("no-config", false, "run without configuration file (configure via environment variables)") printConfigEnvVars := flag.Bool("print-config-env-vars", false, @@ -291,7 +293,19 @@ func Main(versionInfo string) { if *configTomlPath == "" && !*noConfig { *configTomlPath = "config.toml" } - if config, err = Configure(*configTomlPath); err != nil { + + if *secretTomlPath == "" && !*noConfig { + // check for a second config file at $CREDENTIALS_DIRECTORY/secrets.toml, and use it + if systemdCredentialsDir := os.Getenv("CREDENTIALS_DIRECTORY"); systemdCredentialsDir != "" { + secretTomlTestPath := path.Join(systemdCredentialsDir, "secrets.toml") + _, err := os.Stat(secretTomlTestPath) + if !errors.Is(err, os.ErrNotExist) { + *secretTomlPath = secretTomlTestPath + } + } + } + + if config, err = Configure(*configTomlPath, *secretTomlPath); err != nil { logc.Fatalln(ctx, "config:", err) } @@ -602,7 +616,7 @@ func Main(versionInfo string) { // Note that not all of the configuration is updated on reload. Listeners are kept as-is. // The backend is not recreated (this is intentional as it allows preserving the cache). OnReload(func() { - if newConfig, err := Configure(*configTomlPath); err != nil { + if newConfig, err := Configure(*configTomlPath, *secretTomlPath); err != nil { logc.Println(ctx, "config: reload err:", err) } else { // From https://go.dev/ref/mem: