MOK's Onomatomaniske Kaos
Super Cool

Welcome to my pages! What I will be posting here is mainly notes I’ve made to myself, cleaned up a bit for public consumption. Mainly focused on Linux and programming.

Latest blog post

Install Arch Linux from scratch on Mac mini


This is a description of how I installed Arch on my Mac mini (ultimo 2012) that I purchased very cheaply refurbished. This machine has 16 Gb of RAM and 128 Gb SSD and it was expensive when it was first purchased. It is not possible to upgrade this machine past macOS Catalina, but with Linux the support will continue forever, and this little computer can continue to run a modern, fully secure and updated operating system.

Before I had fun doing this, I actually installed Linux Mint 21 on the same hardware, it took around 10 minutes and everything worked including wifi after using Mint’s driver manager to install the driver, which it found automatically. However, I wanted to try to install Linux on btrfs subvolumes and that is why I started this project. I will need this machine for teaching installation of Linux, so I will wipe the Arch installation again soon, but I had fun doing this, and perhaps I’ll repeat this installation when the teaching is done.. I installed Arch several years ago on a different machine, but I can comfort you by saying that it’s still a lot of work 😬.

A few things in this document is specific to Macmini6,1, notably the things related to the wireless interface, otherwise you can probably use most of the following for any computer.

1 Flashing a USB stick

Always use the most recent ISO image from the Arch Linux download site, otherwise you are very likely to get into problems later.

I first put the Arch ISO on my Ventoy disk, but when I got to the stage of creating the grub installation I ran into a problem because apparently efivars was not active on archiso. I assume this is because the image is booted by Ventoy and not by UEFI on the Mac. Anyway, when later booted directly from a USB stick, the problem went away.

2 Set terminal font size and keyboard layout

I am using my TV as display, so I need to increase the font size. I also need to change the keyboard layout. The layout codes can be listed using localectl list-keymaps.

setfont -d
loadkeys dk

3 Connecting to WiFi

The wireless interface on the Mac mini (“Macmini6,1”) is a BCM 4331 chip which is not by default supported by archiso. I could find the interface using:

lspci -nn -d 14e4:

but when looking at the net interfaces using ip link, only the loop and wired interfaces were show. When booting, archiso tells you to go to this link, but this is the correct one. After a lot of web searching, trial and error and many reboots I found that I need to blacklist the b43 driver and load wl which is on archiso from the start.

modprobe -r b43 wl
modprobe wl
systemctl restart iwd

iwctl now shows the device wlan0, and I am back to the normal tutorials. However, ip link shows the device in the state UNKNOWN.

The next step is to run wpa_supplicant. First I generated a wpa_supplicant.conf file:

wpa_passphrase Kanhavehus2 "Elvin&Enzo" > wpa_supplicant.conf

then I ran this command from the wiki:

wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf

After this I need to restart dhcp:

dhcpcd wlan0

Now the system received an IP address from my DHCP server and ip link shows wlan0 as UP, and I can ping 192.168.2.1.

4 Create partitions

Now the network is up, so I can continue by creating partition. Not going into details with this, but these are the partitions I created:

  • /dev/sda1 300 Mb FAT32
  • /dev/sda2 8 Gb swap
  • /dev/sda3 111 Gb btrfs

The final partition /dev/sda3 is simply the remaining free space on the 128 Gb SSD that came with the Mac mini.

Many guides tell you to use zramswap instead of having a swap partition, but I am old fashioned and I want a swap area outside btrfs, and disk space is much cheaper than RAM space.

You could create an additional 4 Gb ext4 partition for /boot but here I am creating a @boot subvolume for that. You want /boot to be isolated from / in order to create snapshots that don’t create problems when restoring. In fact, I’ve often thought about unmounting /boot once the system is running since you don’t need it (except when updating grub).

5 Create the btrfs main file system

I want to use btrfs subvolumes so the setup becomes a bit involved and confusing. Basically the btrfs main file system can be thought of as an LVM volume group that you put logical volumes on. Having a granular set of subvolumes enables you to use snapshots in a rational way, but contrary to LVM, the subvolumes all share the total device space with the advantages and disadvantages that entails: You can make use of all available disk space, but if one of the subvolumes fills up, like for example your $HOME, the whole system locks up.

