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>
This commit is contained in:
88
internal/config/config.go
Normal file
88
internal/config/config.go
Normal file
@@ -0,0 +1,88 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user