Jan 01, 2020 · ⏱ 1 minute

Setting up Windows and Arch Linux in Dual Boot 🦉


Windows install drive

  • Obtain a Windows ISO file
  • Flash onto drive using rufus, choose GPT and UEFI

Arch Linux install drive

BIOS settings

  • Enable virtualization technology (Intel VT-d, etc.)
  • Disable Secure Boot
  • Set boot option UEFI (sometimes marked as UEFI Only)
  • Disable CSM (BIOS/Legacy boot) support, we won't need it
  • Set boot mode to quick, if available
  • Adjust boot order, optional

Installing Windows

  • Boot system to flash drive with Windows ISO
  • Select locales, timezones, etc.
  • Accept license stuff
  • Continue with customized/advanced option: Only install Windows (for advanced users)
  • Delete all existing partitions, you should end up with one entry of unassigned Storage space...
  • Create new Windows system partition, roughly half the size of the entire disk
  • Confirm that the utility will create additional system partitions
  • If not selected already, select primary partition of newly-created Windows system partitions, continue and wait
  • Remove the installation flash drive
  • Follow the installation steps

Installing Arch Linux

Sourced from Arch Wiki

  • Boot to the Arch Linux installation drive

  • Change the keyboard layout to German

    $ loadkeys de-latin1
  • Get the name of your hard drive

    $ lsblk
    nvme0n1 # <-- this one is my primary drive
    nvme0n1p1 # Basic data partition (Windows)
    nvme0n1p2 # EFI system partition (Windows boot)
    nvme0n1p3 # Microsoft reserved.. (Windows)
    nvme0n1p4 # Basic data partition (Windows data C:)
  • Create two more partitions, one data and one swap partition for the Arch system

    $ gdisk /dev/<drive> # in my case nvme0n1
    $ p # will print all partitions (basically the same as described in the previous step)
    1 #...
    2 #...
    3 #...
    4 #...
    $ n # create data partition
    # confirm partition number
    # confirm first sector
    # set +200G as last sector (size of Linux disk space)
    # choose type 8300 (Linux filesystem) and confirm
    $ n # create swap partition
    # confirm partition number
    # confirm first sector
    # set +1G as last sector (swap space)
    # set 8200 (Linux swap) and confirm
    $ p # list and check again
    $ w # write to system
  • Create EXT4 filesystem for Arch Linux system data

    $ mkfs.ext4 -L system /dev/nvme0n1p5 # <-- your new 5th partition should come here, check its name with lsblk
  • Initialize Swap partition

    $ mkswap -L swap /dev/nvme0n1p6
  • Mount partitions

    # mount system partition
    $ mount -L system /mnt
    # create EFI partition mount entrypoint
    $ mkdir -p /mnt/boot
    # mount EFI partition
    $ mount /dev/nvme0n1p2 /mnt/boot
  • Enable swap partition

    $ swapon -L swap
  • Connect to WiFi using wpa_supplicant

    $ ip link
    1: lo
    2: eth0
    3: wlan0 # <- WiFi interface we want to use
    $ wpa_passphrase <SSID> <Password> > /etc/wpa_supplicant/wpa_supplicant.conf
    $ wpa_supplicant -i <WiFi interface> -D wext -c /etc/wpa_supplicant/wpa_supplicant.conf -B
    $ dhcpcd <WiFi interface>
  • Check if you're connected to the internet

    $ ping google.com
    64 bytes from...
  • Configure mirror list for package manager

    # create backup file for original config
    $ cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak
    # configure mirror list
    # ctrl+k will remove line in nano
    $ nano /etc/pacman.d/mirrorlist
    # or just select all Germany servers
    $ grep -E -A 1 ".*Germany.*$" /etc/pacman.d/mirrorlist.bak | sed '/--/d' > /etc/pacman.d/mirrorlist
  • Install system base packages

    $ pacstrap /mnt base base-devel linux linux-firmware nano bash-completion intel-ucode wpa_supplicant dhcpcd sudo grub efibootmgr os-prober git
  • Generate fstab (file system table)

    $ genfstab -Up /mnt > /mnt/etc/fstab
  • Enter new system using Arch chroot

    $ arch-chroot /mnt/
  • Set system hostname

    $ echo <hostname> > /etc/hostname
  • Set primary locale

    $ echo LANG=de_DE.UTF-8 > /etc/locale.conf
    # edit locale generation file to include locale from above
    $ nano /etc/locale.gen
    # install locales
    $ locale-gen
  • Set terminal keymap and font

    $ echo KEYMAP=de-latin1 > /etc/vconsole.conf
    $ echo FONT=lat9w-16 >> /etc/vconsole.conf
  • Set timezone using symlink

    $ ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
  • Configure hosts file

    $ nano /etc/hosts
    #<ip-address> <hostname.domain.org> <hostname> localhost.localdomain localhost
    ::1 localhost.localdomain localhost
  • Generate initramfs

    $ mkinitcpio -p linux
  • Set root password

    $ passwd
  • Configure bootloader (GRUB)

    # install grub
    $ grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub
    # check for existing operating systems (Windows)
    $ os-prober
    # configure grub
    $ grub-mkconfig -o /boot/grub/grub.cfg
  • Generate initramfs once more, just to make sure

  • Leave chroot, unmount partitions and reboot

    $ exit
    $ umount /dev/nvme0n1p2 # efi partition
    $ umount /dev/nvme0n1p5 # data partition
    $ reboot

