package config import ( "encoding/json" "errors" "os" ) // Config holds all backend runtime configuration. type Config struct { StoragePath string `json:"storage_path"` DBPath string `json:"db_path"` LDAP LDAPConfig `json:"ldap"` JWTSecret string `json:"jwt_secret"` ListenAddr string `json:"listen_addr"` } type LDAPConfig struct { Url string `json:"url"` AdminUser string `json:"admin_user"` AdminPass string `json:"admin_pass"` } // ErrRequireSetup is returned when config is missing or empty, // signalling that the frontend should start the Setup Wizard. var ErrRequireSetup = errors.New("REQUIRE_SETUP") func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { if errors.Is(err, os.ErrNotExist) { return nil, ErrRequireSetup } return nil, err } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { return nil, err } if cfg.StoragePath == "" || cfg.JWTSecret == "" { return nil, ErrRequireSetup } if cfg.ListenAddr == "" { cfg.ListenAddr = ":4000" } // Default DB path to the dedicated db volume so it can be backed up // independently of the wiki content. if cfg.DBPath == "" { cfg.DBPath = "/data/db/archivum.db" } return &cfg, nil } func Save(path string, cfg *Config) error { data, err := json.MarshalIndent(cfg, "", " ") if err != nil { return err } return os.WriteFile(path, data, 0600) }