Dual-Booting Arch Linux on Lenovo X1 Carbon 3rd gen
« Isolating Polymorphism
» Hiring Apprentices
Code: Arch Linux, configuration, hardware, Lenovo, Linux, Windows, Windows 8.1, X1 Carbon, yak shave
I decided to replace my mid-2011 Macbook Air 3,2 with a non-Apple machine, but every laptop I looked at was unsuitable. Most were overpriced, with a big and clunky design. The Lenovo X1 Carbon was promising, but the 2nd generation had a keyboard that was just too weird (and the function keys changing modes means you can’t touch-type them anymore). Standard qwerty is bad, but it’s the devil I know.
That was a year ago. In January 2015 Lenovo released a third generation of the X1 Carbon with some slightly improved specs and a normal keyboard, so I picked one up. I decided to switch from Ubuntu because I’ve felt out-of-touch with how it works under the covers and I’ve been curious about Arch Linux. This post is my notes on setting that up.
2016-04-07: A year and three weeks after I started using this laptop (I know precisely because that put the laptop juuuust out of warranty), without warning or accident, the display stopped working. Lenovo’s expensive repair service estimated 6 businesses days for repair but the repair took over 5 weeks. If you might purchase a Lenovo laptop (perhaps the recent X1 Carbon 4th gen), I suggest you consider whether randomly losing hundreds of dollars and access to your laptop for 5 weeks would inconvenience you. 2016-05-16: …and by “5 weeks” I mean “9 weeks”. When Lenovo sent my laptop back with a new motherboard, it was one model down with slower processor, half the RAM, etc. It took another several weeks of dealing with their incompetent bureaucracy before they replaced it. 2016-12-18: Well, shit, the display on the replacement has started flickering.
The out-of-the box settings were decent, but I made a few tweaks.
- Wake on LAN: Disabled. I don’t use it.
- USB/Charge in Battery Mode: Enabled. I want to be able to charge my phone in my bag.
- Power/Intel Rapid Start: Disabled. Insecure hibernation. See partitioning below.
- Intel(R) AMT/Intel (R) AMT Control: Disabled. I do not have an enterprise IT department accessing my laptop.
- Option key Display: Disabled. Just looks nicer.
The laptop shipped with Windows 8.1 Standard installed. I wanted to keep it around for a few video games that don’t run on Linux, which meant resizing down its partition, removing the recovery partition, and removing a mysterious undeletable 7 GB “OEM partition”. The next paragraph is a rant and can be safely ignored.
Windows 8.1 is flippers-on-dry-land unusably bad. I have no idea how this shipped. I counted four GUI toolkit styles, inconsistent navigation, missing help files, privacy-invasive defaults, and settings broken up into several different screens in different programs that all look and work differently. Programs appeared and disappeared with little or no reason. Random DLL crashes on every boot. And even after tidying the many places it wastes disk space it needs 25 GB before any programs are installed. I can’t understand how people put up with this for daily use and spent an evening overwhelming frustrated after a couple hours of trial use. That the most common operating system looks and acts this way is a failure for my profession.
Removing the Windows recovery partition was easy. One of Windows’ several disk management programs slowly copied it to a 16 GB and removed the partition.
None of Windows disk management programs could explain or delete the “OEM partition”. This partition exists for the Intel Rapid Start feature, which (despite the name) exists to save battery life. IRS waits until the computer has been asleep for a while, copies RAM into this partition, and halts the computer. When the computer is started it takes a few seconds to restore RAM and the computer is usable normally. If this sounds an awful lot like the Windows/Linux “hibernate” feature, that’s because it’s the exact same thing implemented in the BIOS instead of the OS. And it saves your RAM unencrypted, so a thief can extract passwords, encryption keys, etc.
Even after turning off this misfeature in the BIOS, the Windows tools refuse to delete the partition, but if you can figure out how to start an admin console
diskpart can remove the partition. I also jumped through some hoops to turn off swapping (the
pagefile.sys) and hibernation (
hiber.sys) and reclaim some disk space, but it’s too tedious to recount.
The Windows disk tools can enlarge an NTFS storage partition but could barely shrink it… it claimed the smallest the 230 GB partition could be reduced to was 111 GB.
But I had my Arch Linux bootable USB key in hand and was off to Linux to get this computer set up. A quick
setfont sun12x22 made the terminal a lot more readable on the HiDPI 2560×1440 screen.
ntfsresize program quickly prepared the the NTFS partition for resizing. (It would be better named “ntfscompact”, because it compacts the drive content in preparation for resizing; it does not change parition size on its own.) I used
ntfsresize -i /dev/sda4 to examine it,
ntfsresize -nv -b -s 40G /dev/sda4 to test, and the same command without the
-n to do the job in a few seconds.
After shrinking it, I used
gdisk to “resize” it by deleting the partition and creating a new partition that starts at the same sector, has the same 0700 “Microsoft basic data” partition type, but is only 40 GB large. I used the “i” command to print info about the partition, snapped a photo with my camera, and used that to replace the “Partition unique GUID”. I don’t know if Windows would care if it changed, but it was so easy to carry over I didn’t want to risk it.
Finally I added a partition filling the rest of the disk space with the type 8300 for Linux, wrote the table, and rebooted to see Windows still working (phew).
I see a lot of client data and security keys as a consultant. Last year I worked on an app that did essential financial planning for a multi-billion dollar multinational company. If my laptop is lost or stolen, I don’t want that data (or my own personal data) easily readable.
Using the dm-crypt guides and Pavel Kogan’s notes on encrypting /boot, I set up full-disk encryption. GRUB is the only part of the Linux system unencrypted, which would be much more of a pain in the ass to compromise than an unencrypted /boot partition in the vanishingly-unlikely case that someone wanted to break the encryption. This is a nice little improvement for a little extra work, but I’m more concerned with protecting against opportunistic thieves than evil maids.
One major difference is that I didn’t mess around with LVM. I only want a single root partition filling my whole drive with /boot encrypted inside. I won’t be resizing or rearranging partitions, so there’s no reason to take on extra complexity for that unused optoin. With that in mind, and the Arch guides to device encryption, system configuration, and encrypting an entire system explaining all the details, here’s my command log:
# encrypt and format the partion cryptsetup -c aes-xts-plain64 -s 512 luksFormat /dev/sda5 cryptsetup luksDump /dev/sda5 cryptsetup luksOpen /dev/sda5 root mkfs.ext4 /dev/mapper/root mount /dev/mapper/root /mnt
My hard drive setup is done until it’s time to finish configuring grub for the encrypted volume, so it’s on to the installation guide:
Following the guide was easy:
wifi-menu # took a few tries to see my network vi /etc/pacman.d/mirrorlist # commented everything out, uncommented a few US mirrors pacstrap /mnt base genfstab -L -p /mnt >> /mnt/etc/fstab arch-chroot /mnt echo [hostname] > /etc/hostname ln -sf /usr/share/zoneinfo/US/Central /etc/localtime vi /etc/locale.gen # search for _US, uncomment locale-gen echo en_US.UTF-8 > /etc/locale.conf echo FONT=sun12x22 > /etc/vconsole.conf cp /usr/lib/systemd/system/systemd-vconsole-setup.service /etc/systemd/system/systemd-vconsole-setup.service
I did have to edit /etc/fstab to change
noatime on root and add the EFI and Windows partitions:
/dev/mapper/root / ext4 rw,noatime,data=ordered 0 1 efivars /sys/firmware/efi/efivars efivars defaults 0 0 /dev/sda2 /boot/efi vfat rw /dev/disk/by-label/Windows8_OS /opt/Windows8_OS ntfs rw,noauto
I also had to edit that copied
system-dvconsole-setup.service file to add
Wants=systemd-udev-settle.service under the
[Unit] heading to set the font after the graphics driver was loaded, as described here.
As prompted by Kogan’s encryption guide, I created the encryption keyfile and added it to LUKS:
dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin cryptsetup luksAddKey /dev/sda5 /crypto_keyfile.bin mkinitcpio -p linux passwd pacman -S grub efibootmgr vi /etc/mkinitcpio.conf vi /etc/default/grub
With that first
vi I added “encrypt” to HOOKS and “/crypto_keyfile.bin” to FILES in
mkinitcpio.conf. With the second I added
grub to add:
before I run this (which needs to run every time grub’s config is tweaked):
grub-mkconfig -o /boot/grub/grub.cfg grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub_uefi --recheck
Next, time to install some basic networking tools so I can install the rest of the system from inside itself rather than the bootable usb:
pacman -Syyu pacman -S iw dialog net-tools pkgfile wpa_supplicant pkgfile --update
Figuring out which packages I needed involved a lot of booting from the usb and running the following commands.
wifi-menu cryptsetup luksOpen /dev/sda5 root mount /dev/mapper/root /mnt arch-chroot /mnt
arch-chroot and ran
umount -R /mnt to see everything cleanly unmount.
It’s finally time to configure wifi (replacing the network ssid and password in brackets) and connect:
# I had to bring the network up manually, first: wpa_supplicant -B -D nl80211,wext -i wlp4s0 <(wpa_passphrase <essid> <passphrase>) dhcpcd wlp4s0 # then save it wifi-menu # saved as wlp4s0-<essid> netctl enable wlp4s0-<essid>
I lost a lot of time trying to get netctl to work reliably with wpa_supplicant. Sometimes it just failed to work after a reboot. Disabling netctl in favor of NetworkManager (whether through nm-applet or nmcli) was a big win.
Next I need to shave a different herd of yaks. I want to use etckeeper to track
/etc (this turned out to be absolutely vital as I struggled with netctl). Which means I need to build and install it from the Arch User Repository, which I’d like to do with aura, which means I need to install enough tools to build and install that, which means I need to create a user account (for makepkg to run)…
# add a user: useradd pushcx passwd pushcx visudo # to append "pushcx ALL=(ALL) ALL" # log out, log in as pushcx # install aura: curl https://aur.archlinux.org/packages/au/aura-bin/aura-bin.tar.gz -O tar -xvf aura-bin.tar.gz makepkg -s sudo pacman -U aura-bin-18.104.22.168-1-x86_75.pkg.tar.xz # install etckeeper: cd sudo aura -Ai etckeeper sudo aura -Ap etckeeper sudo aura -Ax etckeeper # configure etckeeper: sudo etckeeper init sudo git config --global user.email "root@hostname" sudo git config --global user.name "root" sudo git commit -m "initial commit" sudo git gc # saved 5m
Phew, not too bad a shave, and I’m starting to see the Arch philosophy at work. This feels a lot like Slackware with some build automation. I used Slackware for about six years until I realized I wasn’t learning anything new. Lately I’ve felt out of touch with how my Linux install works; I hope Arch is the right level of automation and configuration.
(Speaking of philosophy, even after reading the justification I don’t understand how Arch settled on systemd. It seems the antithesis of the Unix Way and the Arch Way. I’m glad to be learning it as the majority of distros are moving to it, but it’s a beast.)
Digging into the general recommendations page showcases what first caught my attention about Arch: comprehensive, decently-written documentation about all aspects of the system. I’ve already been using Arch’s wiki for tips on understanding and maintaining my Ubuntu system for a year or so.
Meanwhile, I’ll add some basic packages, get into configuring the GUI, and test all the hardware drivers.
timedatectl set-ntp true # console essentials: pacman -S openssh tree tmux vim # x essentials: pacman -S xorg-server xorg-xinit lightdm \ lightdm-gtk3-greeter awesome vicious xterm \ urxvt-unicode notification-daemon ttf-freefont \ ttf-dejavu xorg-xmodmap xorg-xrdb gnome-keyring # drivers: pacman -S libva-intel-driver xf86-video-intel xf86-input-evdev xf86-input-synaptics
lightdm, I created a
#!/bin/sh eval $(/usr/bin/gnome-keyring-daemon --start --components=pkcs11,secrets,ssh) export SSH_AUTH_SOCK xrdb -merge $HOME/.Xdefaults & gnome-settings-daemon & nm-applet &
And I had
startx‘s startup script
~/.xinitrc call that:
#!/bin/sh [ -f ~/.xprofile ] && source ~/.xprofile exec awesome
And added a
~/.Xresources for the HiDPI display:
xterm*utf8: 1 Xft.dpi: 180 Xft.autohint: 0 Xft.lcdfilter: lcddefault Xft.hintstyle: hintfull Xft.hinting: 1 Xft.antialias: 1 Xft.rgba: rgb
[greeter] xft-antialias=true xft-dpi=180 xft-hintstyle=hintfull xft-rgba=rgb hide-user-image=true
Starting X and poking around my virtual terminals, Xorg was on F1, F2-F6 were more consoles, and F7 displayed a horizontally flickering cursor. After seeing that flicker, switching to Xorg or the text terminals displayed the same horizontal flickering; it looked like it was trying to repeatedly draw the screen at several different horizontal offsets that moved in and out of phase. This seems to be a bug in the intel video driver I’ll need to report; it appears fairly regularly as I switch between console and video modes.
2015-03-15: This was fixed in the latest version of the
xf86-video-intel driver. Thanks to Jeremy Fleischman for the heads up.
I installed the laptop mode tools and configured powersaving. After running a laptop with a 3.5 year old battery, I’m really delighted and impressed to see 6-8 hour battery times when I nudge the LCD brightness down a little (in X or by editing
/sys/class/backlight/intel_backlight/brightness) and even more if I turn off the wifi.
pacman -S laptop-mode-tools acpi acpid ethtool wireless_tools systemctl enable laptop-mode
/etc/laptop-mode/laptop-mode.conf only needed one or two tweaks, like
acpi command line tool is handy for watching battery from the console (I was buddy breathing my AC adaptor during the install).
Following the wiki instructions:
pacman -S bluez bluez-utils gnome-bluetooth hciconfig hci0 up bluetoothctl [bluetooth]# devices [bluetooth]# scan on # ... wait a minute ... [bluetooth]# scan off [bluetooth]# agent on [bluetooth]# pair F0<tab> [bluetooth]# trust F0<tab> [bluetooth]# connect F0<tab>
And to bring bluetooth online automatically after restarts, add
# Set bluetooth power up ACTION=="add", KERNEL=="hci0", RUN+="/usr/bin/hciconfig hci0 up"
This works fine, but I also did
aura -A blueman for a nice X applet.
Hope this helps if you’re setting up Linux on an X1 Carbon or just curious about what the steps of setting up Arch Linux look like. As expected, Arch is a whole lot of fiddly little configuration steps. They gave me the excuse I wanted to see current Linux software config and tinker, but it’s quite time-consuming.
2015-02-12: I’ve started a page on the Arch wiki about the X1 Carbon (3g). It contains more information than this about setting it up, including some known bug.