package main import ( "errors" "fmt" "log/slog" "os" "strings" "github.com/spf13/cobra" "github.com/spf13/viper" ) var cfgFile string var rootCmd = &cobra.Command{ Use: "weimar", Short: "Self-hosted media repository for small groups", Long: `weimar is a single-binary media repository for home servers. Store, tag, and browse memes and group-interest images with friends.`, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { return initConfig() }, SilenceUsage: true, SilenceErrors: true, } func Execute() error { return rootCmd.Execute() } func init() { rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "path to config file (default ./weimar.toml)") rootCmd.PersistentFlags().String("log-level", "info", "log level (debug, info, warn, error)") viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level")) } func initConfig() error { if cfgFile != "" { viper.SetConfigFile(cfgFile) } else { viper.AddConfigPath(".") viper.SetConfigName("weimar") } viper.SetEnvPrefix("WEIMAR") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) viper.AutomaticEnv() if err := viper.ReadInConfig(); err != nil { var notFound viper.ConfigFileNotFoundError if errors.As(err, ¬Found) { // No config file is fine — use defaults + env. } else { return fmt.Errorf("reading config: %w", err) } } setDefaults() level := slog.LevelInfo switch strings.ToLower(viper.GetString("log-level")) { case "debug": level = slog.LevelDebug case "warn": level = slog.LevelWarn case "error": level = slog.LevelError } slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level}))) return nil } func setDefaults() { viper.SetDefault("server.host", "0.0.0.0") viper.SetDefault("server.port", 8080) viper.SetDefault("database.path", "./data/weimar.db") viper.SetDefault("storage.path", "./data/images") viper.SetDefault("upload.max_size_mb", 50) viper.SetDefault("upload.rate_limit_per_minute", 0) viper.SetDefault("auth.allow_registration", true) viper.SetDefault("auth.require_auth_for_browse", false) }