Skip to content

Instantly share code, notes, and snippets.

@kongkrit
Last active April 8, 2024 14:56
Show Gist options
  • Save kongkrit/a0585e179e33c2adf92db4050ec5171d to your computer and use it in GitHub Desktop.
Save kongkrit/a0585e179e33c2adf92db4050ec5171d to your computer and use it in GitHub Desktop.
Install Manjaro on ZFS root with systemd-boot or grub

Installing Manjaro on ZFS root using grub [UEFI only]

References:[ manjaro-cli-install | john_ransden-arch on ZFS | arch-systemd-boot-wiki ]

  • Start from manjaro architect [ download ]
  • login as manjaro password manjaro
  • Install necessary packages:
    sudo -i               # become root
    systemctl enable --now systemd-timesyncd  # sync time using NTP
    pacman -Sy
    pacman -S --noconfirm openssh
    # edit /etc/ssh/sshd_config to have 'PermitRootLogin yes` line
    sed -i -E 's/^#PermitRootLogin.*$/PermitRootLogin yes/g' /etc/ssh/sshd_config
    echo "root:any" | chpasswd # change root password to 'any'
    systemctl start sshd ; systemctl status sshd
    ip addr show          # note ip address
    
  • You can now ssh into the box. Login as root:
    pacman-mirrors --country-list    # list all pacman mirror countries
    pacman-mirrors --api --set-branch stable --country United_States,Singapore,Canada
    pacman -Sy
    
  • Install keysrings and create trust database and refresh keys
    pacman -S --noconfirm pacman archlinux-keyring manjaro-keyring ntp
    pacman-key --init
    pacman-key --populate archlinux manjaro
    pacman-key --refresh-keys
    
  • Install zfs
    pacman -S --noconfirm linux54-zfs # install ZFS
    modprobe zfs          # load zfs module
    lsmod | grep zfs      # see zfs module loaded
    zfs --version         # check version
    
  • Set DISK1 and DISK2 variables and erase them
    • ls -lF /dev/disk/by-id and set the UUID of your own hard disks
    DISK1=/dev/disk/by-id/ata-VBOX_HARDDISK_VB18c0305d-4e63e5c6 # use your own
    DISK2=/dev/disk/by-id/ata-VBOX_HARDDISK_VB0a4a9fa5-eb40797e # use your own
    pacman -S --noconfirm gptfdisk
    sgdisk --zap-all $DISK1
    sgdisk --zap-all $DISK2
    
  • create UEFI partition for booting:
    sgdisk -n1:1M:+512M -t1:EF00 $DISK1
    sgdisk -n1:1M:+512M -t1:EF00 $DISK2
    udevadm settle; sleep 1
    mkfs.fat -F 32 -n EFI ${DISK1}-part1
    mkfs.fat -F 32 -n EFI ${DISK2}-part1
    
  • create ZFS partitions for boot:
    sgdisk -n2:0:+1G -t2:BF00 $DISK1
    sgdisk -n2:0:+1G -t2:BF00 $DISK2
    sleep 1
    
  • create ZFS partitions for root:
    sgdisk -n3:0:0 -t3:BF00 $DISK1
    sgdisk -n3:0:0 -t3:BF00 $DISK2
    sleep 1
    
  • create boot pool (bpool) with features incompatible for grub disabled. (see step 2.4) for parameters compatible with GRUB:
    BPOOL=bpool
    zpool create -o ashift=12 -d \
      -o feature@async_destroy=enabled \
      -o feature@bookmarks=enabled \
      -o feature@embedded_data=enabled \
      -o feature@empty_bpobj=enabled \
      -o feature@enabled_txg=enabled \
      -o feature@extensible_dataset=enabled \
      -o feature@filesystem_limits=enabled \
      -o feature@hole_birth=enabled \
      -o feature@large_blocks=enabled \
      -o feature@lz4_compress=enabled \
      -o feature@spacemap_histogram=enabled \
      -o feature@userobj_accounting=enabled \
      -o feature@zpool_checkpoint=enabled \
      -o feature@spacemap_v2=enabled \
      -o feature@project_quota=enabled \
      -o feature@resilver_defer=enabled \
      -o feature@allocation_classes=enabled \
      -O acltype=posixacl -O canmount=off -O compression=lz4 -O devices=off \
      -O normalization=formD -O relatime=on -O xattr=sa \
      -O mountpoint=none -R /mnt -f $BPOOL mirror ${DISK1}-part2 ${DISK2}-part2
    
  • create root pool (use ashift=13 for Samsung SSD):
    RPOOL=rpool
    zpool create -o ashift=12 \
      -O acltype=posixacl -O canmount=off -O compression=lz4 \
      -O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa \
      -O mountpoint=none -R /mnt \
      -f $RPOOL mirror ${DISK1}-part3 ${DISK2}-part3
    
  • create containers for $RPOOL and $BPOOL
    zfs create -o mountpoint=none $BPOOL/BOOT
    zfs create -o mountpoint=none  $RPOOL/ROOT
    
  • create datasets for $RPOOL:
    rm -rf /mnt
    mkdir -p /mnt
    zfs create -o mountpoint=/     $RPOOL/ROOT/manjaro
    zfs create -o mountpoint=none  $RPOOL/data
    zfs create -o mountpoint=/home $RPOOL/data/home
    zfs create -o mountpoint=/root $RPOOL/data/home/root
    zfs create -o mountpoint=/var/cache/pacman $RPOOL/data/paccache
    
  • create datasets for $BPOOL:
    zfs create -o mountpoint=/boot $BPOOL/BOOT/default
    
  • unmount all filesystems and set new mountpoints:
    zfs unmount -a # unmount all zfs filesystems
    zfs set mountpoint=/boot $BPOOL/BOOT/default
    zfs set mountpoint=/     $RPOOL/ROOT/manjaro
    zfs set mountpoint=/home $RPOOL/data/home
    zfs set mountpoint=/root $RPOOL/data/home/root
    zfs set mountpoint=/var/cache/pacman $RPOOL/data/paccache
    
  • Export pools:
    zpool export $BPOOL
    zpool export $RPOOL
    
  • Re-import pools:
    rm -rf /mnt
    zpool import -d /dev/disk/by-id -R /mnt $RPOOL
    zpool import -d /dev/disk/by-id -R /mnt $BPOOL
    
  • Disable cache files:
    zpool set cachefile=none $BPOOL
    zpool set cachefile=none $RPOOL
    
  • make efi mount points and mount them:
    mkdir -p /mnt/{efi1,efi2}
    mount -t vfat ${DISK1}-part1 /mnt/efi1
    mount -t vfat ${DISK2}-part1 /mnt/efi2
    
  • edit /etc/fstab to include the above 4 pools from $RPOOL:
    echo "# generated fstab
    # <file system>                <dir>              <type>    <options>                <dump> <pass>
    $RPOOL/ROOT/manjaro/root         /                  zfs       defaults,noatime          0      0
    $RPOOL/ROOT/manjaro/paccache     /var/cache/pacman  zfs       defaults,noatime          0      0
    $RPOOL/data/home                 /home              zfs       defaults,noatime          0      0
    $RPOOL/data/home/root            /root              zfs       defaults,noatime          0      0" \
    > /etc/fstab
    
  • Set the bootfs property on the root filesystem. This command will only be successful when dnodesize property on $BPOOL/BOOT/default is set to legacy [ ref ]
    zfs set dnodesize=legacy $BPOOL/BOOT/default
    zpool set bootfs=$BPOOL/BOOT/default $BPOOL
    
  • double check work:
    findmnt | grep /mnt # shows /mnt, /mnt/home, /mnt/root, /mnt/var/cache/pacman, /mnt/boot, /mnt/efi1, /mnt/efi2 as mounted
    
  • use basestrap to install base set of packages into /mnt
    basestrap /mnt base linux54-zfs zfs-utils mkinitcpio grub efibootmgr dosfstools \
      dhcpcd networkmanager openssh vi nano sudo man man-pages which bash-completion
    # removed - intel-ucode systemd-boot-manager
    
  • edit /mnt/etc/mkinitcpio.conf and change HOOKS line to be: HOOKS=(base udev autodetect modconf block keyboard zfs filesystems)
    sed -i.bak -E 's/^(HOOKS=.*)$/#\1\nHOOKS=\(base udev autodetect modconf block keyboard zfs filesystems\)/g' /mnt/etc/mkinitcpio.conf
    cat /mnt/etc/mkinitcpio.conf # verify it
    
  • copy /etc/fstab to new installation:
    # cp /etc/fstab /mnt/etc/fstab.old    # keep old fstab
    fstabgen -U /mnt >> /mnt/etc/fstab  # generate new fstab
    
  • since we mounted /var/cache/pacman and /home via ZFS (non-legacy), we need to remove these entries from the new /mnt/etc/fstab
    sed -i -E 's/^('"$RPOOL"'\/data.*)$/#\1/g; s/^('"$RPOOL"'\/ROOT\/manjaro\/paccache.*)/#\1/g' /mnt/etc/fstab
    
  • save the variables for use later (optional):
    cat > /mnt/root/vars.sh << EOF
    DISK1=$DISK1
    DISK2=$DISK2
    RPOOL=$RPOOL
    BPOOL=$BPOOL
    EOF
    
  • chroot into new installation:
    manjaro-chroot /mnt /usr/bin/env DISK1=$DISK1 DISK2=$DISK2 RPOOL=$RPOOL BPOOL=$BPOOL /bin/bash
    
  • set timezone:
    rm -rf /etc/localtime
    ln -sf /usr/share/zoneinfo/Asia/Bangkok /etc/localtime
    hwclock --systohc --utc # generate /etc/adjtime and set HW RTC to UTC
    
  • generate locales:
    sed -iE 's/^#en_US.UTF-8/en_US.UTF-8/g' /etc/locale.gen  # uncomment en_US.UTF-8
    locale-gen
    
  • set locale systemwide:
    export LANG=en_US.UTF-8
    export LC_COLLATE=C
    cat > /etc/locale.conf << EOF
    LANG=$LANG
    LC_COLLATE=$LC_COLLATE
    EOF
    
  • set hostname and edit /etc/hosts file:
    # call it whatever you want
    HOSTNAME=manjaz
    echo $HOSTNAME > /etc/hostname
    cat >> /etc/hosts << EOF
    127.0.0.1       localhost
    ::1             localhost
    127.0.1.1       $HOSTNAME
    EOF
    
  • Allow members of wheel group to admin machine, and choose 1. or 2.
    1. Uncomment %wheel ALL=(ALL) ALL -- sudo would require a password or
      sed -E 's|^#?[ \t]*(\%wheel ALL=\(ALL\) ALL.*)$|\1|g' /etc/sudoers | EDITOR=tee visudo
      
    2. Uncomment %wheel ALL=(ALL) NOPASSWD: ALL -- sudo does not require a password
      sed -E 's|^#?[ \t]*(\%wheel ALL=\(ALL\) NOPASSWD.*)$|\1|g' /etc/sudoers | EDITOR=tee visudo
      
  • enable dhcp client and NTP client:
    systemctl enable dhcpcd
    systemctl enable systemd-timesyncd
    
  • make initramfs:
    mkinitcpio -P # mkinitcpio -p linux54
    
  • set root password:
    echo "root:abc" | chpasswd # change root password to `abc`
    grep root /etc/shadow # should show: root:$6$.....
    
  • generate mount points for EFI partitions:
