Trying to speed up fedora installation and configuration - a journey towards automation with kickstart and Ansible

Hello all,

Happy fedora user since f33/34, I’m getting tired of reinstalling and re-configuring fedora workstation every 6 months.

After some research, I came to the conclusion that my best bet was to try to learn how to use kickstart files and Ansible.

After days of researching and trials and errors, I got a first success toward automating the installation of fedora workstation (configured my way) with a kickstart file.

As the research part was quite painful, given the state of documentation and my level of (non-)expertise, I thought it might be useful to others to document the way of getting this to work I’ve found until now.

Steps:

  1. Generating a kickstart file with the options one would choose during anaconda install:
    a. Create a VM, provide it with the .iso (I went with the everything network installer) and provide it with an empty usb flash drive (so as to force the installer to input an “ignoredisk” option in the kickstart file, will be usefull later).
    b. Complete the installation, reboot.
    c. Copy /root/anaconda-ks.cfg to your flash drive.
    d. Shutoff VM.
    e. Your anaconda-ks.cfg should look like this (identifying information replaced):
# Generated by Anaconda 39.32.6
# Generated by pykickstart v3.48
#version=DEVEL
# Use graphical install
graphical

# Keyboard layouts
keyboard --vckeymap=XX-XX --xlayouts='XX (XX)'
# System language
lang XX_XX.UTF-8

%packages
@^workstation-product-environment

%end

# Run the Setup Agent on first boot
firstboot --enable

# Generated using Blivet version 3.8.1
ignoredisk --only-use=vda
# Partition clearing information
clearpart --none --initlabel
# Disk partitioning information
part / --fstype="ext4" --ondisk=vda --size=15360 --label=p3 --encrypted --luks-version=luks2
part /boot/efi --fstype="efi" --ondisk=vda --size=1024 --fsoptions="umask=0077,shortname=winnt" --label=p1
part /home --fstype="ext4" --ondisk=vda --size=23447 --label=p4 --encrypted --luks-version=luks2
part /boot --fstype="ext4" --ondisk=vda --size=1126 --label=p2

timesource --ntp-server=time.cloudflare.com --nts
timesource --ntp-server=ntppool1.time.nl --nts
timesource --ntp-server=nts.netnod.se --nts
timesource --ntp-server=ptbtime1.ptb.de --nts
# System timezone
timezone XX/XXXX --utc

#Root password
rootpw --lock
user --groups=wheel --name=user --password=***my-pw-hash*** --iscrypted --gecos="***my-username***"
  1. Make your kickstart file able to start an installation:
    a. Rename your USB flash drive to OEMDRV (so the installer will look for a ks.cfg file on it at install start).
    b. Rename your anaconda-ks.cfg file to ks.cfg(so the installer can use it).
    c. customise your kickstart file (I just added /removed some packages for now), like this:
# Generated by Anaconda 39.32.6
# Generated by pykickstart v3.48
#version=DEVEL
# Use graphical install
graphical

# Keyboard layouts
keyboard --vckeymap=XX-XX --xlayouts='XX (XX)'
# System language
lang XX_XX.UTF-8

%packages
@^workstation-product-environment
ansible
keepassxc
virt-manager
yubikey-manager-qt
-gnome-weather

%end

# Run the Setup Agent on first boot
firstboot --enable

# Generated using Blivet version 3.8.1
ignoredisk --only-use=vda
# Partition clearing information
clearpart --none --initlabel
# Disk partitioning information
part / --fstype="ext4" --ondisk=vda --size=15360 --label=p3 --encrypted --luks-version=luks2
part /boot/efi --fstype="efi" --ondisk=vda --size=1024 --fsoptions="umask=0077,shortname=winnt" --label=p1
part /home --fstype="ext4" --ondisk=vda --size=23447 --label=p4 --encrypted --luks-version=luks2
part /boot --fstype="ext4" --ondisk=vda --size=1126 --label=p2

timesource --ntp-server=time.cloudflare.com --nts
timesource --ntp-server=ntppool1.time.nl --nts
timesource --ntp-server=nts.netnod.se --nts
timesource --ntp-server=ptbtime1.ptb.de --nts
# System timezone
timezone XX/XXXX --utc

