# macOS

> A Mac with Apple silicon, through Alloy run by launchd. Sends the Mac's CPU, memory, disks and network. In beta.

> **Beta**: These steps work, but have been tried less than the others.


These are the steps the **Connect** page shows in the portal, at [telopi.com/app](https://telopi.com/app), where your values are filled in. Here they are placeholders:

- `<INGEST_URL>`: your ingest address, on the portal's home page and on its **Connect** page.
- `<USERNAME>`: the username of an ingest key, on the portal's **Ingest keys** page, or, if your Grafana takes one ingest login rather than keys, the login's username on **Connect**. Use one key for each place that sends, so you can replace one without touching the others.
- `<ENVIRONMENT>`: a name you choose for this environment, such as `production`: lower-case letters, digits, `.`, `_` and `-`. Your dashboards group by it.

Your ingest key's password is never in the code: a step that needs it asks for it when it runs.

## 1. Install and start Alloy

Run this in Terminal, as a user that may use sudo, and paste your ingest key's password when it asks: it is not shown, and it goes in no command, so not in your shell's history. It downloads Alloy's binary for Apple silicon from Grafana's releases to /usr/local/bin, writes its configuration and the password to /usr/local/etc/telopi, which only root reads, and a launchd daemon, com.telopi.alloy, and starts it. Run it again to change the configuration or the password.

```bash
sudo bash -s <<'TELOPI'
set -euo pipefail

# The password, from the terminal: it goes in no command.
read -rsp "Ingest key password: " TELOPI_PASSWORD </dev/tty
echo

# Alloy's standalone binary for Apple silicon.
mkdir -p /usr/local/bin /usr/local/etc/telopi /usr/local/var/lib/telopi-alloy /usr/local/var/log
cd "$(mktemp -d)"
curl -fsSLO https://github.com/grafana/alloy/releases/download/v1.20.0/alloy-darwin-arm64.zip
unzip -oq alloy-darwin-arm64.zip
install -m 755 alloy-darwin-arm64 /usr/local/bin/alloy

# The configuration and the password: only root, which runs Alloy, reads them.
chmod 700 /usr/local/etc/telopi
cat > /usr/local/etc/telopi/config.alloy <<'ALLOY'
// Machines: CPU, load, memory, disks and network of the machine Alloy runs
// on, through Alloy's unix exporter, sent to your Telopi stack every minute.
// Run one Alloy per machine. The password is your ingest key's, read from
// the environment variable TELOPI_PASSWORD.

prometheus.exporter.unix "machines" {
  // In a container, TELOPI_ROOTFS is where the host's / is mounted, so the
  // disks are the host's; unset, as on a machine itself, it is /.
  rootfs_path = coalesce(sys.env("TELOPI_ROOTFS"), "/")
}

prometheus.scrape "machines" {
  targets         = prometheus.exporter.unix.machines.targets
  scrape_interval = "60s"
  forward_to      = [prometheus.remote_write.machines.receiver]
}

prometheus.remote_write "machines" {
  // The environment's name: the Machines dashboard and its alerts group by it.
  external_labels = {
    cluster = "<ENVIRONMENT>",
  }

  endpoint {
    url = "<INGEST_URL>/mimir/api/v1/push"

    basic_auth {
      username = "<USERNAME>"
      password = sys.env("TELOPI_PASSWORD")
    }
  }
}
ALLOY
touch /usr/local/etc/telopi/alloy.env
chmod 600 /usr/local/etc/telopi/alloy.env
printf "TELOPI_PASSWORD='%s'\n" "$TELOPI_PASSWORD" > /usr/local/etc/telopi/alloy.env

# The daemon has no secret: its shell reads the password's file, then runs Alloy.
plist=/Library/LaunchDaemons/com.telopi.alloy.plist
cat > "$plist" <<'PLIST'
<?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.telopi.alloy</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/sh</string>
    <string>-c</string>
    <string>set -a; . /usr/local/etc/telopi/alloy.env; exec /usr/local/bin/alloy run --storage.path=/usr/local/var/lib/telopi-alloy /usr/local/etc/telopi/config.alloy</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>StandardOutPath</key>
  <string>/usr/local/var/log/telopi-alloy.log</string>
  <key>StandardErrorPath</key>
  <string>/usr/local/var/log/telopi-alloy.log</string>
</dict>
</plist>
PLIST

launchctl bootout system/com.telopi.alloy 2>/dev/null || true
launchctl bootstrap system "$plist"
TELOPI
```

## 2. Check that it arrived

Alloy should be running and log no error. Within two minutes Connect in the portal says Receiving data, and the Machines dashboard in your Grafana fills; macOS has fewer counters than Linux, so some of its panels stay empty. A 401 in the log is a wrong username or password.

```bash
sudo launchctl print system/com.telopi.alloy | grep -E "^\s+state = "
sudo tail -n 200 /usr/local/var/log/telopi-alloy.log | grep -E "level=error|HTTP status 40[13]" || echo "No errors in the last lines of the log."
```

## More

- [[object Object]]([object Object]): [object Object]
