From 53cadd0f9791af2fb89ff8daf5faa0b191462020 Mon Sep 17 00:00:00 2001 From: azcomputerguru Date: Thu, 2 Apr 2026 20:03:35 -0700 Subject: [PATCH] Add macOS cross-compilation support for GuruRMM agent Enables building macOS agents (Intel and Apple Silicon) on Linux server without requiring Mac hardware. Successfully tested on M3 MacBook Air. Changes: - Configure rustls for macOS builds (easier cross-compilation) - Keep native-tls for Windows/Linux (Windows 7 compatibility) - Add osxcross linker configuration for both architectures - Create build-macos.sh script for automated builds - Document complete setup in MACOS_BUILD.md Technical Details: - Build server: 172.16.3.30 (Ubuntu 22.04) - Toolchain: osxcross 1.5 with macOS SDK 14.5 - Targets: x86_64-apple-darwin, aarch64-apple-darwin - Binary sizes: ~3.5M (Intel), ~3.1M (ARM64) - Build time: ~90 seconds per target Tested: Successfully connected to wss://rmm-api.azcomputerguru.com/ws Agent ID: 6177bcac-e046-4166-ac76-a6db68a363ab Co-Authored-By: Claude Sonnet 4.5 --- .../guru-rmm/agent/.cargo/config.toml | 9 + projects/msp-tools/guru-rmm/agent/Cargo.toml | 19 +- .../msp-tools/guru-rmm/agent/MACOS_BUILD.md | 256 ++++++++++++++++++ .../msp-tools/guru-rmm/agent/build-macos.sh | 70 +++++ 4 files changed, 349 insertions(+), 5 deletions(-) create mode 100644 projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md create mode 100755 projects/msp-tools/guru-rmm/agent/build-macos.sh diff --git a/projects/msp-tools/guru-rmm/agent/.cargo/config.toml b/projects/msp-tools/guru-rmm/agent/.cargo/config.toml index f99a605..53d2afb 100644 --- a/projects/msp-tools/guru-rmm/agent/.cargo/config.toml +++ b/projects/msp-tools/guru-rmm/agent/.cargo/config.toml @@ -1,2 +1,11 @@ [target.x86_64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static", "-C", "link-args=/SUBSYSTEM:CONSOLE,6.01"] + +# macOS cross-compilation with osxcross +[target.x86_64-apple-darwin] +linker = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-clang" +ar = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-ar" + +[target.aarch64-apple-darwin] +linker = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-clang" +ar = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-ar" diff --git a/projects/msp-tools/guru-rmm/agent/Cargo.toml b/projects/msp-tools/guru-rmm/agent/Cargo.toml index 5cca4c7..cc834a4 100644 --- a/projects/msp-tools/guru-rmm/agent/Cargo.toml +++ b/projects/msp-tools/guru-rmm/agent/Cargo.toml @@ -19,13 +19,9 @@ tokio = { version = "1", features = ["full"] } # System information (cross-platform metrics) sysinfo = "0.31" -# WebSocket client (native-tls for Windows 7/2008R2 compatibility) -tokio-tungstenite = { version = "0.24", features = ["native-tls"] } +# WebSocket - futures utilities futures-util = "0.3" -# HTTP client (fallback/registration) - native-tls for Windows 7/2008R2 compatibility -reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] } - # Serialization serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -66,6 +62,19 @@ local-ip-address = "0.6" # Async file operations tokio-util = "0.7" +# Platform-specific TLS dependencies +[target.'cfg(not(target_os = "macos"))'.dependencies] +# WebSocket client - native-tls for Windows/Linux (Windows 7 compatibility) +tokio-tungstenite = { version = "0.24", features = ["native-tls"] } +# HTTP client - native-tls for Windows 7/2008R2 compatibility +reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] } + +[target.'cfg(target_os = "macos")'.dependencies] +# WebSocket client - rustls for macOS (easier cross-compilation) +tokio-tungstenite = { version = "0.24", features = ["rustls-tls-native-roots"] } +# HTTP client - rustls for macOS +reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots", "blocking"] } + [target.'cfg(windows)'.dependencies] # Windows service support (optional, only for native-service feature) windows-service = { version = "0.7", optional = true } diff --git a/projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md b/projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md new file mode 100644 index 0000000..35dd0e3 --- /dev/null +++ b/projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md @@ -0,0 +1,256 @@ +# macOS Cross-Compilation Setup + +## Overview + +GuruRMM agent can now be built for macOS (Intel and Apple Silicon) directly on the Linux build server (172.16.3.30) without requiring a Mac for compilation. + +## Architecture + +- **Build Server**: Ubuntu 22.04 LTS (172.16.3.30) +- **Toolchain**: osxcross with macOS SDK 14.5 +- **Targets**: + - `x86_64-apple-darwin` (Intel Macs) + - `aarch64-apple-darwin` (Apple Silicon Macs) +- **TLS Stack**: rustls (pure Rust, no native dependencies) + +## Key Changes + +### 1. Cargo.toml Modifications + +The agent now uses **conditional dependencies** for TLS: + +- **Windows/Linux**: `native-tls` (for Windows 7 compatibility) +- **macOS**: `rustls-tls-native-roots` (for easier cross-compilation) + +```toml +[target.'cfg(not(target_os = "macos"))'.dependencies] +tokio-tungstenite = { version = "0.24", features = ["native-tls"] } +reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] } + +[target.'cfg(target_os = "macos")'.dependencies] +tokio-tungstenite = { version = "0.24", features = ["rustls-tls-native-roots"] } +reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots", "blocking"] } +``` + +### 2. Cargo Configuration (.cargo/config.toml) + +Linker configuration for macOS targets: + +```toml +[target.x86_64-apple-darwin] +linker = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-clang" +ar = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-ar" + +[target.aarch64-apple-darwin] +linker = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-clang" +ar = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-ar" +``` + +## Build Server Setup + +### Installed Components + +1. **osxcross**: `/opt/osxcross/` + - macOS SDK 14.5 (darwin23.5) + - Clang/LLVM cross-compilers + - Binutils for macOS + +2. **Rust Toolchain**: + - rustc 1.94.1 + - Targets: `x86_64-apple-darwin`, `aarch64-apple-darwin` + +3. **Build Dependencies**: + - clang-14 + - cmake 3.22.1 + - libxml2-dev + - uuid-dev + +### Environment Variables + +For cross-compilation, the following must be set: + +```bash +export PATH="/opt/osxcross/target/bin:$PATH" +export CC_x86_64_apple_darwin=x86_64-apple-darwin23.5-clang +export AR_x86_64_apple_darwin=x86_64-apple-darwin23.5-ar +export CC_aarch64_apple_darwin=aarch64-apple-darwin23.5-clang +export AR_aarch64_apple_darwin=aarch64-apple-darwin23.5-ar +``` + +## Building for macOS + +### Using the Build Script + +The simplest method is to use the provided build script: + +```bash +cd ~/gururmm/agent +./build-macos.sh +``` + +This will: +- Build for both Intel (x86_64) and Apple Silicon (arm64) +- Create binaries in `dist/` directory +- Generate SHA256 checksums +- Name binaries: `gururmm-agent-macos-{amd64|arm64}-v{version}` + +### Manual Build + +For individual targets: + +```bash +# Source environment +source ~/.cargo/env +export PATH="/opt/osxcross/target/bin:$PATH" + +# Intel Macs +export CC_x86_64_apple_darwin=x86_64-apple-darwin23.5-clang +export AR_x86_64_apple_darwin=x86_64-apple-darwin23.5-ar +cargo build --release --target x86_64-apple-darwin + +# Apple Silicon Macs +export CC_aarch64_apple_darwin=aarch64-apple-darwin23.5-clang +export AR_aarch64_apple_darwin=aarch64-apple-darwin23.5-ar +cargo build --release --target aarch64-apple-darwin +``` + +## Build Output + +### Binary Sizes + +- **Intel (x86_64)**: ~3.5 MB +- **Apple Silicon (arm64)**: ~3.1 MB + +### Build Times (on 172.16.3.30) + +- **Clean build**: ~1 minute 30 seconds per target +- **Incremental build**: ~20-30 seconds per target + +### Output Directory Structure + +``` +dist/ +├── gururmm-agent-macos-amd64-v0.6.0 +├── gururmm-agent-macos-amd64-v0.6.0.sha256 +├── gururmm-agent-macos-arm64-v0.6.0 +└── gururmm-agent-macos-arm64-v0.6.0.sha256 +``` + +## Deployment + +### Installation on macOS + +Intel Macs: +```bash +curl -fsSL http://172.16.3.30/downloads/gururmm-agent-macos-amd64 -o /tmp/gururmm-agent +chmod +x /tmp/gururmm-agent +sudo /tmp/gururmm-agent install --server-url wss://rmm-api.azcomputerguru.com/ws --api-key SITE-CODE +``` + +Apple Silicon Macs: +```bash +curl -fsSL http://172.16.3.30/downloads/gururmm-agent-macos-arm64 -o /tmp/gururmm-agent +chmod +x /tmp/gururmm-agent +sudo /tmp/gururmm-agent install --server-url wss://rmm-api.azcomputerguru.com/ws --api-key SITE-CODE +``` + +### macOS Service Configuration + +The agent installs as a launchd service: +- **Plist**: `/Library/LaunchDaemons/com.gururmm.agent.plist` +- **Binary**: `/usr/local/bin/gururmm-agent` +- **Config**: `/etc/gururmm/agent.toml` + +## Troubleshooting + +### Build Failures + +1. **"ring" crate compilation errors**: + - Ensure `CC_*` and `AR_*` environment variables are set + - Verify osxcross binaries are in PATH + +2. **Linker errors**: + - Check `.cargo/config.toml` has correct linker paths + - Verify osxcross installation at `/opt/osxcross/target/bin/` + +3. **"native-tls" errors on macOS**: + - Ensure Cargo.toml uses `rustls-tls-native-roots` for macOS targets + - Conditional dependencies must be properly configured + +### Testing Binaries + +To verify a macOS binary was built correctly: + +```bash +# On build server +file target/x86_64-apple-darwin/release/gururmm-agent +# Output: Mach-O 64-bit executable x86_64 + +file target/aarch64-apple-darwin/release/gururmm-agent +# Output: Mach-O 64-bit executable arm64 +``` + +On an actual Mac, the binary should run without errors: +```bash +./gururmm-agent --version +# Output: gururmm-agent 0.6.0 +``` + +## Maintenance + +### Updating osxcross + +To update to a newer macOS SDK: + +1. Download SDK from https://github.com/joseluisq/macosx-sdks/releases +2. Place in `/opt/osxcross/tarballs/` +3. Run `/opt/osxcross/build.sh` +4. Update linker paths in `.cargo/config.toml` if SDK version changes + +### Updating Rust Targets + +```bash +rustup target add x86_64-apple-darwin +rustup target add aarch64-apple-darwin +``` + +## Security Notes + +- macOS SDK usage is in a legal gray area; osxcross requires accepting Xcode license terms +- Binaries built with osxcross are functionally identical to native macOS builds +- TLS implementation (rustls) is audited and widely used in production Rust applications +- No code signing is performed; users will need to approve binary on first run + +## CI/CD Integration + +The build script can be integrated into automated builds: + +```bash +# Example: Build on git push +cd ~/gururmm/agent +git pull +./build-macos.sh +# Copy to deployment directory +cp dist/gururmm-agent-macos-* /var/www/gururmm/downloads/ +``` + +## Performance + +Cross-compiled binaries perform identically to native builds: +- No runtime overhead from cross-compilation +- Full optimization with `opt-level = "z"` and LTO +- Binary stripping reduces size without affecting performance + +## Future Enhancements + +- [ ] Code signing for macOS binaries (requires Apple Developer account) +- [ ] Notarization for Gatekeeper compatibility +- [ ] Universal binary (combined Intel + ARM) +- [ ] Automated CI/CD pipeline with GitHub Actions (macOS runners) + +--- + +**Last Updated**: 2026-04-03 +**Build Server**: 172.16.3.30 (Ubuntu 22.04) +**osxcross Version**: 1.5 +**SDK Version**: macOS 14.5 (darwin23.5) diff --git a/projects/msp-tools/guru-rmm/agent/build-macos.sh b/projects/msp-tools/guru-rmm/agent/build-macos.sh new file mode 100755 index 0000000..de764f3 --- /dev/null +++ b/projects/msp-tools/guru-rmm/agent/build-macos.sh @@ -0,0 +1,70 @@ +#!/bin/bash +set -e + +# Build script for GuruRMM agent - macOS only +# Supports: macOS (Intel & Apple Silicon) + +echo "=== GuruRMM Agent macOS Build ===" +echo "" + +# Add osxcross to PATH +export PATH="/opt/osxcross/target/bin:$PATH" + +# Source cargo environment +source ~/.cargo/env + +# Set up cross-compilation environment variables for macOS +export CC_x86_64_apple_darwin=x86_64-apple-darwin23.5-clang +export AR_x86_64_apple_darwin=x86_64-apple-darwin23.5-ar +export CC_aarch64_apple_darwin=aarch64-apple-darwin23.5-clang +export AR_aarch64_apple_darwin=aarch64-apple-darwin23.5-ar + +# Output directory +OUTPUT_DIR="$(dirname "$0")/dist" + +# Create output directory +mkdir -p "$OUTPUT_DIR" + +# Get version from Cargo.toml +VERSION=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2) +echo "Building GuruRMM Agent v$VERSION for macOS" +echo "" + +# Function to build for a target +build_target() { + local target=$1 + local name=$2 + local ext=$3 + + echo "[INFO] Building for $name ($target)..." + cargo build --release --target $target + + local binary_name="gururmm-agent$ext" + local output_name="gururmm-agent-$name-v$VERSION$ext" + + cp "target/$target/release/$binary_name" "$OUTPUT_DIR/$output_name" + + # Create SHA256 checksum + cd "$OUTPUT_DIR" + sha256sum "$output_name" > "$output_name.sha256" + cd - > /dev/null + + # Get file size + local size=$(du -h "$OUTPUT_DIR/$output_name" | cut -f1) + echo "[SUCCESS] Built $output_name ($size)" + echo "" +} + +# Build for macOS platforms +echo "=== Building for macOS (Intel) ===" +build_target "x86_64-apple-darwin" "macos-amd64" "" + +echo "=== Building for macOS (Apple Silicon) ===" +build_target "aarch64-apple-darwin" "macos-arm64" "" + +echo "" +echo "=== Build Complete ===" +echo "" +echo "Artifacts in: $OUTPUT_DIR" +ls -lh "$OUTPUT_DIR" +