package main import ( "context" "log" "os" "os/signal" "runtime" "syscall" "time" "github.com/kelseyhightower/envconfig" "github.com/vigilcyber/corrosion-companion/internal/app" "github.com/vigilcyber/corrosion-companion/internal/client" ) // Config holds all environment-based configuration type Config struct { // NATS connection NATSUrl string `envconfig:"NATS_URL" required:"true"` NATSToken string `envconfig:"NATS_TOKEN" required:"true"` // License identification LicenseID string `envconfig:"LICENSE_ID" required:"true"` // Game server configuration SteamCMDPath string `envconfig:"STEAMCMD_PATH" default:"/usr/games/steamcmd"` GameServerPath string `envconfig:"GAME_SERVER_PATH" default:""` GameServerArgs string `envconfig:"GAME_SERVER_ARGS" default:"-batchmode"` // Install directory for deployment InstallDir string `envconfig:"INSTALL_DIR" default:""` // Optional settings HeartbeatInterval int `envconfig:"HEARTBEAT_INTERVAL" default:"60"` LogLevel string `envconfig:"LOG_LEVEL" default:"info"` } var version = "dev" func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.Printf("Corrosion Companion Agent v%s starting...", version) // Load configuration from environment var cfg Config if err := envconfig.Process("", &cfg); err != nil { log.Fatalf("Failed to load configuration: %v", err) } // Set default InstallDir based on OS if not configured if cfg.InstallDir == "" { if runtime.GOOS == "windows" { cfg.InstallDir = `C:\RustServer` } else { cfg.InstallDir = "/opt/rustserver" } } log.Printf("Configuration loaded:") log.Printf(" NATS URL: %s", cfg.NATSUrl) log.Printf(" License ID: %s", cfg.LicenseID) log.Printf(" Game Server Path: %s", cfg.GameServerPath) log.Printf(" SteamCMD Path: %s", cfg.SteamCMDPath) log.Printf(" Install Dir: %s", cfg.InstallDir) log.Printf(" Heartbeat Interval: %ds", cfg.HeartbeatInterval) // Create context with signal handling for graceful shutdown ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() // Connect to NATS log.Println("Connecting to NATS...") nc, err := client.Connect(cfg.NATSUrl, cfg.NATSToken) if err != nil { log.Fatalf("Failed to connect to NATS: %v", err) } defer nc.Close() log.Println("NATS connection established") // Initialize daemon configuration daemonCfg := &app.DaemonConfig{ LicenseID: cfg.LicenseID, HeartbeatInterval: time.Duration(cfg.HeartbeatInterval) * time.Second, SteamCMDPath: cfg.SteamCMDPath, GameServerPath: cfg.GameServerPath, GameServerArgs: cfg.GameServerArgs, Version: version, InstallDir: cfg.InstallDir, } // Start daemon daemon, err := app.NewDaemon(nc, daemonCfg) if err != nil { log.Fatalf("Failed to initialize daemon: %v", err) } log.Println("Daemon initialized, starting main loop...") // Run daemon until context is cancelled if err := daemon.Run(ctx); err != nil { log.Fatalf("Daemon error: %v", err) } log.Println("Companion agent shutdown complete") }