Home
Complete Configuration Management for Go
Confii loads, merges, validates, and manages configuration from any source — YAML, JSON, TOML, INI, .env files, environment variables, HTTP endpoints, and cloud stores — with type-safe generics, secret resolution, source tracking, drift detection, and versioning.
Features¶
- Multi-source loading — YAML, JSON, TOML, INI, .env, env vars, HTTP, S3, SSM, Azure Blob, GCS, IBM COS, Git
- Type-safe generics —
Config[T]withcfg.Typed()returning*Tand full IDE autocomplete - 6 merge strategies — replace, merge, append, prepend, intersection, union — with per-path overrides
- Secret resolution —
${secret:key}placeholders from AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, HashiCorp Vault (9 auth methods) - Config composition — Hydra-style
_includeand_defaultsdirectives with cycle detection - Environment resolution — Automatic
default+production/stagingmerging - Hook system — 4 types (key, value, condition, global) for value transformation on access
- Introspection —
Explain(),Layers(),Schema(), source tracking, override history - Drift detection — Diff configs, detect unintended changes, version with rollback
- Dynamic reloading — File watching via fsnotify, incremental reload (mtime + SHA256)
- Observability — Access metrics, event emission, change callbacks
- CLI tool — 10 commands: load, get, validate, export, diff, debug, explain, lint, docs, migrate
- Thread-safe —
sync.RWMutex, zero global state, safe for concurrent reads
Install¶
Quick Start¶
cfg, err := confii.New[any](context.Background(),
confii.WithLoaders(
loader.NewYAML("config.yaml"),
loader.NewEnvironment("APP"),
),
confii.WithEnv("production"),
)
if err != nil {
log.Fatal(err)
}
host, _ := cfg.Get("database.host")
port := cfg.GetIntOr("database.port", 5432)
debug := cfg.GetBoolOr("debug", false)
type AppConfig struct {
Database struct {
Host string `mapstructure:"host" validate:"required"`
Port int `mapstructure:"port" validate:"required,min=1,max=65535"`
} `mapstructure:"database"`
Debug bool `mapstructure:"debug"`
}
cfg, err := confii.New[AppConfig](ctx,
confii.WithLoaders(loader.NewYAML("config.yaml")),
confii.WithValidateOnLoad(true),
)
model, _ := cfg.Typed()
fmt.Println(model.Database.Host) // IDE autocomplete works
Drop a .confii.yaml in your project root — zero Go code to configure Confii itself:
.confii.yaml
# Confii finds this file automatically
default_environment: production
env_switcher: APP_ENV
validate_on_load: true
use_env_expander: true
freeze_on_load: true
deep_merge: true
log_level: warn
schema_path: schema.json
sources:
- type: yaml
path: config/base.yaml
- type: yaml
path: config/prod.yaml
- type: env
prefix: APP
secrets:
provider: vault
address: https://vault.internal:8200
auth: kubernetes
main.go
// That's it — Confii reads .confii.yaml automatically
cfg, err := confii.New[AppConfig](ctx)
if err != nil {
log.Fatal(err)
}
model, _ := cfg.Typed()
No WithLoaders(), no WithEnv(), no WithValidateOnLoad() — everything is declared in the config file. Constructor arguments still override self-config values when you need them.