The first thing to do is to create all the subvolumes I want. /dev/sda3 is already formatted as a btrfs volume using mkfs.btrfs, so just mount it:

mount /dev/sda3 /mnt

Now create subvolumes:

btrfs subvolume create @         # for /
btrfs subvolume create @boot     # for /boot
btrfs subvolume create @varlog   # for /var/log
btrfs subvolume create @cache    # for /var/cache
btrfs subvolume create @home     # for /home

The reason to keep /var/log and /var/cache in separate subvolumes is again when restoring / from a snapshot, the system retains logs etc. and in addtion, the files in these areas are constantly updated with information and would take up disk space in the snapshot.

Now, unmount /dev/sda3 and remount the root subvolume (@):

umount /dev/sda3
 mount -o rw,noatime,space_cache=v2,compress=zstd,ssd,discard=async,subvol=@ /dev/sda2 /mnt

Create all the mount points needed:

mkdir /mnt/home
mkdir -p /boot/efi
mkdir -p /var/log
mkdir -p /var/cache

and mount all the subvolumes. I found that you actually don’t need to include all the options above, it will work fine with this:

mount /dev/sda3 -o  -o compress=zstd,subvol=@ /mnt
mount /dev/sda3 -o  -o compress=zstd,subvol=@boot /mnt/boot
mount /dev/sda3 -o  -o compress=zstd,subvol=@home /mnt/home
mount /dev/sda3 -o  -o compress=zstd,subvol=@varlog /mnt/var/log
mount /dev/sda3 -o  -o compress=zstd,subvol=@cache /mnt/var/cache

Finally mount the efi partition:

mount /sda1 /mnt/boot/efi

Now we have the naked directory structure needed to install a Linux system mounted on /mnt.

TIP

I had to boot from archiso many times, and every time it has forgotten everything, except the filesystems we have generated on /dev/sda3. I created a few small shell scripts that I store on a second USB stick, and it can be mounted while in archiso environment, and I could then copy the scripts from the USB stick to the local /root. Fortunately the Mac mini has 4 USB ports to it’s possible to connect 2 USB sticks, a keyboard and a mouse.

6 Preparing for the Arch installation environment

Before doing pacstrap it’s a good idea to refresh the signing keys, especially if your install image is not brand new, the signing keys of the Arch devs seem to expire all the time. This operation might take quite a while.

pacman-key --refresh-keys

7 Bootstrapping a basic Linux system

Now that we have our partitions mounted, let’s install the set of base packages for Arch. I suppose you could use debootstrap if creating a Debian installation instead of Arch.

pacstrap -i /mnt base

8 Enter the chroot environment

There is nothing else we need to do in the archiso environment right now, so we switch root to the newly bootstrapped Linux system:

cd /root
arch-chroot /mnt

9 Mount the swap partition

Next step is creating and mounting the swap partion in our new Linux system. As seen above I created an 8 Gb partition for swap, now activate it:

mkswap /dev/sda2
swapon /dev/sda2

10 Generate an fstab file

Now we have all subvolumes plus swap mounted, so generate an /etc/fstab file to save all this information for the next boot:

Generate an fstab and place it in /etc:

genfstab -U > /etc/fstab

The -U switch prompts genfstab to output UUIDs instead of device names that might change. Inspect the /etc/fstab file to check that all the information is correct, and that all our partitions are listed in the file.

11 Set zoneinfo and hostname

Just set the timezone, it’s also possible to wait and do it via the Cosmic settings, but we might as well do it now we’re here:

ln -s /usr/share/zoneinfo/Europe/Copenhagen /etc/localtime

Set the hostname, I name it after the monster Grendel:

cat "grendel" > /etc/hostname

We also need to define the hostname in /etc/hosts, from here it will be recognized by the local network, thanks to mDNS (avahi_daemon) that we installed above.

cat << EOF > /etc/hosts
127.0.0.1 localhost
::1       localhost
127.0.1.1 grendel
EOF

12 User accounts

To protect the root account, set a password for it:

passwd

and I also create a user for myself:

