New Sign in

fierj

Public

Tiny personal git forge

← fierj / config.go
package main

import (
	"encoding/json"
	"log/slog"
	"os"
	"reflect"
)

const envPrefix = "FIERJ_"

type Config struct {
	Addr        string `json:"addr" env:"ADDR"`
	Host        string `json:"host" env:"HOST"`
	Dir         string `json:"dir" env:"DIR"`
	SSHAddr     string `json:"ssh_addr" env:"SSH_ADDR"`
	SSHHostKey  string `json:"ssh_host_key" env:"SSH_HOST_KEY"`
	UsersPath   string `json:"users_path" env:"USERS_PATH"`
	CookieSecret string `json:"cookie_secret" env:"COOKIE_SECRET"`
}

func LoadConfig(path string) Config {
	// default config
	cfg := Config{
		Addr:         ":8080",
		Host:         "localhost:8080",
		SSHAddr:      ":2222",
		Dir:          "repos",
		UsersPath:    "users.json",
		CookieSecret: "change-me-in-production",
	}

	// read file, log read/unmarshal errors, if any
	b, err := os.ReadFile(path)
	if err != nil {
		if !os.IsNotExist(err) {
			slog.Error("failed to read config file", "error", err)
		}
	} else {
		if err := json.Unmarshal(b, &cfg); err != nil {
			slog.Error("failed to unmarshal config file", "error", err)
		}
	}

	// scan fields and override with env vars (FIERJ_<env>) if present
	v := reflect.ValueOf(&cfg).Elem()
	for i := 0; i < v.NumField(); i++ {
		field := v.Type().Field(i)
		envTag := field.Tag.Get("env")
		if envTag == "" {
			continue
		}
		if envVal, ok := os.LookupEnv(envPrefix + envTag); ok {
			v.Field(i).SetString(envVal)
		}
	}
	return cfg
}