1package config
  2
  3import (
  4	"path/filepath"
  5
  6	"github.com/caarlos0/env/v6"
  7	"github.com/charmbracelet/log"
  8	"github.com/charmbracelet/soft-serve/server/backend"
  9	"github.com/charmbracelet/soft-serve/server/backend/file"
 10)
 11
 12// SSHConfig is the configuration for the SSH server.
 13type SSHConfig struct {
 14	// ListenAddr is the address on which the SSH server will listen.
 15	ListenAddr string `env:"LISTEN_ADDR" envDefault:":23231"`
 16
 17	// PublicURL is the public URL of the SSH server.
 18	PublicURL string `env:"PUBLIC_URL" envDefault:"ssh://localhost:23231"`
 19
 20	// KeyPath is the path to the SSH server's private key.
 21	KeyPath string `env:"KEY_PATH"`
 22
 23	// MaxTimeout is the maximum number of seconds a connection can take.
 24	MaxTimeout int `env:"MAX_TIMEOUT" envDefault:"0"`
 25
 26	// IdleTimeout is the number of seconds a connection can be idle before it is closed.
 27	IdleTimeout int `env:"IDLE_TIMEOUT" envDefault:"120"`
 28}
 29
 30// GitConfig is the Git daemon configuration for the server.
 31type GitConfig struct {
 32	// ListenAddr is the address on which the Git daemon will listen.
 33	ListenAddr string `env:"LISTEN_ADDR" envDefault:":9418"`
 34
 35	// MaxTimeout is the maximum number of seconds a connection can take.
 36	MaxTimeout int `env:"MAX_TIMEOUT" envDefault:"0"`
 37
 38	// IdleTimeout is the number of seconds a connection can be idle before it is closed.
 39	IdleTimeout int `env:"IDLE_TIMEOUT" envDefault:"3"`
 40
 41	// MaxConnections is the maximum number of concurrent connections.
 42	MaxConnections int `env:"MAX_CONNECTIONS" envDefault:"32"`
 43}
 44
 45// HTTPConfig is the HTTP configuration for the server.
 46type HTTPConfig struct {
 47	// ListenAddr is the address on which the HTTP server will listen.
 48	ListenAddr string `env:"LISTEN_ADDR" envDefault:":8080"`
 49
 50	// PublicURL is the public URL of the HTTP server.
 51	PublicURL string `env:"PUBLIC_URL" envDefault:"http://localhost:8080"`
 52}
 53
 54// Config is the configuration for Soft Serve.
 55type Config struct {
 56	// Name is the name of the server.
 57	Name string `env:"NAME" envDefault:"Soft Serve"`
 58
 59	// SSH is the configuration for the SSH server.
 60	SSH SSHConfig `envPrefix:"SSH_"`
 61
 62	// Git is the configuration for the Git daemon.
 63	Git GitConfig `envPrefix:"GIT_"`
 64
 65	// HTTP is the configuration for the HTTP server.
 66	HTTP HTTPConfig `envPrefix:"HTTP_"`
 67
 68	// InitialAdminKeys is a list of public keys that will be added to the list of admins.
 69	InitialAdminKeys []string `env:"INITIAL_ADMIN_KEY" envSeparator:"\n"`
 70
 71	// DataPath is the path to the directory where Soft Serve will store its data.
 72	DataPath string `env:"DATA_PATH" envDefault:"data"`
 73
 74	// Backend is the Git backend to use.
 75	Backend backend.Backend
 76
 77	// Access is the access control backend to use.
 78	Access backend.AccessMethod
 79}
 80
 81// DefaultConfig returns a Config with the values populated with the defaults
 82// or specified environment variables.
 83func DefaultConfig() *Config {
 84	cfg := &Config{}
 85	if err := env.Parse(cfg, env.Options{
 86		Prefix: "SOFT_SERVE_",
 87	}); err != nil {
 88		log.Fatal(err)
 89	}
 90	if cfg.SSH.KeyPath == "" {
 91		cfg.SSH.KeyPath = filepath.Join(cfg.DataPath, "ssh", "soft_serve")
 92	}
 93	fb, err := file.NewFileBackend(cfg.DataPath)
 94	if err != nil {
 95		log.Fatal(err)
 96	}
 97	// Add the initial admin keys to the list of admins.
 98	fb.AdditionalAdmins = cfg.InitialAdminKeys
 99	return cfg.WithBackend(fb).WithAccessMethod(fb)
100}
101
102// WithBackend sets the backend for the configuration.
103func (c *Config) WithBackend(backend backend.Backend) *Config {
104	c.Backend = backend
105	return c
106}
107
108// WithAccessMethod sets the access control method for the configuration.
109func (c *Config) WithAccessMethod(access backend.AccessMethod) *Config {
110	c.Access = access
111	return c
112}