Arch on a MacBook

This was written in 2016. Much of it is out of date. Modern systems should use Wayland and libinput, not X11 and Synaptics.

This is what I did to put Arch Linux on my MacBook Pro 12,1 (A1502, 2015) with dm-crypt (LVM on LUKS). Much of the start is taken from this blog post, but it’s reproduced here because of fear of link-rot.

Here’s my hardware (from lspci).

00:00.0 Host bridge: Intel Corporation Broadwell-U Host Bridge -OPI (rev 09)
00:02.0 VGA compatible controller: Intel Corporation Broadwell-U Integrated Graphics (rev 09)
00:03.0 Audio device: Intel Corporation Broadwell-U Audio Controller (rev 09)
00:14.0 USB controller: Intel Corporation Wildcat Point-LP USB xHCI Controller (rev 03)
00:15.0 DMA controller: Intel Corporation Wildcat Point-LP Serial IO DMA Controller (rev 03)
00:15.4 Serial bus controller [0c80]: Intel Corporation Wildcat Point-LP Serial IO GSPI Controller #1 (rev 03)
00:16.0 Communication controller: Intel Corporation Wildcat Point-LP MEI Controller #1 (rev 03)
00:1b.0 Audio device: Intel Corporation Wildcat Point-LP High Definition Audio Controller (rev 03)
00:1c.0 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #1 (rev e3)
00:1c.1 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #2 (rev e3)
00:1c.2 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #3 (rev e3)
00:1c.4 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #5 (rev e3)
00:1c.5 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #6 (rev e3)
00:1f.0 ISA bridge: Intel Corporation Wildcat Point-LP LPC Controller (rev 03)
00:1f.3 SMBus: Intel Corporation Wildcat Point-LP SMBus Controller (rev 03)
00:1f.6 Signal processing controller: Intel Corporation Wildcat Point-LP Thermal Management Controller (rev 03)
02:00.0 Multimedia controller: Broadcom Corporation 720p FaceTime HD Camera
03:00.0 Network controller: Broadcom Corporation BCM43602 802.11ac Wireless LAN SoC (rev 01)
04:00.0 SATA controller: Samsung Electronics Co Ltd Device a801 (rev 01)
05:00.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
06:00.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
06:03.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
06:04.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
06:05.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
06:06.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
07:00.0 System peripheral: Intel Corporation DSL5520 Thunderbolt 2 NHI [Falcon Ridge 4C 2013]

This is the partition scheme we’ll end up with (45 GiB for OS X, 10 GiB for a shared HFS+ partition and the rest (~177.8 GiB) for a LVM container).

sudo gdisk -l /dev/sda
GPT fdisk (gdisk) version 1.0.1

