A Go-based CLI tool for recovering servers from backups to new cloud VMs. Features: - Multi-cloud support: Exoscale, Cloudscale, Hetzner Cloud - Backup sources: Local filesystem, Hetzner Storage Box - 6-stage restore pipeline with /etc whitelist protection - DNS migration with safety checks and auto-rollback - Dry-run by default, requires --yes to execute - Cloud-init for SSH key injection Packages: - cmd/recover-server: CLI commands (recover, migrate-dns, list, cleanup) - internal/providers: Cloud provider implementations - internal/backup: Backup source implementations - internal/restore: 6-stage restore pipeline - internal/dns: Exoscale DNS management - internal/ui: Prompts, progress, dry-run display - internal/config: Environment and host configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Config holds all configuration values
|
|
type Config struct {
|
|
// Exoscale
|
|
ExoscaleAPIKey string
|
|
ExoscaleAPISecret string
|
|
|
|
// Cloudscale
|
|
CloudscaleAPIToken string
|
|
|
|
// Hetzner Cloud
|
|
HetznerAPIKey string
|
|
|
|
// Hetzner Storage Box (for backups)
|
|
HetznerStorageBoxUser string
|
|
HetznerStorageBoxHost string
|
|
|
|
// Local backup path
|
|
LocalBackupPath string
|
|
}
|
|
|
|
var cfg *Config
|
|
|
|
// Load reads configuration from .env file
|
|
func Load(envFile string) error {
|
|
if envFile != "" {
|
|
if err := godotenv.Load(envFile); err != nil {
|
|
// Not fatal - env vars might be set directly
|
|
fmt.Fprintf(os.Stderr, "Warning: could not load %s: %v\n", envFile, err)
|
|
}
|
|
}
|
|
|
|
cfg = &Config{
|
|
ExoscaleAPIKey: os.Getenv("EXOSCALE_API_KEY"),
|
|
ExoscaleAPISecret: os.Getenv("EXOSCALE_API_SECRET"),
|
|
CloudscaleAPIToken: os.Getenv("CLOUDSCALE_API_TOKEN"),
|
|
HetznerAPIKey: os.Getenv("HETZNER_API_KEY"),
|
|
HetznerStorageBoxUser: getEnvDefault("HETZNER_STORAGEBOX_USER", "u480813"),
|
|
HetznerStorageBoxHost: getEnvDefault("HETZNER_STORAGEBOX_HOST", "u480813.your-storagebox.de"),
|
|
LocalBackupPath: getEnvDefault("LOCAL_BACKUP_PATH", "/srv/backups"),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Get returns the current configuration
|
|
func Get() *Config {
|
|
if cfg == nil {
|
|
cfg = &Config{}
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
// Validate checks required credentials for a provider
|
|
func (c *Config) ValidateProvider(provider string) error {
|
|
switch provider {
|
|
case "exoscale":
|
|
if c.ExoscaleAPIKey == "" || c.ExoscaleAPISecret == "" {
|
|
return fmt.Errorf("EXOSCALE_API_KEY and EXOSCALE_API_SECRET required")
|
|
}
|
|
case "cloudscale":
|
|
if c.CloudscaleAPIToken == "" {
|
|
return fmt.Errorf("CLOUDSCALE_API_TOKEN required")
|
|
}
|
|
case "hetzner":
|
|
if c.HetznerAPIKey == "" {
|
|
return fmt.Errorf("HETZNER_API_KEY required")
|
|
}
|
|
default:
|
|
return fmt.Errorf("unknown provider: %s", provider)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getEnvDefault(key, defaultVal string) string {
|
|
if val := os.Getenv(key); val != "" {
|
|
return val
|
|
}
|
|
return defaultVal
|
|
}
|