Post-Installation Arch Linux setup

Taken from here

  • Reconnect to WiFi

  • Create user account

    # create user
    $ useradd -m -g users -s /bin/bash bruno
    # set user password
    $ passwd bruno
    # edit sudoers file, uncomment
    # %wheel ALL=(ALL) ALL
    $ nano /etc/sudoers
    # add user to sudoers group
    $ gpasswd -a bruno wheel
  • Install yay (AUR helper)

    git clone https://aur.archlinux.org/yay.git
    cd yay
    makepkg -si

Configure Remote Access via SSH

  • Retrieve IP address
    $ ip address show

Virtualization Setup (KVM)

Mostly combined sources Arch Wiki

  • Enable IOMMU

    # edit kernel parameters, add to GRUB_CMDLINE_LINUX_DEFAULT
    # intel_iommu=on
    # iommu=pt
    $ sudo nano /etc/default/grub
    # regenerate configuration
    $ sudo grub-mkconfig -o /boot/grub/grub.cfg
    # regenerate initramfs
    $ sudo mkinitcpio -p linux
    # reboot system
    $ reboot
  • Follow instructions from VM setup guides

  • Create script to isolate GPU at runtime, meaning that we want to disable the integrated GPU to be used in VMs

    set -e
    # Script to shutdown integrated graphics and launch QEMU VM
    # with graphics, etc. devices passed in
    # Inspired by https://worthdoingbadly.com/gpupassthrough/
    # Stop virtual terminals
    function stop-virtual-terminals() {
    echo "Stopping virtual terminals..."
    for i in /sys/class/vtconsole/*/bind
    echo 0 >$i
    echo "Stopped virtual terminals!"
    # Hot-disable kernel modules
    function disable-kernel-modules() {
    echo "Waiting for everything to settle down..."
    sleep 0.5
    echo "Removing modules..."
    rmmod snd_hda_intel
    rmmod i915
    echo "Removed kernel modules!"
    # Enable VFIO-PCI
    function enable-passthrough-pci() {
    # Load vfio-pci module with id of integrated graphics
    # Get ID from running lspci -nnkv
    modprobe vfio-pci ids=8086:5916,8086:9d71
    # Start VM
    function start-vm() {
    # Enable kernel modules again
    function enable-kernel-modules() {
    echo "Removing vfio-pci module again..."
    rmmod vfio-pci
    echo "Starting integrated graphics and audio again..."
    # Enable graphics for integrated GPU
    modprobe i915
    modprobe snd_hda_intel
    echo "Done!"
    function launch-vm() {