Partition table scan:
  MBR: hybrid
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with hybrid MBR; using GPT.
Disk /dev/sda: 490234752 sectors, 233.8 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 490234718
Partitions will be aligned on 8-sector boundaries
Total free space is 262150 sectors (128.0 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              40          409639   200.0 MiB   EF00  EFI System Partition
   2          409640        94865191   45.0 GiB    AF05  Customer
   3        94865192        96134727   619.9 MiB   AB00  Recovery HD
   4        96396872       117368391   10.0 GiB    AF00  hfs
   5       117368392       490234718   177.8 GiB   8E00  archlinux

It’s probably a good idea to make a backup first. I didn’t because I like to live on the edge. You can boot into recovery mode later if you need to with + R.

OS X

Get an Arch image, verify it and burn it to a USB key with something like

dd if=archlinux-2016.05.01-dual.iso of=/dev/rdisk2 bs=4M && sync

where we use rdisk2 to write to the raw disk and skip some buffering. Use diskutil to figure out which disk to use.

Then resize the OS X partition and encrypt it with FileVault.

Arch Linux

Boot into Arch by holding the right alt key. To make the console font larger, use setfont sun12x22 (the biggest one on the system).

I had to set

echo 0 > /sys/module/hid_apple/parameters/iso_layout

to fix the keyboard layout, swapping ` and ~ with < and >. (See aw: Apple Keyboard.)

Then run timedatectl set-ntp true, connect to the internet and update.

Partitioning

Apple recommend leaving a 128 MiB gap between partitions.

We leave free space after each partition to make it easier for future system software to manipulate the partition map in ways that we can’t anticipate currently.

It’s debatable whether this is worthwhile.

With cgdisk:

It should look like this in the end.

Part. #     Size        Partition Type            Partition Name
----------------------------------------------------------------
            3.0 KiB     free space
   1        200.0 MiB   EFI System                EFI System Partition
   2        45.0 GiB    Apple Core Storage        Customer
   3        619.9 MiB   Recovery HD               Recovery HD
            128.0 MiB   free space
   4        10.0 GiB    Apple HFS/HFS+            hfs
   5        177.8 GiB   Linux LVM                 archlinux

Encrypting

We’re going to encrypt /dev/sdc5 with LVM on LUKS. These are approximately the results I got from cryptsetup benchmark.

cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1      1213629 iterations per second for 256-bit key
PBKDF2-sha256    1354749 iterations per second for 256-bit key
PBKDF2-sha512    1100289 iterations per second for 256-bit key
PBKDF2-ripemd160  897753 iterations per second for 256-bit key
PBKDF2-whirlpool  666185 iterations per second for 256-bit key
#  Algorithm | Key |  Encryption |  Decryption
     aes-cbc   128b   601.2 MiB/s  2589.5 MiB/s
 serpent-cbc   128b    78.5 MiB/s   511.4 MiB/s
 twofish-cbc   128b   178.7 MiB/s   328.4 MiB/s
     aes-cbc   256b   443.6 MiB/s  1964.6 MiB/s
 serpent-cbc   256b    79.6 MiB/s   511.2 MiB/s
 twofish-cbc   256b   180.1 MiB/s   328.4 MiB/s
     aes-xts   256b  2194.5 MiB/s  2182.6 MiB/s
 serpent-xts   256b   492.9 MiB/s   496.6 MiB/s
 twofish-xts   256b   319.2 MiB/s   324.4 MiB/s
     aes-xts   512b  1703.8 MiB/s  1689.3 MiB/s
 serpent-xts   512b   513.7 MiB/s   496.8 MiB/s
 twofish-xts   512b   285.3 MiB/s   324.8 MiB/s

First we must fill the partition with random-looking data. There is a clever way to do this with dm-crypt.

cryptsetup open --type plain /dev/sdc5 container --key-file /dev/random
dd if=/dev/zero of=/dev/mapper/container bs=1M status=progress
cryptsetup close container

This took about 700 seconds. Next, encrypt the partition and put a logical volume on it.

cryptsetup -v --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-password luksFormat /dev/sdc5
cryptsetup luksOpen /dev/sdc5 lvm
pvcreate /dev/mapper/lvm
vgcreate vgcrypt /dev/mapper/lvm
lvcreate --extents 100%FREE -n root vgcrypt
mkfs.ext4 /dev/mapper/vgcrypt-root

Now we can mount the volume with

mount /dev/mapper/vgcrypt-root /mnt
mkdir /mnt/boot
mount /dev/sdc1 /mnt/boot

where /dev/sdc1 is the EFI system partition.

Chrooting

The rest follows the wiki quite closely.

pacstrap -i /mnt base base-devel
genfstab -U /mnt >> /mnt/etc/fstab

The -U flag tells genfstab to use UUIDs. Now would be a good time to edit the fstab to add the discard option for TRIM, but let’s hold off on that.

arch-chroot /mnt /bin/bash
echo xyza > /etc/hostname

Edit /etc/locale.gen and uncomment #en_IE.UTF-8.

locale-gen
echo "LANG=en_IE.UTF-8" > /etc/locale.conf
ln -s /usr/share/zoneinfo/Europe/Dublin /etc/localtime

Edit the /etc/mkinitcpio.conf MODULES and HOOKS

MODULES="i915"    # for a smoother boot screen
⋮
HOOKS="base udev consolefont autodetect modconf block keymap keyboard encrypt lvm2 filesystems fsck"

and build the initial ramdisk with mkinitcpio -p linux.

Now set up the bootloader.

mkdir -p /boot/loader/entries
vi /boot/loader/loader.conf

and add

default arch.conf
timeout 3

Check that dev/sdc1 is mounted properly with findmnt /boot. Then make and edit /boot/loader/entries/arch.conf.

title       Arch Linux
linux       /vmlinuz-linux
initrd      /initramfs-linux.img
options     cryptdevice=/dev/sda5:vgcrypt:allow-discards root=/dev/mapper/vgcrypt-root rw

Note that there are security implications with enabling TRIM/discards.

bootctl install
pacman -S iw wpa_supplicant dialog
passwd

Shutdown, remove the installation media and reboot.

Configuration

Let’s make some swap space.

fallocate -l 8G /swapfile
chmod 600 /swapfile
mkswap swapfile
swapon /swapfile

Check that this worked with free -h or swapon --show and add

/swapfile none swap defaults 0 0

to the fstab.

For user management, make a new user and add them to the admin group.

useradd -m -G wheel -s /bin/bash fionn
passwd fionn

Then run visudo, uncomment # %wheel ALL=(ALL) ALL, log out and then back in again as a regular user.

sudo pacman -Syu bash-completion pkgfile

Now would be a good time to import .dotfiles.

To get netctl to automatically connect to networks, install wpa_actiond and enable netctl-auto@wlp3s0.service.

The console font is very small. Install terminus-font and add the line

FONT=ter-124n

to /etc/vconsole.conf.

X11

xf86-video-intel seems to be necessary to avoid screen tearing (xf86-video-modesetting doesn’t seem to help here). Edit /etc/X11/xorg.conf.d/20-intel.conf.

Section "Device"
   Identifier  "Intel Graphics"
   Driver      "intel"
   Option      "TearFree" "true"
EndSection

There’s a lot of talk about xf86-input-mtrack, but I find synaptics to be just fine. Here’s my /etc/X11/xorg.conf.d/50-synaptics.conf. (1, 2 and 3 correspond to left, middle and right.)

# Example xorg.conf.d snippet that assigns the touchpad driver
# to all touchpads. See xorg.conf.d(5) for more information on
# InputClass.
# DO NOT EDIT THIS FILE, your distribution will likely overwrite
# it when updating. Copy (and rename) this file into
# /etc/X11/xorg.conf.d first.
# Additional options may be added in the form of
#   Option "OptionName" "value"
#
Section "InputClass"
        Identifier "touchpad catchall"
        Driver "synaptics"
        MatchIsTouchpad "on"
        Option "TapButton1" "0"   # 1, 2, 3 for tapping
        Option "TapButton2" "0"
        Option "TapButton3" "0"
# Custom options
        Option "ClickFinger2" "2"
        Option "ClickFinger3" "3"
        Option "HorizTwoFingerScroll" "1"
        Option "VertEdgeScroll" "1"
        Option "PalmDetect" "1"
        Option "RBCornerButton" "3"
# This option is recommend on all Linux systems using evdev, but cannot be
# enabled by default. See the following link for details:
# https://who-t.blogspot.com/2010/11/how-to-ignore-configuration-errors.html
        MatchDevicePath "/dev/input/event*"
EndSection

Section "InputClass"
        Identifier "touchpad ignore duplicates"
        MatchIsTouchpad "on"
        MatchOS "Linux"
        MatchDevicePath "/dev/input/mouse*"
        Option "Ignore" "on"
EndSection

# This option enables the bottom right corner to be a right button on clickpads
# and the right and middle top areas to be right / middle buttons on clickpads
# with a top button area.
# This option is only interpreted by clickpads.
Section "InputClass"
        Identifier "Default clickpad buttons"
        MatchDriver "synaptics"
        Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
        Option "SecondarySoftButtonAreas" "58% 0 0 15% 42% 58% 0 15%"
EndSection

# This option disables software buttons on Apple touchpads.
# This option is only interpreted by clickpads.
Section "InputClass"
        Identifier "Disable clickpad buttons on Apple touchpads"
        MatchProduct "Apple|bcm5974"
        MatchDriver "synaptics"
        #Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
EndSection

To swap the function and media keys, edit /etc/modprobe.d/hid_apple.conf.

options hid_apple iso_layout=0   # for the key swap earlier
options hid_apple fnmode=2

To map the media keys to the hardware, install xorg-xbacklight, alsa-utils and, from the AUR, kbdlight. Edit /etc/modprobe.d/snd_hda_intel.conf.

options snd_hda_intel index=1,0

Bind the keys in ~/.i3/config with something like this.

bindsym XF86KbdBrightnessUp exec --no-startup-id kbdlight up

Lid

Edit /etc/systemd/logind.conf and set HandleLidSwitch=Ignore to stop the laptop from suspending whenever the lid is closed.

Mirrors

Grab a new mirrorlist with

cd /etc/pacman.d
sudo mv mirrorlist mirrorlist.bkup
sudo wget https://www.archlinux.org/mirrorlist/?country=all -O mirrorlist

and uncomment a mirror.

TRIM

TRIM the filesystem.

sudo fstrim -v /
/: 163.5 GiB (175549890560 bytes) trimmed

Then enable fstrim.timer to periodically issue discards.

DPP

Put xrandr --dpi 144 in ~/.xinitrc.

GTK3+ is supposed to pick up the system DPP settings, but it doesn’t for me. The solution is to set the font size to around 16 (using e.g. lxappearance-gtk3). For Firefox, set layout.css.devPixelsPerPixel=1.4 in about:config.

For QT to pick up on the GTK theme, install adwaita-qt5 from the AUR. Also export QT_STYLE_OVERRIDE=GTK+?