#Root password
rootpw --lock
user --groups=wheel --name=user --password=***my-pw-hash*** --iscrypted --gecos="***my-username***"
  1. Attempt installation with kickstart file:
    a. Create a VM, provide it with the .iso (I went with the everything network installer) and provide it with your OEMDRV named USB flash drive, containing your customised ks.cfg file.
    b. In grub, select install (the installer detects the OEMDRV drive and the contained ks.cfg file automatically and start your configuration (including username password, but, for some reason, not the disk encryption password which you’ll be prompted to input as only input during install)
    c. Once installation is complete, reboot.
    d. Tadaa, welcome in your fresh automated install!

  2. Generate your personal Ansible playbook:
    a. create a file named my-playbook.yml.
    b. Configure it following this fedora magazine article.
    c. to get ideas about your DConf parameters, type dconf dump / > dump.dconf in your terminal on a fully configured system. The resulting dump.dconf file contains the parameters you need to configure in your my-playbook.yml, following the syntax layed out in the fedora magazine article.
    d. Your file should look like this:

- hosts: localhost
  tasks:
#Enable ProtonVPN repo & install Protonvpn
    - name: Download ProtonVPN repository file
      become: yes
      command: wget https://repo.protonvpn.com/fedora-39-stable/protonvpn-stable-release/protonvpn-stable-release-1.0.1-2.noarch.rpm
    - name: Enable ProtonVPN repository file
      become: yes
      command: sudo dnf install -y ./protonvpn-stable-release-1.0.1-2.noarch.rpm
    - name: Install ProtonVPN
      become: yes
      command: sudo dnf install -y --refresh proton-vpn-gnome-desktop
#Enable Brave Browser repo & install Brave Browser
    - name: Install dependencies
      become: yes
      command: sudo dnf install -y --refresh dnf-plugins-core
    - name: Add Brave Browser repository
      become: yes
      command: sudo dnf config-manager --add-repo https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo
    - name: Import Brave Browser Keys
      become: yes
      command: sudo rpm --import https://brave-browser-rpm-release.s3.brave.com/brave-core.asc
    - name: Install Brave Browser
      become: yes
      command: sudo dnf install -y --refresh brave-browser
#Install pyton-library psutil as dependency for DConf module to work
    - name: Install DConf Mod Dependency python3-psutil
      become: yes
      command: sudo dnf install -y --refresh python3-psutil
#DConf Module:
    - name: Enable Night Light
      dconf:
        key: /org/gnome/settings-daemon/plugins/color/night-light-enabled
        value: true
    - name: Disable Automatic Night Light Schedule
      dconf:
        key: /org/gnome/settings-daemon/plugins/color/night-light-schedule-automatic
        value: false
    - name: Set Night Light Schedule From
      dconf:
        key: /org/gnome/settings-daemon/plugins/color/night-light-schedule-from
        value: 18.0
    - name: Set Night Light Schedule To
      dconf:
        key: /org/gnome/settings-daemon/plugins/color/night-light-schedule-to
        value: 7.0
    - name: Disable Gnome Text Editor Line Highlight
      dconf:
        key: /org/gnome/TextEditor/highlight-current-line
        value: false
    - name: Disable Gnome Text Editor Show Grid
      dconf:
        key: /org/gnome/TextEditor/show-grid
        value: false
    - name: Set Gnome Text Editor Show Line Numbers
      dconf:
        key: /org/gnome/TextEditor/show-line-numbers
        value: true
    - name: Disable Gnome Text Editor Show Map
      dconf:
        key: /org/gnome/TextEditor/show-map
        value: false
    - name: Set Gnome Text Editor Font
      dconf:
        key: /org/gnome/TextEditor/use-system-font
        value: true
    - name: Set Gnome Calendar Weekdate
      dconf:
        key: /org/gnome/desktop/calendar/show-weekdate
        value: true
    - name: Disable Gnome Clock Show Seconds
      dconf:
        key: /org/gnome/desktop/interface/clock-show-seconds
        value: false
    - name: Set Gnome Clock Show Weekday
      dconf:
        key: /org/gnome/desktop/interface/clock-show-weekday
        value: true
    - name: Set Gnome Show Battery Percentage
      dconf:
        key: /org/gnome/desktop/interface/show-battery-percentage
        value: true
    - name: Disable Gnome Toolkit Accessibility
      dconf:
        key: /org/gnome/desktop/interface/toolkit-accessibility
        value: false
    - name: Disable Gnome Media Handling Autorun
      dconf:
        key: /org/gnome/desktop/media-handling/autorun-never
        value: true
    - name: Disable Gnome Notifications on Lockscreen
      dconf:
        key: /org/gnome/desktop/notifications/show-in-lock-screen
        value: false
    - name: Set Touchpad Edge Scrolling
      dconf:
        key: /org/gnome/desktop/peripherals/touchpad/edge-scrolling-enabled
        value: true
    - name: Disable Touchpad Natural Scrolling
      dconf:
        key: /org/gnome/desktop/peripherals/touchpad/natural-scroll
        value: false
    - name: Set Touchpad Tap to Click
      dconf:
        key: /org/gnome/desktop/peripherals/touchpad/tap-to-click
        value: true
    - name: Disable Touchpad Two Finger Scrolling
      dconf:
        key: /org/gnome/desktop/peripherals/touchpad/two-finger-scrolling-enabled
        value: false
    - name: Disable Camera
      dconf:
        key: /org/gnome/desktop/privacy/disable-camera
        value: true
    - name: Disable Microphone
      dconf:
        key: /org/gnome/desktop/privacy/disable-microphone
        value: true
    - name: Disable Automatic Problem Reporting
      dconf:
        key: /org/gnome/desktop/privacy/report-technical-problems
        value: false
#    - name: Set Nautilus Default View as List
#      dconf:
#        key: /org/gnome/nautilus/preferences/default-folder-viewer
#        value: 'list-view'
    - name: Disable Software App Automatic Updates
      dconf:
        key: /org/gnome/software/download-updates
        value: false
    - name: Disable Software App Automatic Updates Notification
      dconf:
        key: /org/gnome/software/download-updates-notify
        value: false
    - name: Disable Software App First-Run
      dconf:
        key: /org/gnome/software/first-run
        value: false
    - name: Disable Location
      dconf:
        key: /org/gnome/system/location/enabled
        value: false
  1. Initial configuration of system with Ansible:
    a. Put Ansible file on your system.
    b. In terminal, type: ansible-playbook -K /path-to-ansible-playbook/my-playbook.yml, when asked enter become (admin) password.
    c. Tadaa, enjoy your configured system!

Remaining to solve (optionally):

  • Also automate disk encryption password input in the kickstart file;
  • modify the kickstart file for it to work for bare-metal install (drives configuration).

Hope this is useful to others.

Let me know if you have advice’s or improvements to the method.

Best regards

Why are you having to reinstall so often?

1 Like

I read somewhere, a while ago, that it’s best to do a fresh install instead of an upgrade to make sure all the new tech of a new version is configured correctly (like when fedora switched from ext4 to btrfs for example).

Not really necessary in my opinion. Sure some things like the btrfs migration may not apply in a normal upgrade, but if you’re technologically interested about such things, you could probably work around them without a full reinstall or just reinstall when there’s something worth doing it for. Nevertheless, it should cut down your frequency of reinstalls; I don’t think reinstalling the entire system every 6 months is the intended workflow by Fedora.

1 Like

@nhnh that might have been the recommendation 10-20 years ago but is no longer necessary or recommended, see the first link below. The sense I have gotten over the years is the leaders of the project would prefer we upgrade rather than nuking and paving because that is how everyday users would do it, and we want Fedora to be accessible to anyone.

The primary reason to nuke and pave would be to get new defaults, like you brought up with the transition from ext4 to btrfs. Not every release is going to necessarily have new defaults and not all new defaults may be worth installing depending on your perspective. In most cases the old default is still a supported configuration, as with using ext4.

A good way to approach may be to look at the changeset of the release and determine for yourself if you want to reinstall. If you want to help the project perhaps even consider doing both a normal upgrade, note any bugs, then do a clean install to test any new defaults. If you want to be a normal user who does normal upgrades, you should be able to do that too!

https://fedoraproject.org/wiki/Releases/39/ChangeSet

1 Like

One thing did go unsaid with us giving our thoughts… nice job on documenting the steps for reinstallation with Kickstart and Ansible!

2 Likes

This is the only change in a very long time that you might (not must) want to reinstall for.

1 Like

There are very few changes that are likely to cause problems when using the dnf system-upgrade procedure for version updates. Even the switch from ext4 to btrfs did not require a reinstall since ext4 is still very much supported and it is possible, with care, to change the file system without doing a full reinstall.

I only did a reinstall with F39 since I took the opportunity to upgrade from HDD to NVME for my boot device.

@guiltydoggy @mpphill2 @barryascott @computersavvy

Thanks for your inputs, of course it is not necessary to reinstall each release, but one might still want to for a lot of different reasons (like getting the new defaults, making sure no hardening changes are lost during update, having a new machine, providing VM’s often for your home server and so on).

I feel like my point has been missed (but by @mpphill2 , thanks): I’m mostly trying to automate installation and initial configuration of fedora and, as the documentation found was outdated / incomplete / too complicated, I’ve thought I’ll share my solution to help someone also wanting to do this.

I’ve changed the title to better reflect that.

Best regards

1 Like

Bear in mind that each new release may well need you to debug your kickstart and initial config as packages improve and change.

In production environments fully automated installation and config is the norm in my experience. I have always seen this done with PXE boot.