mkdir -p /efi1
mkdir -p /efi2
  • add 2 EFI partitions to /etc/fstab
    # comment everything on /etc/fstab
    sed -i -E 's/^([^#].*)$/# \1/g' /etc/fstab
    
    echo PARTUUID=$(blkid -s PARTUUID -o value ${DISK1}-part1) \
      /efi1 vfat nofail,x-systemd.device-timeout=1 0 1 >> /etc/fstab
    echo PARTUUID=$(blkid -s PARTUUID -o value ${DISK2}-part1) \
      /efi2 vfat nofail,x-systemd.device-timeout=1 0 1 >> /etc/fstab
    
  • install grub
    pacman -S --noconfirm grub efibootmgr
    # mount /efi1
    # mount /efi2
    
  • create /etc/default/grub
    ZPOOL_VDEV_NAME_PATH=1 grub-probe /boot # should return "zfs"
    
  • modify /etc/default/grub - add zfs=rpool: ref [ grub-error-sparse-file-not-allowed-fix ]
    [[ -f /etc/default/grub.original ]] && cp /etc/default/grub.original /etc/default/grub
    cp /etc/default/grub /etc/default/grub.original
    
    # comment out GRUB_TIMEOUT_STYLE=hidden
    sed -i -E 's/(^GRUB_TIMEOUT_STYLE=hidden)/#\1/g' /etc/default/grub
    
    ## add GRUB_CMDLINE_LINUX="root=ZFS=$RPOOL/ROOT/default"
    # sed -i -E 's/(^GRUB_CMDLINE_LINUX=")/\1root=ZFS='"$RPOOL"'\/ROOT\/manjaro\/root /g' /etc/default/grub
    # add GRUB_CMDLINE_LINUX="zfs=$RPOOL" (info from mkinitcpio -H zfs)
    sed -i -E 's/^(GRUB_CMDLINE_LINUX=")(.*)$/\1zfs='"$RPOOL"' \2/g' /etc/default/grub
    
    # comment out any GRUB_SAVEDEFAULT and write GRUB_SAVEDEFAULT=false
    # this gets rid of "sparse file not supported" error when GRUB boots
    sed -i -E 's/^#?(GRUB_SAVEDEFAULT=.*)$/GRUB_SAVEDEFAULT=false\n#\1/g' /etc/default/grub
    
    # add GRUB_RECORDFAIL_TIMEOUT=5
    sed -i -E 's/(^GRUB_TIMEOUT=)[0-9]+$/\15\nGRUB_RECORDFAIL_TIMEOUT=5/g' /etc/default/grub
    
    # remove "quiet" from GRUB_CMDLINE_LINUX_DEFAULT
    sed -i -E 's/(^GRUB_CMDLINE_LINUX_DEFAULT=")(.*)(quiet)(.*)(")/\1\2\4\5/g' /etc/default/grub
    
    # remove spaces next to quotation marks on GRUB_CMDLINE_LINUX_DEFAULT
    sed -i -E 's/(^GRUB_CMDLINE_LINUX_DEFAULT=")([ \t]+)(.*)(")/\1\3\4/g' /etc/default/grub
    sed -i -E 's/(^GRUB_CMDLINE_LINUX_DEFAULT=")(.*)([ \t]+)(")/\1\2\4/g' /etc/default/grub
    
  • run grub-mkconfig and install grub:
    ZPOOL_VDEV_NAME_PATH=1 grub-mkconfig -o /boot/grub/grub.cfg
    ZPOOL_VDEV_NAME_PATH=1 grub-install --target=x86_64-efi --efi-directory=/efi1 --bootloader-id=GRUB
    
  • sync the two EFI partitions:
    pacman -S --noconfirm rsync
    rsync -Rai --stats --human-readable --delete --verbose --progress /efi1/./ /efi2
    
  • do efibootmgr on disk2
    efibootmgr -c -g -d $DISK2 -p 1 -L "GRUB-2" -l '\EFI\GRUB\grubx64.efi'
    
  • double check /etc/grub/grub.cfg according to [this](https://wiki.archlinux.org/index.php/Install_Arch_Linux_on_ZFS#Booting_your_kernel_and_initrd_from_ZFS
  • start sshd and enable root login (add PermitRootLogin yes to /etc/ssh/sshd_config):
    pacman -S --noconfirm openssh
    sed -i -E 's/^(#PermitRootLogin.*)$/PermitRootLogin yes\n\1/g' /etc/ssh/sshd_config
    systemctl enable sshd
    
  • comment out all the zfs from /etc/fstab
cp /etc/fstab /etc/fstab.original
sed -i -E 's/^('"$RPOOL"'.*)$/# \1/g' /etc/fstab
sed -i -E 's/^('"$BPOOL"'.*)$/# \1/g' /etc/fstab
  • enable zfs-import-cache.service
    zpool set cachefile=/etc/zfs/zpool.cache $BPOOL 
    zpool set cachefile=/etc/zfs/zpool.cache $RPOOL
    systemctl enable zfs-import-cache.service
    
  • add aliases and prompt to /etc/skel/.bashrc:
    cat >> /etc/skel/.bashrc << EOF
    
    if [[ \$USER != "root" ]]; then
      PS1="\[\e[01;32m\]\u@\h\[\e[01;34m\] \w \\\\$\[\e[0m\] "
    else
      PS1="\[\e[01;31m\]\u@\h\[\e[01;34m\] \w \\\\$\[\e[0m\] "
    fi
    alias egrep='egrep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias grep='grep --color=auto'
    alias l='ls -CF'
    alias la='ls -A'
    alias ll='ls -alF'
    alias ls='ls --color=auto'
    EOF
    
  • copy this .bash_profile and .bashrc to root:
    [[ ! -f /root/.bash_profile ]] && cp /etc/skel/.bash_profile /root
    [[ ! -f /root/.bashrc ]]       && cp /etc/skel/.bashrc       /root
    
  • save installation environment variables:
    cat > ~/vars.sh << EOF
    # installation environment
    DISK1=$DISK1
    DISK2=$DISK2
    RPOOL=$RPOOL
    BPOOL=$BPOOL
    EOF
    
  • Exit chroot
    exit
    
  • unmount filesystem
    umount -R /mnt
    zfs umount -a
    
  • export them:
    zpool export $RPOOL
    zpool export $BPOOL
    
  • remove live media and prepare to reboot
    reboot
    
  • after reboot, login as root
  • make sure zfs-import-cache.service can find zpool cache.
    zpool set cachefile=/etc/zfs/zpool.cache zroot # <-- zroot here is our $ZROOT
    
  • edit /etc/pacman.conf and scroll to #IgnorePkg and add:
    IgnorePkg = linux54-zfs  # so this package won't be updated
    
  • add more packages:
    pacman -S --noconfirm bash-completion pv
    

Installing Manjaro on ZFS root using systemd-boot [UEFI only]

References:[ manjaro-cli-install | john_ransden-arch on ZFS | arch-systemd-boot-wiki ]

  • Start from manjaro architect [ download ]
  • login as manjaro password manjaro
  • Install necessary packages:
    sudo -i               # become root
    systemctl enable --now systemd-timesyncd  # sync time using NTP
    pacman -Sy
    pacman -S --noconfirm openssh
    # edit /etc/ssh/sshd_config to have 'PermitRootLogin yes` line
    # sed -i -E 's/^#PermitRootLogin.*$/PermitRootLogin yes/g' /etc/ssh/sshd_config
    # echo "root:any" | chpasswd # change root password to 'any'
    systemctl start sshd ; systemctl status sshd
    ip addr show          # note ip address
    
  • You can now ssh into the box. Login as manjaro password manjaro:
  • Become root:
    sudo -i
    
  • Setup pacman:
    pacman-mirrors --country-list    # list all pacman mirror countries
    pacman-mirrors --api --set-branch stable --country United_States,Singapore,Canada
    pacman -Sy
    
  • Install keysrings and create trust database and refresh keys
    pacman -S --noconfirm pacman archlinux-keyring manjaro-keyring ntp
    pacman-key --init
    pacman-key --populate archlinux manjaro
    pacman-key --refresh-keys
    
  • Install zfs
    pacman -S --noconfirm linux54-zfs # install ZFS
    modprobe zfs          # load zfs module
    lsmod | grep zfs      # see zfs module loaded
    zfs --version         # check version
    
  • Set DISK1 and DISK2 variables and erase them
    • ls -lF /dev/disk/by-id and set the UUID of your own hard disks
    DISK1=/dev/disk/by-id/ata-VBOX_HARDDISK_VB18c0305d-4e63e5c6 # use your own
    DISK2=/dev/disk/by-id/ata-VBOX_HARDDISK_VB0a4a9fa5-eb40797e # use your own
    pacman -S --noconfirm gptfdisk
    sgdisk --zap-all $DISK1
    sgdisk --zap-all $DISK2
    udevadm settle; sleep 1
    
  • create UEFI partition for booting:
    sgdisk -n1:1M:+512M -t1:EF00 $DISK1
    sgdisk -n1:1M:+512M -t1:EF00 $DISK2
    udevadm settle; sleep 1
    mkfs.fat -F 32 -n EFI ${DISK1}-part1
    mkfs.fat -F 32 -n EFI ${DISK2}-part1
    
  • create ZFS partitions for root:
    sgdisk -n2:0:0 -t2:BF00 $DISK1
    sgdisk -n2:0:0 -t2:BF00 $DISK2
    sleep 1
    
  • create zpool (use ashift=13 for Samsung SSD):
    ZROOT=zroot
    zpool create -o ashift=12 \
      -O acltype=posixacl -O canmount=off -O compression=lz4 \
      -O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa \
      -O mountpoint=none \
      -f $ZROOT mirror ${DISK1}-part2 ${DISK2}-part2
    
  • create datasets
    zfs create -o mountpoint=none $ZROOT/ROOT
    zfs create -o mountpoint=none $ZROOT/ROOT/manjaro
    zfs create -o mountpoint=none $ZROOT/data
    zfs create -o mountpoint=/mnt                  $ZROOT/ROOT/manjaro/root
    zfs create -o mountpoint=/mnt/home             $ZROOT/data/home
    zfs create -o mountpoint=/mnt/home/root        $ZROOT/data/root
    zfs create -o mountpoint=/mnt/var/cache/pacman $ZROOT/ROOT/manjaro/paccache
    
  • unmount all zfs filesystems and set new mountpoints:
    zfs unmount -a # unmount all zfs filesystems
    zfs set mountpoint=/ $ZROOT/ROOT/manjaro/root
    zfs set mountpoint=/home $ZROOT/data/home
    zfs set mountpoint=/root $ZROOT/data/root
    zfs set mountpoint=/var/cache/pacman $ZROOT/ROOT/manjaro/paccache
    
  • edit /etc/fstab to include the above 4 datasets:
    echo "# generated fstab
    # <file system>                <dir>              <type>    <options>                <dump> <pass>
    $ZROOT/ROOT/manjaro/root         /                  zfs       defaults,noatime          0      0
    $ZROOT/ROOT/manjaro/paccache     /var/cache/pacman  zfs       defaults,noatime          0      0
    $ZROOT/data/root                 /root              zfs       defaults,noatime          0      0
    $ZROOT/data/home                 /home              zfs       defaults,noatime          0      0" \
    > /etc/fstab
    
  • Set the bootfs property on the root filesystem. This command will only be successful when dnodesize property on $ZROOT/ROOT/manjaro/root is set to legacy [ ref ]
    zfs set dnodesize=legacy $ZROOT/ROOT/manjaro/root
    zpool set bootfs=$ZROOT/ROOT/manjaro/root $ZROOT
    
  • Export & re-import pool:
    zpool export $ZROOT
    zpool import -d /dev/disk/by-id -R /mnt $ZROOT
    # mount -t zfs $ZROOT/ROOT/manjaro/paccache /mnt/var/cache/pacman  # must use "mount" for legacy zfs datasets
    # mount -t zfs $ZROOT/data/home /mnt/home                          # must use "mount" for legacy zfs datasets
    
  • check the work:
    findmnt | grep /mnt  # check that /mnt, /mnt/root, /mnt/home, /mnt/var/cache/pacman are mounted
    
  • use basestrap to install base set of packages into /mnt
    basestrap /mnt base linux54-zfs intel-ucode systemd-boot-manager mkinitcpio \
        gptfdisk dosfstools zfs-utils \
        dhcpcd networkmanager openssh ntp \
        vi nano sudo man which bash-completion pv  # removed - grub efibootmgr
    
  • edit /mnt/etc/mkinitcpio.conf and change HOOKS line to be: HOOKS=(base udev autodetect modconf block keyboard zfs filesystems)
    sed -i.bak -E 's/^(HOOKS=.*)$/#\1\nHOOKS=\(base udev autodetect modconf block keyboard zfs filesystems\)/g' /mnt/etc/mkinitcpio.conf
    cat /mnt/etc/mkinitcpio.conf # verify it
    
  • copy /etc/fstab to new installation:
    cp /etc/fstab /mnt/etc/fstab.old    # keep old fstab
    fstabgen -U /mnt >> /mnt/etc/fstab  # generate new fstab
    
  • since we mounted /var/cache/pacman, /home, and /root via ZFS (non-legacy), we need to remove these entries from the new /mnt/etc/fstab
    sed -i -E 's/^('"$ZROOT"'\/data.*)$/#\1/g; s/^('"$ZROOT"'\/ROOT\/manjaro\/paccache.*)/#\1/g' /mnt/etc/fstab
    
  • chroot into new installation:
    manjaro-chroot /mnt /usr/bin/env DISK1=$DISK1 DISK2=$DISK2 ZROOT=$ZROOT /bin/bash
    
  • set timezone:
    rm -rf /etc/localtime
    ln -sf /usr/share/zoneinfo/Asia/Bangkok /etc/localtime
    hwclock --systohc --utc # generate /etc/adjtime and set HW RTC to UTC
    
  • generate locales:
    sed -iE 's/^#en_US.UTF-8/en_US.UTF-8/g' /etc/locale.gen  # uncomment en_US.UTF-8
    locale-gen
    echo LANG=en_US.UTF-8 > /etc/locale.conf
    export LANG=en_US.UTF-8
    
  • set hostname and edit /etc/hosts file:
    # call it whatever you want
    HOSTNAME=manjaz
    echo $HOSTNAME > /etc/hostname
    echo "# setup
    127.0.0.1       localhost
    ::1             localhost
    127.0.1.1       $HOSTNAME" >> /etc/hosts
    
  • Allow members of wheel group to admin machine: EDITOR=nano visudo and choose 1. or 2.
    1. Uncomment %wheel ALL=(ALL) ALL -- sudo would require a password or
    2. Uncomment %wheel ALL=(ALL) NOPASSWD: ALL -- sudo does not require a password
  • enable dhcp client and NTP client:
    systemctl enable dhcpcd
    systemctl enable systemd-timesyncd
    
  • set root password:
    echo "root:abc" | chpasswd # change root password to `abc`
    

systemd-boot Bootloader

  • make initramfs:
    mkinitcpio -P # mkinitcpio -p linux54
    
  • create EFI paritions mount points and add them to /etc/fstab:
    mkdir -p /boot1
    mkdir -p /boot2
    echo PARTUUID=$(blkid -s PARTUUID -o value ${DISK1}-part1) \
      /boot1 vfat nofail,x-systemd.device-timeout=1 0 1 >> /etc/fstab
    echo PARTUUID=$(blkid -s PARTUUID -o value ${DISK2}-part1) \
      /boot2 vfat nofail,x-systemd.device-timeout=1 0 1 >> /etc/fstab
    
  • mount /boot1 and /boot2:
    mount /boot1
    mount /boot2
    
  • install systemd-boot
    cp -r /boot/* /boot1
    cp -r /boot/* /boot2
    bootctl --path=/boot1 install
    bootctl --path=/boot2 install
    
  • patch sdboot-manage and create manjaro entries
    cp /usr/bin/sdboot-manage ~/sdboot-manage
    # patch sdboot-manage so it works with directories other than /boot or /efi
    sed -i -E 's/^(bootctl=)(.*)$/\[\[ ! -z \$2 \]\] \&\& \[\[ ! \$2 =~ --esp-path=\.\+ \]\] \&\& exit 1\n\1"\2 ""\$2"/g' ~/sdboot-manage
    sed -i -E 's/^(.+[^$/])bootctl(.*)$/\1\$bootctl\2/g' ~/sdboot-manage
    ~/sdboot-manage gen --esp-path=/boot1 # create manjaro entries on /boot1
    ~/sdboot-manage gen --esp-path=/boot2 # create manjaro entries on /boot2
    
  • check sdboot-manage work:
    bootctl --path=/boot1
    bootctl --path=/boot2
    
  • start sshd and enable root login (add PermitRootLogin yes to /etc/ssh/sshd_config):
    sed -i -E 's/^(#PermitRootLogin.*)$/PermitRootLogin yes\n\1/g' /etc/ssh/sshd_config
    systemctl enable sshd
    
  • Exit chroot and unmount filesystem
    exit
    umount -R /mnt
    zfs umount -a
    
  • set ZFS pool cachefile and export it:
    zpool set cachefile=/etc/zfs/zpool.cache $ZROOT # <-- zroot here is our $ZROOT
    zpool export $ZROOT
    
  • remove live media
    ### remove the live media
    reboot # or "poweroff"
    
  • reboot
  • after reboot, login as root
  • edit /etc/pacman.conf and scroll to #IgnorePkg and add:
    IgnorePkg = linux54-zfs  # so this package won't be updated
    
  • add more packages:
    pacman -S --noconfirm bash-completion pv
    

Disable nvidia driver, which causes slow boot ref1 ref2

  • journalctl -xb traces boot log and can identify which modules cause problems, for me, it was nouveau and i2c_nvidia_gpu
  • edit or create /etc/modprobe.d/blacklist-nvidia-nouveau.conf and add
    blacklist nouveau
    options nouveau modeset=0
    
  • edit or create /etc/modprobe.d/blacklist-i2c-nvidia-gpu.conf and add blacklist i2c_nvidia_gpu
  • sudo update-initramfs -u
  • sudo reboot -- it should boot a lot faster!

Use systemd-networkd to configure static IP address and/or network bridge

  • disable dhcpcd and NetworkManager
    systemctl disable --now dhcpcd.service
    systemctl disable --now NetworkManager.service
    
  • create bridge at /etc/systemd/network/br0.netdev:
    cat > /etc/systemd/network/br0.netdev << EOF
    [NetDev]
    Name=br0
    Kind=bridge
    EOF
    
  • bind ethernet to bridge in /etc/systemd/network/br0.network
    cat > /etc/systemd/network/br0.network << EOF
    [Match]
    Name=br0
    
    [Network]
    Address=192.168.1.11/24
    Gateway=192.168.1.1
    DNS=192.168.1.4
    DNS=192.168.1.10
    DNS=192.168.1.1
    EOF
    
  • bind ethernet to bridge in /etc/systemd/network/eno1.network
    cat > /etc/systemd/network/eno1.network << EOF
    [Match]
    Name=eno1
    
    [Network]
    Bridge=br0
    EOF
    
  • start systemd-networkd.service:
    systemctl enable --now systemd-networkd.service
    
  • The new settings will take effect immediately

Installing qemu libvirt

  • install packages:
    pacman -S --noconfirm qemu libvirt virt-manager ovmf
    usermod -aG libvirt <username> # this user will use virt-manager
    systemctl enable --now libvirtd.service
    
  • for <username>/.bashrc add:
    export DISPLAY=xserver_ip_address:0.0
    # HiDPI for QT software
    export QT_SCALE_FACTOR=2
    # HiDPI for GTK/GDK software
    export GDK_SCALE=2
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment