Install on macOS
Native binaries for both Intel and Apple Silicon. Ferrum Edge was benchmarked on Apple Silicon — expect excellent performance.
Download, Verify, and Install the Binary
Pick the block that matches your Mac and run it in an empty directory. uname -m prints arm64 on Apple Silicon and x86_64 on Intel. Each block also clears the Gatekeeper quarantine flag that macOS adds to files downloaded through a browser.
ASSET=ferrum-edge-macos-aarch64
BASE=https://github.com/ferrum-edge/ferrum-edge/releases/download/v0.9.10
curl -fsSLO "$BASE/$ASSET" &&
curl -fsSLO "$BASE/$ASSET.sha256" &&
shasum -a 256 -c "$ASSET.sha256" &&
(xattr -d com.apple.quarantine "$ASSET" 2>/dev/null || true) &&
sudo install -d -m 0755 /usr/local/bin &&
sudo install -m 0755 "$ASSET" /usr/local/bin/ferrum-edge &&
/usr/local/bin/ferrum-edge version
# Expected: ferrum-edge-macos-aarch64: OK
# ferrum-edge 0.9.10 (aarch64-apple-darwin)
ASSET=ferrum-edge-macos-x86_64
BASE=https://github.com/ferrum-edge/ferrum-edge/releases/download/v0.9.10
curl -fsSLO "$BASE/$ASSET" &&
curl -fsSLO "$BASE/$ASSET.sha256" &&
shasum -a 256 -c "$ASSET.sha256" &&
(xattr -d com.apple.quarantine "$ASSET" 2>/dev/null || true) &&
sudo install -d -m 0755 /usr/local/bin &&
sudo install -m 0755 "$ASSET" /usr/local/bin/ferrum-edge &&
/usr/local/bin/ferrum-edge version
# Expected: ferrum-edge-macos-x86_64: OK
# ferrum-edge 0.9.10 (x86_64-apple-darwin)
&&, so a failed download or a checksum mismatch stops the block before anything is installed, and the final version line does not run. If shasum prints FAILED, delete both files and download again; do not install that binary. The version check calls /usr/local/bin/ferrum-edge by full path so an older copy elsewhere on your PATH cannot answer for it.
Create a Configuration File
This sample proxies /api to a backend on localhost:3000; step 3 starts a throwaway backend there.
mkdir -p ~/.ferrum
cat > ~/.ferrum/config.yaml << 'EOF'
version: "1"
proxies:
- id: "local-api"
listen_path: "/api"
backend_scheme: http
backend_host: "localhost"
backend_port: 3000
strip_listen_path: true
plugins:
- plugin_config_id: "cors-dev"
- plugin_config_id: "log-stdout"
plugin_configs:
- id: "cors-dev"
plugin_name: "cors"
scope: proxy
proxy_id: local-api
enabled: true
config:
allowed_origins: ["http://localhost:3001", "http://localhost:5173"]
allowed_methods: [GET, POST, PUT, DELETE, OPTIONS]
allowed_headers: [Content-Type, Authorization]
- id: "log-stdout"
plugin_name: "stdout_logging"
scope: proxy
proxy_id: local-api
enabled: true
config: {}
EOF
Start Ferrum Edge and Send a First Request
ferrum-edge run stays in the foreground, so the walkthrough uses three terminals: one for a test backend, one for the gateway, and one for the checks. Any HTTP server on port 3000 works as the backend; Python's built-in server is used because macOS ships python3 with the Xcode Command Line Tools.
mkdir -p /tmp/ferrum-backend && cd /tmp/ferrum-backend &&
echo 'hello from the backend' > index.html &&
python3 -m http.server 3000 --bind 127.0.0.1
# Leave this running. Expected: Serving HTTP on 127.0.0.1 port 3000 ...
ferrum-edge validate --spec ~/.ferrum/config.yaml &&
ferrum-edge run --spec ~/.ferrum/config.yaml -v
# Leave this running. If validate fails, fix the config before continuing.
# 1. Gateway liveness on the admin listener (no auth).
curl -fsS http://localhost:9000/live; echo
# Expected: {"status":"ok"}
# 2. A real proxied request: /api is stripped and forwarded to the backend.
curl -sS -i http://localhost:8000/api/
# Expected: HTTP/1.1 200 OK ... followed by: hello from the backend
502 with an X-Gateway-Error header, the gateway is alive but cannot reach the backend; look at Terminal A. A passing liveness check alone does not prove that proxying works, so do not continue to the launchd section until both checks pass. Stop the backend and gateway with Ctrl+C when you are done.
Run as a Background Service (launchd)
On macOS, use launchd to run Ferrum Edge as a user-level background service that starts automatically on login.
<?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>com.ferrumedge</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/ferrum-edge</string>
<string>run</string>
<string>--spec</string>
<string>/Users/YOUR_USER/.ferrum/config.yaml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/ferrum-edge.log</string>
<key>StandardErrorPath</key>
<string>/tmp/ferrum-edge-error.log</string>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/com.ferrumedge.plist
launchctl start com.ferrumedge
Build from Source
# Install Rust via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
# Install protoc via Homebrew
brew install protobuf
# Clone and build
git clone https://github.com/ferrum-edge/ferrum-edge.git
cd ferrum-edge
git checkout v0.9.10
./scripts/install-build-deps.sh
cargo build --release
# Install
sudo cp target/release/ferrum-edge /usr/local/bin/