Skip to content

Conversation

@l50
Copy link
Contributor

@l50 l50 commented Sep 10, 2025

Added:

  • Introduced macOS (Darwin) support for installing and managing Alloy, including a dedicated setup-Darwin.yml task file leveraging Homebrew for package management and service control (as per https://grafana.com/docs/alloy/latest/set-up/install/macos/)
  • Added macOS-specific handler to restart Alloy using Homebrew services
  • Defined Darwin-specific variables in vars/Darwin.yml for Homebrew tap, package, and default config path
  • Updated role metadata to declare macOS platform support

Changed:

  • Updated documentation to mention macOS as a supported OS and specify Homebrew and community.general requirements
  • Modified deployment tasks to conditionally execute Linux-specific logic only on RedHat and Debian families, and add macOS-specific verification and setup
  • Adjusted handler logic to include macOS restart handler
  • Improved uninstall logic to stop Alloy and remove config on macOS, and uninstall via Homebrew when appropriate

**Added:**

- Introduced macOS (Darwin) support for installing and managing Alloy, including
  a dedicated `setup-Darwin.yml` task file leveraging Homebrew for package
  management and service control
- Added macOS-specific handler to restart Alloy using Homebrew services
- Defined Darwin-specific variables in `vars/Darwin.yml` for Homebrew tap,
  package, and default config path
- Updated role metadata to declare macOS platform support

**Changed:**

- Updated documentation to mention macOS as a supported OS and specify
  Homebrew and `community.general` requirements
- Modified deployment tasks to conditionally execute Linux-specific logic only
  on RedHat and Debian families, and add macOS-specific verification and setup
- Adjusted handler logic to include macOS restart handler
- Improved uninstall logic to stop Alloy and remove config on macOS, and
  uninstall via Homebrew when appropriate
@CLAassistant
Copy link

CLAassistant commented Sep 10, 2025

CLA assistant check
All committers have signed the CLA.

@voidquark
Copy link
Collaborator

Thanks for contributing and adding macOS support! I'm not a macOS user myself, so I can’t fully test it, but I did take the time to review your PR.

From my perspective, it’s safe to merge since it doesn’t affect Debian/Ubuntu/RHEL deployment or uninstallation. I also tested it on those systems, and everything continues to work as expected.

Before we merge, could you please update setup-Darwin.yml to use __ as a prefix for all registered variables?

l50 added 2 commits September 12, 2025 16:32
**Changed:**

- Updated all Ansible register and fact variable names in the Alloy macOS setup
  task to use a double underscore prefix for consistency and to avoid naming
  conflicts
- Changed the default value for `__alloy_config_path_default` to reference
  `__brew_prefix.stdout` instead of `brew_prefix.stdout` in Darwin-specific
  variables for consistency with task variable naming
- Refactored logic throughout the Alloy Darwin setup to use the new variable
  names in all conditions, paths, and debug statements for clarity and
  maintainability
@l50
Copy link
Contributor Author

l50 commented Sep 12, 2025

Before we merge, could you please update setup-Darwin.yml to use __ as a prefix for all registered variables?

Sure thing, done!

@l50
Copy link
Contributor Author

l50 commented Sep 12, 2025

Thanks for contributing and adding macOS support! I'm not a macOS user myself, so I can’t fully test it, but I did take the time to review your PR.

If it helps, here's the relevant snippet from the playbook I use:

---
- name: Workstation
  hosts: all
  roles:
    # Set up logging first to ensure log directories exist for other roles
    - name: Configure logging and log rotation
      role: cowdogmoo.workstation.logging
      # For debugging
      # role: ../../roles/logging
      vars:
        logging_directories:
          - path: "~/ansible-logs"
            mode: "0755"
            owner: "{{ ansible_user_id }}"
            group: "{{ ansible_user_gid | default(ansible_user_id) }}"
          - path: "~/ansible-logs/hosts"  # For log_plays callback
            mode: "0755"
            owner: "{{ ansible_user_id }}"
            group: "{{ ansible_user_gid | default(ansible_user_id) }}"

        logging_rotation_configs:
          - name: "ansible-hosts"
            path: "~/ansible-logs/hosts/*"
            rotate: 30
            frequency: "daily"
            compress: true
            missingok: true
            notifempty: true
            create: true
            dateext: true
            maxsize: "100M"
            copytruncate: true
            delaycompress: true
            owner: "{{ ansible_user_id }}"
            group: "{{ ansible_user_gid | default(ansible_user_id) }}"

        # Optional: Override default LaunchAgent settings for macOS
        logging_launchagent_label: "com.ansible.logrotate"
        logging_logrotate_log_path: "{{ ansible_env.HOME }}/ansible-logs/logrotate"

    # Install and configure Alloy for log shipping to Loki
    # This should come after logging setup to ensure directories exist
    - name: Install and configure Grafana Alloy
      role: grafana.grafana.alloy
      vars:
        # Alloy configuration for log collection and shipping to Loki
        alloy_config: |
          // Enable debug logging to help troubleshoot
          logging {
            level  = "debug"
            format = "logfmt"
          }

          // Discover and read all non-compressed host log files
          local.file_match "ansible_logs" {
            path_targets = [{
              __path__ = env("HOME") + "/ansible-logs/hosts/*",
              job      = "ansible",
              environment = "local",
            }]
            sync_period = "10s"
          }

          // Read logs from the discovered files
          loki.source.file "ansible" {
            targets    = local.file_match.ansible_logs.targets
            forward_to = [loki.process.ansible.receiver]

            // Start reading from the beginning to catch existing logs
            tail_from_end = false
          }

          // Process logs and extract hostname from filename
          loki.process "ansible" {
            // Extract the hostname from the file path
            stage.regex {
              expression = ".*/hosts/(?P<extracted_hostname>[^/]+)$"
              source     = "filename"
            }

            // Drop logs from compressed files (files containing .gz)
            stage.match {
              selector = `{filename=~".*\\.gz.*"}`
              action   = "drop"
            }

            // Check if it's a localhost file and create a flag
            stage.regex {
              expression = "^(?P<is_localhost>localhost(-[0-9]+)?)$"
              source     = "extracted_hostname"
            }

            // Use template to set the final hostname
            // If is_localhost exists (matches localhost pattern), use constants.hostname
            // Otherwise use the extracted_hostname
            stage.template {
              source   = "final_hostname"
              template = `{{"{{ if .is_localhost }}"}}` + constants.hostname + `{{"{{ else }}"}}{{ "{{" }} .extracted_hostname {{ "}}" }}{{"{{ end }}"}}`
            }

            // Add the processed hostname as labels
            stage.labels {
              values = {
                host   = "final_hostname",
                source = "final_hostname",
              }
            }

            // Add static labels
            stage.static_labels {
              values = {
                application  = "ansible",
                environment  = "local",
                service_name = "ansible",
              }
            }
            forward_to = [loki.write.remote.receiver]
          }

          // Send logs to Loki
          loki.write "remote" {
            endpoint {
              url = "https://loki.techvomit.xyz/loki/api/v1/push"
            }
          }

and the output from running it:

TASK [grafana.grafana.alloy : Include OS specific variables] ***********************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:04 -0600 (0:00:00.012)       0:00:03.072 ******

TASK [grafana.grafana.alloy : Preflight] *******************************************************************************************
included: /Users/l/.ansible/collections/ansible_collections/grafana/grafana/roles/alloy/tasks/preflight.yml for localhost
Friday 12 September 2025  16:35:04 -0600 (0:00:00.014)       0:00:03.086 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.014)       0:00:03.101 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.016)       0:00:03.118 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.022)       0:00:03.140 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.016)       0:00:03.157 ******

