package app import "strings" func writeTransportSystemdProvisionUnits( client TransportClient, in transportSystemdProvisionInputs, ) *transportBackendActionResult { if transportSystemdSingBoxUsesTemplateInstance(client, in.unit) { if err := writeTransportSingBoxTemplateArtifacts(client, in); err != nil { res := transportBackendActionResult{ OK: false, Code: "TRANSPORT_BACKEND_PROVISION_FAILED", Message: "write singbox template/drop-in failed: " + err.Error(), ExitCode: -1, } return &res } return nil } primaryUnitContent := renderTransportSystemdUnit( client, in.unit, in.primaryCmd, in.sshOverlay, in.sshUnit, in.primaryTuning, in.primaryHardening, ) if err := writeTransportSystemdUnitFile(in.unit, primaryUnitContent); err != nil { res := transportBackendActionResult{ OK: false, Code: "TRANSPORT_BACKEND_PROVISION_FAILED", Message: "write primary unit failed: " + err.Error(), ExitCode: -1, } return &res } if in.sshOverlay { sshUnitContent := renderTransportSSHOverlayUnit(client, in.sshUnit, in.sshCmd, in.sshTuning, in.sshHardening) if err := writeTransportSystemdUnitFile(in.sshUnit, sshUnitContent); err != nil { res := transportBackendActionResult{ OK: false, Code: "TRANSPORT_BACKEND_PROVISION_FAILED", Message: "write ssh unit failed: " + err.Error(), ExitCode: -1, } return &res } } return nil } func finalizeTransportSystemdProvision( client TransportClient, in transportSystemdProvisionInputs, preOut []string, preErr []string, ) transportBackendActionResult { out := make([]string, 0, 4+len(preOut)) errOut := make([]string, 0, 4+len(preErr)) out = append(out, preOut...) errOut = append(errOut, preErr...) stdout, stderr, code, err := transportRunCommand(transportBackendActionTimeout, "systemctl", "daemon-reload") if s := strings.TrimSpace(stdout); s != "" { out = append(out, s) } if s := strings.TrimSpace(stderr); s != "" { errOut = append(errOut, s) } if err != nil || code != 0 { return transportBackendActionResult{ OK: false, Code: "TRANSPORT_BACKEND_PROVISION_FAILED", Message: "systemctl daemon-reload failed", ExitCode: code, Stdout: strings.Join(out, "\n"), Stderr: strings.Join(errOut, "\n"), } } if transportConfigBool(client.Config, "enable_on_boot") { units := []string{in.unit} if in.sshOverlay { units = []string{in.sshUnit, in.unit} } for _, u := range units { stdout, stderr, code, err = transportRunCommand(transportBackendActionTimeout, "systemctl", "enable", u) if s := strings.TrimSpace(stdout); s != "" { out = append(out, s) } if s := strings.TrimSpace(stderr); s != "" { errOut = append(errOut, s) } if err != nil || code != 0 { return transportBackendActionResult{ OK: false, Code: "TRANSPORT_BACKEND_PROVISION_FAILED", Message: "systemctl enable failed for " + u, ExitCode: code, Stdout: strings.Join(out, "\n"), Stderr: strings.Join(errOut, "\n"), Retryable: true, } } } } msg := "provision done: " + in.unit if in.sshOverlay { msg += " + " + in.sshUnit } if in.cmdSource != "" { msg += " [" + in.cmdSource + "]" } return transportBackendActionResult{ OK: true, ExitCode: 0, Message: msg, Stdout: strings.Join(out, "\n"), Stderr: strings.Join(errOut, "\n"), } }