Allow loading secrets from an additional configuration file.

Adds the `-secrets` command line flag, which defaults to `$CREDENTIALS_DIRECTORY/secrets.toml` if it exists. The secrets.toml file will be loaded the same way as the main config.toml.

Reviewed-on: https://codeberg.org/git-pages/git-pages/pulls/137
Reviewed-by: Catherine <whitequark@whitequark.org>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
This commit is contained in:
Andrew Cassidy
2026-04-20 02:40:34 +02:00
committed by Catherine
parent 021c493daa
commit b3692362d8
2 changed files with 36 additions and 9 deletions

View File

@@ -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 {

View File

@@ -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: