feat: production-ready domain control dashboard
Container-Image veröffentlichen / container (push) Has been cancelled
Container-Image veröffentlichen / container (push) Has been cancelled
This commit is contained in:
1 parent
9c60eaf3fe
commit
df7516e7ab
45 files changed
+7932
-1
No files matched your search
@@ -0,0 +1,92 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultIPv4Primary = "https://api.ipify.org"
|
||||
DefaultIPv4Fallback = "https://ifconfig.co/ip"
|
||||
DefaultIPv6Primary = "https://api6.ipify.org"
|
||||
DefaultIPv6Fallback = "https://ifconfig.co/ip"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Address string
|
||||
DataDir string
|
||||
DatabasePath string
|
||||
MasterKeyFile string
|
||||
CookieSecure bool
|
||||
SessionTTL time.Duration
|
||||
HCloudBaseURL string
|
||||
Mode string
|
||||
ShutdownTimeout time.Duration
|
||||
}
|
||||
|
||||
func Load() (Config, error) {
|
||||
dataDir := value("APP_DATA_DIR", "/data")
|
||||
address := value("APP_ADDRESS", ":8080")
|
||||
if _, _, err := net.SplitHostPort(address); err != nil {
|
||||
return Config{}, fmt.Errorf("APP_ADDRESS must be host:port: %w", err)
|
||||
}
|
||||
|
||||
mode := strings.ToLower(value("APP_MODE", "lan"))
|
||||
if mode != "lan" && mode != "https" {
|
||||
return Config{}, fmt.Errorf("APP_MODE must be either lan or https")
|
||||
}
|
||||
|
||||
ttl, err := duration("APP_SESSION_TTL", 8*time.Hour)
|
||||
if err != nil || ttl < time.Hour || ttl > 7*24*time.Hour {
|
||||
return Config{}, fmt.Errorf("APP_SESSION_TTL must be between 1h and 168h")
|
||||
}
|
||||
shutdownTimeout, err := duration("APP_SHUTDOWN_TIMEOUT", 15*time.Second)
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("APP_SHUTDOWN_TIMEOUT: %w", err)
|
||||
}
|
||||
|
||||
keyFile := os.Getenv("APP_MASTER_KEY_FILE")
|
||||
if keyFile == "" {
|
||||
return Config{}, fmt.Errorf("APP_MASTER_KEY_FILE is required (mount a Docker secret there)")
|
||||
}
|
||||
|
||||
cookieSecure := mode == "https"
|
||||
if raw := os.Getenv("APP_COOKIE_SECURE"); raw != "" {
|
||||
parsed, parseErr := strconv.ParseBool(raw)
|
||||
if parseErr != nil {
|
||||
return Config{}, fmt.Errorf("APP_COOKIE_SECURE: %w", parseErr)
|
||||
}
|
||||
cookieSecure = parsed
|
||||
}
|
||||
|
||||
return Config{
|
||||
Address: address,
|
||||
DataDir: dataDir,
|
||||
DatabasePath: value("APP_DATABASE_PATH", filepath.Join(dataDir, "dyndns.db")),
|
||||
MasterKeyFile: keyFile,
|
||||
CookieSecure: cookieSecure,
|
||||
SessionTTL: ttl,
|
||||
HCloudBaseURL: strings.TrimRight(value("APP_HCLOUD_BASE_URL", "https://api.hetzner.cloud/v1"), "/"),
|
||||
Mode: mode,
|
||||
ShutdownTimeout: shutdownTimeout,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func value(name, fallback string) string {
|
||||
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func duration(name string, fallback time.Duration) (time.Duration, error) {
|
||||
if raw := strings.TrimSpace(os.Getenv(name)); raw != "" {
|
||||
return time.ParseDuration(raw)
|
||||
}
|
||||
return fallback, nil
|
||||
}
|
||||
Reference in new issue
Block a user