TASK [grafana.grafana.alloy : Deploy Alloy service] ********************************************************************************
included: /Users/l/.ansible/collections/ansible_collections/grafana/grafana/roles/alloy/tasks/deploy.yml for localhost
Friday 12 September 2025  16:35:04 -0600 (0:00:00.025)       0:00:03.182 ******

TASK [grafana.grafana.alloy : Scrape Github API endpoint to obtain latest Alloy version] *******************************************
ok: [localhost]
Friday 12 September 2025  16:35:04 -0600 (0:00:00.627)       0:00:03.809 ******

TASK [grafana.grafana.alloy : Latest available Alloy version] **********************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:04 -0600 (0:00:00.015)       0:00:03.825 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.010)       0:00:03.835 ******
Friday 12 September 2025  16:35:04 -0600 (0:00:00.010)       0:00:03.846 ******

TASK [grafana.grafana.alloy : Check if Alloy is installed via Homebrew] ************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:01.117)       0:00:04.964 ******

TASK [grafana.grafana.alloy : Extract current Alloy version on macOS] **************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:00.015)       0:00:04.979 ******
Friday 12 September 2025  16:35:06 -0600 (0:00:00.011)       0:00:04.991 ******
Friday 12 September 2025  16:35:06 -0600 (0:00:00.011)       0:00:05.003 ******

