## Installing Manjaro on ZFS root using systemd-boot \[UEFI only\]
References:\[ [manjaro-cli-install](https://forum.manjaro.org/t/howto-install-manjaro-using-cli-only/108203) | [john_ransden-arch on ZFS](https://ramsdenj.com/2016/06/23/arch-linux-on-zfs-part-2-installation.html#efi-bootloader) | [arch-systemd-boot-wiki](https://wiki.archlinux.org/index.php/Systemd-boot) \]

- Start from manjaro architect \[ [download](https://manjaro.org/download/official/architect/) \]
- 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](https://github.com/zfsonlinux/zfs/issues/8538) \]
  ```
  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
  ```