Preperation

  • Acquire a Fedora Workstation image.
  • Create a bootable USB with that image.
  • Open a terminal and acquire root.
  • Disable enforcing selinux with setenforce 0, this is only required for setting the password for the new user that you’ll create.
  • Acquire the genfstab script which makes it easier to create the /etc/fstab. The script is originally from Arch Install Scripts, but for convenience you can acquire it and add executable permission with this command:
    wget https://github.com/glacion/genfstab/releases/download/1.0/genfstab; chmod +x genfstab

Partitioning

If you are not familiar with partitioning, get comfortable with it.
For reference, these are the partitions i use for testing in a VM with a drive of 12GiB:

  • /dev/sda1 ESP partition of size 100MiB, mounted on /boot.
  • /dev/sda2 swap partition of size 1.9GiB.
  • /dev/sda3 XFS partition of size 10GiB, mounted on /.

I chose /mnt to be my install root, you may change to your preference but be sure to update the commands accordingly.

Installing The Base System

Assuming that your partitions are mounted on /mnt, install the base system like below:

dnf install \
--installroot=/mnt \
--releasever=30 \
--setopt=install_weak_deps=False \
--setopt=keepcache=True \
--assumeyes \
--nodocs \
systemd dnf glibc-langpack-en passwd rtkit policycoreutils \
NetworkManager audit firewalld selinux-policy-targeted kbd zchunk sudo \
vim-minimal systemd-udev rootfiles less iputils deltarpm sqlite lz4 xfsprogs
  • releasever=30 Install fedora 30, change if desired.
  • setopt=install_weak_deps=False Do not install weak dependencies.
  • glibc-langpack-en English langpack for glibc, in order to have a localized system install glibc-langpack-<LANGCODE> if no langpack is specified to install, dnf will install glibc-all-langpacks package which costs 100MB alone compared to installing them seperately which costs around 1MB per langpack. Use a different langcode if you want to use a different locale.
  • xfsprogs because i used an XFS root, change or add more filesystem tools depending on your setup.

Configuration

  • Setup machine id and configure the system locale, keymap, hostname on your new system;

    systemd-firstboot \
    --root=/mnt \
    --locale=C.UTF-8 \
    --keymap=us \
    --hostname=fedora \
    --setup-machine-id
    
  • Generate fstab and save it in your new system, replace -U with -L if you want to use labels instead of UUIDs in your /etc/fstab

    ./genfstab -U /mnt >> /mnt/etc/fstab
    
  • Chroot without booting and add an user

    systemd-nspawn -D /mnt
    useradd -c "<YOUR_FULL_NAME>" -m -g users -G wheel -s /bin/bash <YOUR_USERNAME>
    passwd <YOUR_USERNAME>
    exit
    
  • Boot the system as a container

    systemd-nspawn -bD /mnt
    

    Login with the newly created user and get root with sudo -s, commands until the exit will be executed in the container.

  • DNF configuration

    • Delete unnecessary repositories with rm -f /mnt/etc/yum.repos.d/*{*cisco*,*testing*,*modular*}*

    • Add following options to /etc/dnf/dnf.conf

      install_weak_deps=False
      keepcache=True
      tsflags=nodocs
      
  • Install the bootloader

    systemd-boot is a fairly minimal and gets the job done without much configuration. If you opt to use GRUB or something similar, you are on your own.

    bootctl install
    
  • Add any required filesystem to dracut configuration

    Dracut needs to know the root filesystem so that it can mount it when booting, it doesn’t need to know about other filesystems that are in the system. Open /etc/dracut.conf.d/fs.conf and add the root filesystem like below:

    filesystems+="xfs"
    
  • Install the kernel

    dnf install kernel
    
  • Configure the bootloader

    When you installed the kernel, the bootloader created an entry at /boot/loader/entries/<MACHINE_ID>-<KVER>.conf, however it just copied the boot parameters of the live system.

    The options part of the file shows something like this:

    options    BOOT_IMAGE=/images/pxeboot/vmlinuz
    root=live:CDLABEL=Fedora-WS-Live-30-1-2 rd.live.image quiet
    

    Change it to something like this:

    options    root=UUID=<UUID_OF_ROOT_PARTITION> ro quiet
    

    Add the kernel parameters that you want to include here.

  • Exit the container with poweroff

  • EFI Entry

    Create an EFI entry using efibootmgr like below.
    Note: Make sure that the -d and -p arguments point to the ESP of your system.

    efibootmgr -d /dev/sda \
    -p 1 \
    -c \
    -L "Fedora" \
    -l /EFI/systemd/systemd-bootx64.efi
    
  • Clean up and reboot

    umount -R /mnt
    reboot
    

Tweaks

  • Dracut

    • Install binutils with dnf install binutils so that initramfs can be stripped.

    • Open /etc/dracut.conf.d/custom.conf and add the lines below:

       drivers+="i915"
       compress="lz4"
       hostonly="yes"
      
      • drivers+="i915" add i915 driver to initramfs for early Kernel Mode Setting.
      • compress="lz4" use lz4 for the initramfs compression.
      • hostonly="yes" generate images that works with this host only.
    • Rebuild the initramfs with dracut -fv

  • Time

    • Set the timezone with timedatectl set-timezone Europe/Istanbul
    • Enable NTP with timedatectl set-ntp true