TASK [grafana.grafana.alloy : Include macOS/Darwin setup] **************************************************************************
included: /Users/l/.ansible/collections/ansible_collections/grafana/grafana/roles/alloy/tasks/setup-Darwin.yml for localhost
Friday 12 September 2025  16:35:06 -0600 (0:00:00.024)       0:00:05.027 ******

TASK [grafana.grafana.alloy : Check if Homebrew is installed] **********************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:00.196)       0:00:05.224 ******
Friday 12 September 2025  16:35:06 -0600 (0:00:00.011)       0:00:05.236 ******

TASK [grafana.grafana.alloy : Get Homebrew prefix] *********************************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:00.250)       0:00:05.486 ******

TASK [grafana.grafana.alloy : Set Alloy config directory path] *********************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:00.017)       0:00:05.504 ******

TASK [grafana.grafana.alloy : Add Grafana tap to Homebrew] *************************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:06 -0600 (0:00:00.335)       0:00:05.839 ******

TASK [grafana.grafana.alloy : Install Alloy via Homebrew] **************************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:10 -0600 (0:00:03.753)       0:00:09.592 ******

TASK [grafana.grafana.alloy : Ensure Alloy config directory exists] ****************************************************************
changed: [localhost]
Friday 12 September 2025  16:35:10 -0600 (0:00:00.190)       0:00:09.783 ******

TASK [grafana.grafana.alloy : Template Alloy config] *******************************************************************************
changed: [localhost]
Friday 12 September 2025  16:35:11 -0600 (0:00:00.384)       0:00:10.168 ******

TASK [grafana.grafana.alloy : Check if Alloy service is loaded] ********************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:12 -0600 (0:00:01.454)       0:00:11.622 ******

TASK [grafana.grafana.alloy : Stop Alloy service if it exists (to clean up any issues)] ********************************************
changed: [localhost]
Friday 12 September 2025  16:35:14 -0600 (0:00:01.800)       0:00:13.423 ******

TASK [grafana.grafana.alloy : Start Alloy service with sudo (for first-time setup)] ************************************************
ok: [localhost]
Friday 12 September 2025  16:35:14 -0600 (0:00:00.084)       0:00:13.507 ******
Friday 12 September 2025  16:35:14 -0600 (0:00:00.015)       0:00:13.523 ******

TASK [grafana.grafana.alloy : Restart Alloy service if already running] ************************************************************
changed: [localhost]
Friday 12 September 2025  16:35:15 -0600 (0:00:01.046)       0:00:14.569 ******

TASK [grafana.grafana.alloy : Check final service status] **************************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:17 -0600 (0:00:01.458)       0:00:16.027 ******