useradd  --groups wheel,users --home-dir /home/mok --uid 1026 mok

Then, I set a password:

passwd mok

13 Install basic packages

Next step is to install basic packages:

pacman -S base-devel btrfs-progs grub efibootmgr mtools networkmanager openssh sudo acpid vim

14 Install Linux kernel

Install at least one kernel:

pacman -S linux linux-headers

and install firmware files:

pacman -S linux-firmware

The Mac mini has an Intel GPU, so I install mesa:

pacman -S mesa

15 More packages to install

More packages to install, in no particular order:

  • broadcom-wl (necessary for Mac mini)
  • git
  • dnsutils
  • inetutils
  • dnsutils
  • fastfetch
  • htop
  • btop
  • man-db
  • man-pages
  • pipewire
  • wireplumber
  • pipewire-alsa
  • pipewire-pulseaudio
  • fzf
  • zoxide
  • eza
  • bat
  • emacs
  • tmux
  • mosh
  • otf-monaspace-nerd
  • ttf-firacode-nerd
  • firefox

Copy/paste this list from here:

bat bind bluez broadcom-wl btop btrfs-progs chromium cmake
cosmic dnsutils emacs eza fastfetch firefox fzf git grub-btrfs htop
inetutils inotify-tools ipython linux linux-firmware linux-headers
man-db man-pages mosh openssh otf-monaspace-nerd pipewire pipewire-alsa
pipewire-pulse pipewire-pulseaudio reflector timeshift tmux
ttf-firacode-nerd wireplumber xdg-desktop-portal-cosmic zoxide
zsh

Many guides on the Internet talk about os-prober, but I don’t plan to add more operating systems so I am omitting it.

16 Install Cosmic desktop

Install the Cosmic desktop and enable it when booting

pacman -S cosmic

Note, cosmic is a meta package that will install around 20 other packages such as cosmic-greeter, cosmic-settings and cosmic-terminal. You can select to install all of them (recommended).

Next enable cosmic-greeter to present the login screen when booting next time.

systemctl enable cosmic-greeter

17 Enable ssh

I installed openssh so enable it to start up at boot time.

systemctl enable sshd --now

The --now switch tells systemd to start the service after enabling it for boot. At this point you should in fact be able to ssh into the new machine from another computer.

18 Generate kernel ramdisks

Generate the intial Linux image to boot:

mkinitcpio -p linux

19 Set up GRUB

Install GRUB:

grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck

and generate a config file for GRUB:

grub-mkconfig -o /boot/grub/grub.cfg

20 Other services to start

Enable NetworkManager so networking will function when you reboot:

systemctl enable NetworkManager

acpid for power management:

systemctl enable acpid

next, systemd-resolved for DNS resolution and avahi-daemon for name resolution on your local network (mDNS):

systemctl enable systemd-resolved
systemctl enable avahi-daemon

Enable bluetooth

systemctl enable bluetooth

Enable boot from timeshift snapshots. You will have to configure this system later. Check out manuals and YouTube videos for guides. I find that Timeshift does not open a window on Wayland, btw.

systemctl enable grub-btrfs

For the sound system to work, enable everything pipewire:

systemctl enable pipewire-pulse
systemctl enable pipewire
systemctl enable wireplumber.service

That’s it for now. Once the newly installed system boots, there will be opportunity to enable other services if needed.

21 Update the pacman mirrorlist

Let’s just update the list of pacman mirrors to be the fastest I can access:

reflector --country DK --latest 10 --sort rate --save /etc/pacman.d/mirrorlist

22 Blacklist the b43 driver

Important!

The Macmini6,1 wireless interface needs the wl kernel module that we installed above in the broadcom-wl package. But we need to prevent the b43 module from starting, otherwise wifi won’t work. Create a file in /etc/modprobe.d/ called blacklist.conf:

echo "blacklist b43" > /etc/modprobe.d/blacklist.conf

23 Wrapping Up

Exit our chroot environment:

exit

Now we are back on archiso. Unmount all partitions and reboot.

umount -R /mnt
reboot

If you are lucky, the system will boot up in the Cosmic greeter. Otherwise, back to the drawing board.

Screenshot of terminal with fastfetch output