Installing GitLab on an Apple silicon-based Mac

Posted on Feb 17, 2025

I use an M2 Pro MacBook Pro for my day-to-day development work. It’s a fantastic computer, and the vast majority of the tooling I use for my job is available natively for Apple silicon and Just Works™ like it would on my previous Intel Macs. However, there are still times when I run into issues where a particular tool I need is only available as an x86_64 binary that doesn’t quite work in Rosetta, and I have to resort to workarounds.

For a project at work, I needed a local GitLab CE instance to test some integrations for a proof-of-concept, and didn’t want to incur any cost by spinning up infrastructure to host it. My first thought would be to use Docker, and indeed there are officially-published Docker images for GitLab CE, but there’s no arm64 images (the only available images are x86_64). I tried running the official images using Rosetta 2, but found the performance to be unacceptable.

There are a few community-provided arm64 images for GitLab, but they’re in various states of inactivity, and I’d prefer to use the officially-provided GitLab builds to reduce the likelihood of a supply-chain attack.

Finding myself at an impasse, I decided to try creating a virtual machine using an arm64-based Linux distribution, then installing GitLab into that VM. It’s not an ideal solution compared to doing it in Docker, requiring much more setup work, but by this point I’d already wasted enough time trying to get GitLab up and running in Docker and in the absence of any other (free) options, it felt like the best choice.

Creating the Virtual Machine

I decided to use the following software:

  • UTM (as the virtualisation software - essentially just a frontend for QEMU)
  • Ubuntu Server for ARM (the guest operating system in the VM, also a supported target for GitLab’s arm64 builds)

GitLab needs at least 4GB RAM to perform correctly, so make sure to assign at least this much memory to the virtual machine.

If your Mac has less than 16GB RAM, you might want to install GitLab on a separate computer instead to get acceptable performance while still leaving macOS enough memory to work with.

The actual Ubuntu Server installation was quite straightforward, and I accepted most of the default options during the install wizard, making sure to enable the OpenSSH server to make administering the VM and installing GitLab easier.

Get the VM’s IP address

Once Ubuntu Server is installed, log in on the console, and type ip addr show enp0s1. You should see something resembling the following output:

2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 96:97:7e:09:c8:4a brd ff:ff:ff:ff:ff:ff
    inet 192.168.64.14/24 metric 100 brd 192.168.64.255 scope global dynamic enp0s1
       valid_lft 3214sec preferred_lft 3214sec
    inet6 fdfa:dbd0:d542:f954:9497:7eff:fe09:c84a/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591920sec preferred_lft 604720sec
    inet6 fe80::9497:7eff:fe09:c84a/64 scope link
       valid_lft forever preferred_lft forever

Look for the IP address (under inet) - in this example, the VM’s IP address is 192.168.64.14. This IP address is accessible from your macOS host, and will be used to SSH into the VM and install GitLab.

Optional: Assign a DNS name to the VM

This section requires you to have root access to your Mac. You can skip this step if e.g. you’re on a corporate device without a local administrator account.

For convenience, I assigned a DNS name to my virtual machine, so I don’t have to remember the IP address every time I want to access GitLab or SSH into the machine. This also makes life easier if the IP address ever changes, as GitLab would otherwise need to be reconfigured to use the new IP address for URL redirects.

I used gitlab.local to avoid conflicting with any real top-level domains, but you can use something else if you’d prefer. Either way, I used this command on my Mac to add an entry to the /etc/hosts file (making sure to replace the IP address and DNS name according to my setup):

echo "192.168.64.14 gitlab.local" | sudo tee -a /etc/hosts

Post-install Housekeeping

At this point, I SSH’d into the VM:

# Replace `gitlab.local` with the VM's hostname or IP address, depending whether you followed the last step
ssh my-user@gitlab.local

Then I made sure Ubuntu Server had the latest package updates, as well as any dependencies needed to install GitLab:

sudo apt update
sudo apt upgrade
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl

Installing GitLab

First, I used the official GitLab convenience script to add the GitLab CE apt repository:

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

For security reasons, never run any commands that pipe untrusted input into your shell without first inspecting the output - not doing so could potentially allow a bad actor to compromise your device. In this case, you can use the curl command on its own without piping it to bash to make sure the script is doing what you expect it to.

The official GitLab script may seem like a safe source, but you should never discount the possibility that GitLab’s CDN has been compromised, or that you are subject to a man-in-the-middle attack - this has happened before to other open-source projects.

Then, I installed the official gitlab-ce package (which installs and configures all of the other dependencies, like postgresql, for you):

sudo apt update

# Replace the value of EXTERNAL_URL with the VM's DNS name or IP address
sudo EXTERNAL_URL="http://gitlab.local" apt install gitlab-ce

The initial installation might take a while, depending on the speed of your Internet connection - the GitLab package is quite large, and there’s a lot of configuration to do beforehand.

Once the installation is done, I grabbed the initial root password:

sudo cat /etc/gitlab/initial_root_password

Finally, I was able to open my web browser, navigate to the DNS name of my virtual machine (in this case, http://gitlab.local), and I was greeted by the GitLab login page. I used the initial root password to log in as root, then changed the password and created a separate non-root user account to use for development purposes - from this point onwards, it worked just like a normal GitLab CE installation.

Final Thoughts

I’ve been using this testing setup for a couple of weeks now, and while it’s not quite as handy as using Docker, it works well enough for my purposes while performing noticeably better than the x86_64 Docker images running in Rosetta.

When finished with the VM, it’s important to remember to shut it down cleanly (SSH in and use sudo shutdown) - saving the machine state can cause the system time to get out of sync, which causes all manner of timekeeping issues with GitLab.

A Call for Feedback

As an aside, this is my first time blogging since… *checks notes*… 2019! I’m open to any feedback you might have about the layout of this site, my writing style, or anything else you think works/could be improved upon.