Files
Olaf Berberich 29a2886402 Initial commit: Disaster recovery CLI tool
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>
2025-12-08 00:31:27 +00:00

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
}