// Package config loads tomswallapi runtime configuration from the environment. package config import ( "fmt" "net/url" "os" ) // Config holds all runtime configuration, sourced from environment variables. type Config struct { ListenAddr string DBHost string DBPort string DBUser string DBPassword string DBName string DBSSLMode string // WriteToken guards all mutating API endpoints (used by the Terraform provider). WriteToken string // AgentToken guards the per-device config endpoint (used by tomswall agents). AgentToken string // IPLocateAPIKey is used to expand ASN address groups into prefixes. IPLocateAPIKey string } // Load reads configuration from the environment, applying defaults. func Load() (*Config, error) { c := &Config{ ListenAddr: env("TOMSWALLAPI_LISTEN_ADDR", ":8000"), DBHost: env("TOMSWALLAPI_DB_HOST", "localhost"), DBPort: env("TOMSWALLAPI_DB_PORT", "5432"), DBUser: env("TOMSWALLAPI_DB_USER", "tomswallapi"), DBPassword: os.Getenv("TOMSWALLAPI_DB_PASSWORD"), DBName: env("TOMSWALLAPI_DB_NAME", "tomswallapi"), DBSSLMode: env("TOMSWALLAPI_DB_SSLMODE", "disable"), WriteToken: os.Getenv("TOMSWALLAPI_WRITE_TOKEN"), AgentToken: os.Getenv("TOMSWALLAPI_AGENT_TOKEN"), IPLocateAPIKey: os.Getenv("TOMSWALLAPI_IPLOCATE_API_KEY"), } if c.DBName == "" { return nil, fmt.Errorf("TOMSWALLAPI_DB_NAME must not be empty") } return c, nil } // DatabaseDSN builds a libpq-style connection string. func (c *Config) DatabaseDSN() string { u := url.URL{ Scheme: "postgres", User: url.UserPassword(c.DBUser, c.DBPassword), Host: fmt.Sprintf("%s:%s", c.DBHost, c.DBPort), Path: c.DBName, } q := u.Query() q.Set("sslmode", c.DBSSLMode) u.RawQuery = q.Encode() return u.String() } func env(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def }