TASK [grafana.grafana.alloy : Verify Alloy installation] ***************************************************************************
ok: [localhost]
Friday 12 September 2025  16:35:17 -0600 (0:00:00.248)       0:00:16.276 ******

TASK [grafana.grafana.alloy : Display Alloy version] *******************************************************************************
ok: [localhost] =>
    msg: |-
        Alloy version: alloy, version v1.10.1 (branch: HEAD, revision: unknown)
          build user:       grafana
          build date:       2025-08-07T08:12:40Z
          go version:       go1.24.7
          platform:         darwin/arm64
          tags:             builtinassets,noebpf
Friday 12 September 2025  16:35:17 -0600 (0:00:00.015)       0:00:16.291 ******

TASK [grafana.grafana.alloy : Display service status] ******************************************************************************
ok: [localhost] =>
    msg: 'Alloy service status: [''alloy     started         l    ~/Library/LaunchAgents/homebrew.mxcl.alloy.plist'']'
Friday 12 September 2025  16:35:17 -0600 (0:00:00.019)       0:00:16.310 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.018)       0:00:16.329 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.015)       0:00:16.344 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.011)       0:00:16.355 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.018)       0:00:16.373 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.016)       0:00:16.390 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.010)       0:00:16.400 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.012)       0:00:16.413 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.012)       0:00:16.425 ******
Friday 12 September 2025  16:35:17 -0600 (0:00:00.002)       0:00:16.427 ******

RUNNING HANDLER [grafana.grafana.alloy : Restart alloy macos] **********************************************************************
changed: [localhost]
Friday 12 September 2025  16:35:19 -0600 (0:00:01.767)       0:00:18.195 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.012)       0:00:18.207 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.013)       0:00:18.221 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.014)       0:00:18.235 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.011)       0:00:18.247 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.012)       0:00:18.259 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.014)       0:00:18.274 ******
Friday 12 September 2025  16:35:19 -0600 (0:00:00.015)       0:00:18.289 ******
...

TASKS RECAP ************************************************************************************************************************
Friday 12 September 2025  16:35:31 -0600 (0:00:00.012)       0:00:30.091 ******
===============================================================================
grafana.grafana.alloy : Install Alloy via Homebrew -------------------------------------------------------------------------- 3.75s
grafana.grafana.alloy : Stop Alloy service if it exists (to clean up any issues) -------------------------------------------- 1.80s
grafana.grafana.alloy : Restart alloy macos --------------------------------------------------------------------------------- 1.77s
grafana.grafana.alloy : Check final service status -------------------------------------------------------------------------- 1.46s
grafana.grafana.alloy : Check if Alloy service is loaded -------------------------------------------------------------------- 1.45s
grafana.grafana.alloy : Check if Alloy is installed via Homebrew ------------------------------------------------------------ 1.12s
grafana.grafana.alloy : Restart Alloy service if already running ------------------------------------------------------------ 1.05s
grafana.grafana.alloy : Scrape Github API endpoint to obtain latest Alloy version ------------------------------------------- 0.63s
grafana.grafana.alloy : Template Alloy config ------------------------------------------------------------------------------- 0.38s

@l50
Copy link
Contributor Author

l50 commented Sep 12, 2025

Thanks for contributing and adding macOS support!

Of course! I started to write it into one of my collections and quickly realized there was probably an existing collection that I could update instead.

**Changed:**

- Consolidated Alloy service start tasks into a single step, removing redundant
  sudo logic and user-level distinction to streamline service management
- Updated service start and restart steps to use explicit return code checks for
  failure detection, improving error handling consistency
- Simplified conditional logic to reduce complexity in service start and restart
  operations on Darwin systems

**Removed:**

- Eliminated separate sudo-based service start task and related conditionals to
  avoid unnecessary privilege escalation and duplication
@voidquark voidquark merged commit cdd9a2e into grafana:main Sep 16, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants