b23ef64ee1
Generate a fresh ed25519 key pair at rebuild time, inject the public key into the Proxmox answer file, use the private key for cluster join over SSH, then remove the key from both the remote host and the database. This eliminates the need to manage static SSH keys in config/secrets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Config struct {
|
|
Server Server `yaml:"server"`
|
|
Database Database `yaml:"database"`
|
|
PXE PXE `yaml:"pxe"`
|
|
Images Images `yaml:"images"`
|
|
Proxmox Proxmox `yaml:"proxmox"`
|
|
Credentials Credentials `yaml:"credentials"`
|
|
Infrastructure Infrastructure `yaml:"infrastructure"`
|
|
Locks Locks `yaml:"locks"`
|
|
ServerTypePath string `yaml:"server_types_path"`
|
|
}
|
|
|
|
type Server struct {
|
|
Bind string `yaml:"bind"`
|
|
PublicURL string `yaml:"public_url"`
|
|
}
|
|
|
|
type Database struct {
|
|
Path string `yaml:"path"`
|
|
}
|
|
|
|
type PXE struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Interface string `yaml:"interface"`
|
|
Subnet string `yaml:"subnet"`
|
|
RuntimeDir string `yaml:"runtime_dir"`
|
|
TFTPRoot string `yaml:"tftp_root"`
|
|
DnsmasqBin string `yaml:"dnsmasq_bin"`
|
|
}
|
|
|
|
type Images struct {
|
|
Dir string `yaml:"dir"`
|
|
}
|
|
|
|
type Proxmox struct {
|
|
ExistingNode string `yaml:"existing_node"`
|
|
ClusterName string `yaml:"cluster_name"`
|
|
JoinFingerprint string `yaml:"join_fingerprint"`
|
|
}
|
|
|
|
type Credentials struct {
|
|
RootPasswordHash string `yaml:"root_password_hash"`
|
|
}
|
|
|
|
type Infrastructure struct {
|
|
BaseURL string `yaml:"base_url"`
|
|
RoomID int `yaml:"room_id"`
|
|
ServerTypeMap map[string]int `yaml:"server_type_map"`
|
|
TimeoutSec int `yaml:"timeout_seconds"`
|
|
}
|
|
|
|
type Locks struct {
|
|
TTLMinutes int `yaml:"ttl_minutes"`
|
|
}
|
|
|
|
func Load(path string) (*Config, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read config: %w", err)
|
|
}
|
|
cfg := &Config{}
|
|
if err := yaml.Unmarshal(data, cfg); err != nil {
|
|
return nil, fmt.Errorf("parse config: %w", err)
|
|
}
|
|
applyDefaults(cfg)
|
|
return cfg, nil
|
|
}
|
|
|
|
func applyDefaults(cfg *Config) {
|
|
if cfg.Server.Bind == "" {
|
|
cfg.Server.Bind = "0.0.0.0:8080"
|
|
}
|
|
if cfg.Database.Path == "" {
|
|
cfg.Database.Path = "./data/provisioning.db"
|
|
}
|
|
if cfg.PXE.RuntimeDir == "" {
|
|
cfg.PXE.RuntimeDir = "./data/pxe"
|
|
}
|
|
if cfg.PXE.TFTPRoot == "" {
|
|
cfg.PXE.TFTPRoot = "./data/tftp"
|
|
}
|
|
if cfg.PXE.DnsmasqBin == "" {
|
|
cfg.PXE.DnsmasqBin = "/usr/sbin/dnsmasq"
|
|
}
|
|
if cfg.Images.Dir == "" {
|
|
cfg.Images.Dir = "./data/images"
|
|
}
|
|
if cfg.Locks.TTLMinutes == 0 {
|
|
cfg.Locks.TTLMinutes = 60
|
|
}
|
|
if cfg.Infrastructure.TimeoutSec == 0 {
|
|
cfg.Infrastructure.TimeoutSec = 10
|
|
}
|
|
if cfg.ServerTypePath == "" {
|
|
cfg.ServerTypePath = "./server-types.yaml"
|
|
}
|
|
}
|