FlexConf¶
Flexible configuration & secret management for Go โ declare your config as
plain Go types, and let the people who write the config decide where each
value comes from: a file, an environment variable, or a vault.
service: api
timeout: 10s
url: https://$(env:HOST)/api # ๐ฑ from the environment
token: $(secret:artifactory/token) # ๐ from an encrypted vault
Your application code never changes โ it just sees a string.
Why FlexConf?¶
Most config libraries make the application decide what is an env var, what is a flag, and what is a secret โ hardcoded at compile time. FlexConf flips that around:
The core idea
The application declares what configuration it needs (typed Go
structs). The operator decides where each value comes from โ plain
YAML, $(env:โฆ), $(file:โฆ), or $(secret:โฆ) โ without touching a line
of Go.
That separation is what makes the same binary run unchanged on a laptop, in CI, and in production โ only the config files differ.
How it works¶
flowchart LR
A["๐ Config layers<br/><small>/etc/myapp โ ./config</small>"] --> B["๐ Deep merge"]
B --> C["๐งฉ Resolve tokens<br/><small>env ยท file ยท config ยท secret</small>"]
C --> D["๐ท๏ธ Bind to Go struct<br/><small>typed, validated, all-or-nothing</small>"]
C -.-> E["๐ Vault agent<br/><small>ssh-agent-style, auto-locks</small>"]
- Layer โ config directories are merged lowest โ highest precedence.
- Resolve โ
$(scheme:path)tokens are expanded at load time. - Bind โ the merged tree is bound to your struct; on any error, your struct is left untouched.
What's in the box¶
-
Layered configuration
Stack config directories (
/etc/myapp,./config, โฆ). Maps deep-merge, scalars override โ defaults live in Go. -
Typed schema & binding
Plain Go structs with
flexconftags. Required fields, durations, nested types โ binding is all-or-nothing. -
Templating tokens
$(env:โฆ),$(file:โฆ),$(config:โฆ),$(secret:โฆ)โ embeddable in literal text, with escaping and custom resolvers. -
Vault-backed secrets
Secrets live in an encrypted vault (KeePass, โฆ), never in config files. Operators own the vault registry.
-
Secret agent & CLI
flexconf secret unlockspawns an ssh-agent-style daemon holding the unlocked vault in memory, auto-locking on idle. -
Variants & prompting
Polymorphic config via discriminators, and interactive prompting when a value can't be resolved silently.
Try it in 30 seconds¶
type Config struct {
Service string `flexconf:"service,required"`
Token string `flexconf:"token"` // may be $(secret:โฆ) โ the type doesn't care
}
var cfg Config
err := flexconf.New("/etc/myapp", "./config").Load("config.yaml", &cfg)
That's it โ head to the Get started guide for the full
four-step setup, including secrets.