Skip to content

tinyconf

tinyconf is a simple and universal library for parsing configs in Go. It fills your config structs with values from drivers: default values from struct tags, YAML, JSON, TOML, INI and .properties files, environment variables, command line flags, Consul KV, HashiCorp Vault, etcd. Every driver is a separate small package, and you can add your own.

One-line ideology

The config is a plain Go struct. Where the values come from is described by struct tags and by the list of drivers, the last driver wins.

Install

go get github.com/insei/tinyconf@latest

Minimum Go version is 1.19.

Quick start

package main

import (
    "fmt"
    "time"

    "github.com/insei/tinyconf"
    "github.com/insei/tinyconf/drivers/env"
    "github.com/insei/tinyconf/drivers/tag"
    "github.com/insei/tinyconf/drivers/yaml"
    "github.com/insei/tinyconf/logger"
)

type HTTP struct {
    Host    string        `initial:"localhost" yaml:"host" env:"HTTP_HOST" doc:"http host"`
    Port    int           `initial:"8080" yaml:"port" env:"HTTP_PORT" doc:"http port"`
    Timeout time.Duration `initial:"30s" yaml:"timeout" env:"HTTP_TIMEOUT" doc:"http timeout"`
}

type Config struct {
    HTTP     HTTP     `yaml:"http"`
    Hosts    []string `initial:"a,b" yaml:"hosts" env:"HOSTS" doc:"allowed hosts"`
    Password string   `yaml:"password" env:"PASSWORD" hidden:"true"`
}

func main() {
    tagDriver, err := tag.New("initial") // defaults from the `initial` tag
    if err != nil {
        panic(err)
    }
    yamlDriver, err := yaml.New("config.yaml")
    if err != nil {
        panic(err)
    }
    envDriver, err := env.New()
    if err != nil {
        panic(err)
    }

    // the next driver overrides values of the previous one:
    // defaults < config.yaml < environment variables
    config, err := tinyconf.New(
        tinyconf.WithLogger(logger.NewFmtLogger(logger.INFO)),
        tinyconf.WithDriver(tagDriver),
        tinyconf.WithDriver(yamlDriver),
        tinyconf.WithDriver(envDriver),
    )
    if err != nil {
        panic(err)
    }

    c := &Config{}
    if err = config.Register(c); err != nil {
        panic(err)
    }
    if err = config.Parse(c); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", *c)
}

With this config.yaml

http:
  port: 9090
password: secret

and HTTP_HOST=example.com in the environment the program prints

{HTTP:{Host:example.com Port:9090 Timeout:30s} Hosts:[a b] Password:secret}

Host came from the environment, Port and Password from the file, Timeout and Hosts from the defaults.

  • Why tinyconf? →

    Where it fits, what it gives up, and how it compares to viper, koanf, cleanenv and others.

  • Use cases →

    Recipes for typical tasks: environment only, file with overrides, files per environment, secrets, containers, command line tools, optional sections, reloading, tests.

  • Features →

    The manager, struct tags, supported types, nested structs and sub configs, required fields, value sources, reloading, documentation generation, logging.

  • Drivers →

    Bundled drivers and how to write your own.

  • API reference →

    Autogenerated on pkg.go.dev.

  • Repository →

    Source, issue tracker, pull requests.