Run Azure Self-hosted macOS Agents on Apple M1 Mac

Part-1: Use M1 Mac to power your own iOS CI/CD pipelines

Soumya Mahunt
ITNEXT

--

Azure pipeline background

Releasing ARM-based M1 chip in November of last year, Apple has made clear its intentions of eventually dropping support for Intel-based machines. M1 powered machines have been proven to be more performant and efficient than Intel-based machines, as of now, the only way to leverage this performance in Microsoft Azure’s DevOps CI/CD pipelines is to use self-hosted agents.

In this post, we will walk through the process of using an M1-based machine for self-hosted agents to improve existing pipeline(s) performance and efficiency. If you are using GitHub actions you can follow through with part-2 of this series.

Generate a personal access token

Before you begin, you’ll need to generate a personal access token (PAT) for a user with adequate permissions within your Azure DevOps organization. For the scope select Agent Pools (read, manage) and make sure all the other boxes are cleared. If it’s a deployment group agent, for the scope select Deployment group (read, manage) and make sure all the other boxes are cleared. You can select Show all scopes at the bottom of the window to see the complete list of possible scopes to set permissions for.

NOTE: At a minimum, the PAT will need read and manage permissions for Agent Pools scope. You’ll need to copy the PAT when the hash is generated for later use, as it will only be available to view after generated and it won’t be displayed again after this step.

Download and configure the agent

Within your Azure DevOps project, you’ll need to either select an existing agent pool to add your M1-based machine to or you can create a new one. To do so, navigate to Project Settings or Organization Settings on the left sidebar of the Azure DevOps portal, depending on whether you want to add an agent to the project or organization level respectively.

Next, either select or create the agent pool you intend to use for your iOS or macOS CI/CD workflow by first clicking Agent pools in the left sidebar and then clicking New agent as shown below.

Then, you’ll need to download the agent onto your M1 agent by clicking Download as shown in the below screenshot.

After that, you’ll then simply need to run the provided commands on your M1 machine to configure and start the agent, please refer to the above screenshot.

NOTE: if you have not yet done so, you should install Rosetta 2 on your Apple M1 machine and install System prerequisites.

Configure and run the Azure DevOps Agent interactively

After extracting the agent into a newly-created directory, you’ll need to run ./config.sh, as shown above, to associate the agent with your organization in Azure DevOps.

When you do, you will see the following dialogue in the terminal:

First, to connect with your server, you will need to provide the server URL, which is https://dev.azure.com/{organization name}. Next, you can simply press Enter to select PAT as your authentication type, and then finally paste the PAT you collected earlier into the terminal when prompted.

Now to configure your agent, you need to provide the name of the agent pool to add your agent to and give a name to your agent. Next, you have to provide a work folder or accept the default choice _work.

And with that, you’ll be ready to start the interactive agent by running ./run.sh.

Confirming status

After starting the Azure DevOps self-hosted agent for macOS, you should see a “Listening for jobs” dialogue in the terminal. You should also see the new agent listed in the appropriate agent pool in the Azure UI, which will look like the following:

Now you can change the agent pool name for your pipeline to the M1-based machine pools and enjoy the improved pipeline performance:

Configure tool cache

Some Tool tasks (i.e. Use Ruby Version) require your tool cache already set up with required tools. You will find your tool cache in _tool directory inside your workFolder (default _work) you provided at the time of configuration. With homebrew, you can manage the different versions of these tools, and using the following python script you can link already installed tools to your _tool folder.

Sudoers configuration

If your tasks require root privileges, you can configure your sudoers file by typing sudo visudo. You can add the following line in this file to allow root privileges without prompting for a password, however, this is not advisable due to potential security risks:

your_username  ALL=(ALL) NOPASSWD: ALL

Alternatively, you can add restriction application level, so that these applications won’t require a password prompt. For example, default Tool Tasks require root privileges to create a symlink in system directories, in that case, you can add ln to no password prompt like this:

your_username  ALL= NOPASSWD: /bin/ln
# Or your additional applications with arguments:
your_username ALL= NOPASSWD: /bin/ln,/your_dir/your_bin your_args

--

--

Writer for

Senior Software Engineer at MoEngage | System architecture enthusiast | Ex Tataneu