/*
* Copyright (C) 2024 Jonni Liljamo <jonni@liljamo.com>
*
* This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for
* more information.
*/
// Package config implements the global program config.
package config
import (
"fmt"
"log/slog"
"net"
"os"
"strconv"
"github.com/miekg/dns"
)
// TODO: Switch back to erya-go once I've rearchitected it.
//import "git.src.quest/~liljamo/erya-go/util"
// FeluConfig is a global for accessing the global config.
var FeluConfig *config
type config struct {
// Domain, is fqdn'd when read.
//
// Used for NS records and as DNS pattern.
Domain string
// IPv4 address to return on A queries for Domain.
IPv4 string
// The name displayed in the frontend.
ServiceName string
// The email to return in SOAs (e.g. admin.felu.arpa.), is fqdn'd when read.
SOAEmail string
// Initial email for the admin user, used if no admin account exists (e.g. first boot).
InitialAdminEmail string
// Initial password for the admin user, used if no admin account exists (e.g. first boot).
InitialAdminPwd string
LogLevel string
// Data directory, with trailing slash
DataDir string
FrontendBindAddr string
// API url, where the API is served at (e.g. https://api.felud.arpa)
APIUrl string
APIBindAddr string
DNSBindIP string
DNSBindPort int32
}
// InitConfig initializes the global program config from environment variables.
func InitConfig() {
ipv4 := net.ParseIP(loadEnvStr("FELU_IPV4")).To4()
if ipv4 == nil {
panic("Invalid IPv4")
}
FeluConfig = &config{
Domain: dns.Fqdn(loadEnvStr("FELU_DOMAIN")),
IPv4: ipv4.String(),
ServiceName: loadEnvStrDef("FELU_SERVICE_NAME", "FeluDDNS"),
SOAEmail: dns.Fqdn(loadEnvStr("FELU_SOA_EMAIL")),
InitialAdminEmail: loadEnvStrDef("FELU_INITIAL_ADMIN_EMAIL", "admin@example.com"),
InitialAdminPwd: loadEnvStrDef("FELU_INITIAL_ADMIN_PWD", "feluadmin"),
LogLevel: loadEnvStrDef("FELU_LOG_LEVEL", "info"),
DataDir: loadEnvStrDef("FELU_DB_PATH", "/var/felu/"),
FrontendBindAddr: loadEnvStrDef("FELU_FRONTEND_BIND_ADDR", "0.0.0.0:8080"),
APIUrl: loadEnvStr("FELU_API_URL"),
APIBindAddr: loadEnvStrDef("FELU_API_BIND_ADDR", "0.0.0.0:8081"),
DNSBindIP: loadEnvStrDef("FELU_DNS_BIND_IP", "0.0.0.0"),
DNSBindPort: loadEnvInt32Def("FELU_DNS_BIND_PORT", 53),
}
}
func loadEnvStr(key string) string {
value, found := os.LookupEnv(key)
if found {
return value
}
panic(fmt.Sprintf("Env var '%s' not found", key))
}
func loadEnvStrDef(key string, def string) string {
value, found := os.LookupEnv(key)
if found {
return value
}
slog.Warn("Env var not set, using default", slog.String("key", key), slog.String("def", def))
return def
}
func loadEnvInt32Def(key string, def int32) int32 {
value, found := os.LookupEnv(key)
if found {
res, err := strconv.ParseInt(value, 10, 32)
if err != nil {
panic(fmt.Sprintf("Couldn't parse env var '%s' into an integer", key))
}
return int32(res)
}
slog.Warn("Env var not set, using default", slog.String("key", key), slog.Int("def", int(def)))
return def
}