Linux-libre Kernel installation script for Ubuntu.
Hello, everyone.
I would like to share with the community a script that will install the GNU Linux-libre Kernel on Ubuntu 24.04 LTS.
The manual installation method described on the FSF Latin America website https://www.fsfla.org/ikiwiki/selibre/linux-libre/liberty.en.html (many thanks to Jason Self). It is very simple and works reliably, but there are some nuances that not everyone knows about and that are not described on the website.
Of course, this method is an alternative, since after installing the Linux-libre Kernel, programs from the Ubuntu repository are not free if you connect the free Trisquel repository, the question arises: why do all this if there is Trisquel ISO https://trisquel.info/en/download ))
Let's consider this a backup workaround))
So what does this script do and how does it work:
It is assumed that you are a root user and have Ubuntu 24.04 LTS installed on your server (tested on this version).
You log into the server (VPS) via SSH, for example:
$ ssh root@ip_address_of_your_vps
Before running the script, you need to set up cron on the server (vps)
# crontab -e @reboot /bin/bash /root/install_libre_linux.sh
Copy this script to the server (VPS) and make your script executable:
# nano install_libre_linux.sh (copy the script and save it) # chmod +x install_libre_linux.sh
Important: After answering the question:
Reboot now so the system boots the new Linux‑Libre kernel?
You will be logged out of the server (this is normal) as the server will reboot with the new Linux-Libre kernel. Run the script again and continue with the installation.
Script features:
• Interactive Linux‑Libre installer with colorized output
• Prompts before every action (questions in yellow)
• Retries on failure
• Reboots after installing the new kernel, then optionally removes old kernels
The script code turned out to be very large. If you have the time and desire, you can reduce the code, improve it, modify it, etc.
I checked the installation and it works. After installing the script, you will have the latest GNU Linux-libre Kernel. I chose number 2 for the kernel
2) linux-image-6.6.65-gnu-rt47-rc2
#!/usr/bin/env bash
# -------------------------------------------------
# Installing the Linux‑Libre Kernel GPL-3.0
# -------------------------------------------------
# • Interactive Linux‑Libre installer with colourised output
# • Prompts before every action (questions in yellow)
# • Retries on failure
# • Reboots after installing the new kernel, then optionally removes old kernels
# ------------------------------------------------------------------
# Before installation, configure "cron"
# # crontab -e
# At the very bottom of the configuration file, insert this line with the path to your script, for example:
# @reboot /bin/bash /root/vps_setup.sh
# -----------------------------------------------
#
#
set -euo pipefail
# -------------------- Colour palette --------------------
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
CYAN=$(tput setaf 6)
MAGENTA=$(tput setaf 5)
WHITE=$(tput setaf 7)
BRIGHT_GREEN=$(tput setaf 2)
BRIGHT_GREEN="${BRIGHT_GREEN}$(tput bold)"
RESET=$(tput sgr0)
# -------------------------------------------------
# Paths to flag files
# -------------------------------------------------
REBOOT_FLAG="/root/vps_reboot_done"
CLEAR_FLAG="/root/vps_clear_kernel_done"
# -------------------- helpers --------------------
log() { printf "${BLUE}[${WHITE}%s${BLUE}]${RESET} %b\n" "$(date +%T)" "$*"; }
ok() { printf "${GREEN}[✔] %s${RESET}\n" "$*"; }
fail(){ printf "${RED}[✖] %s${RESET}\n" "$*"; }
warn(){ printf "${YELLOW}[⚠] %s${RESET}\n" "$*"; }
ask_yes_no() {
while true; do
printf "${BLUE}[INFO] ${RESET}${YELLOW}%s${RESET} [Y/n]: ${RESET}" "$1"
read -r ans
case "$ans" in
[Yy]*) return 0 ;;
[Nn]*) return 1 ;;
*) echo "Please answer y or n." ;;
esac
done
}
retry_cmd() {
local description="$1"
shift
local cmd=("$@")
while true; do
if "${cmd[@]}"; then
ok "$description succeeded"
return 0
else
fail "$description failed"
if ask_yes_no "Retry $description?"; then
continue
else
fail "Aborting."
exit 1
fi
fi
done
}
# -------------------------------------------------
# ONLY run the installation steps if we have NOT rebooted yet
# -------------------------------------------------
if [[ ! -f "$REBOOT_FLAG" ]]; then
# -------------------- 1 System update --------------------
if ask_yes_no "Do you want to install the Linux‑Libre kernel?"; then
retry_cmd "Update package lists" apt update -y
retry_cmd "Upgrade packages" apt upgrade -y
retry_cmd "Full upgrade (dist-upgrade)" apt dist-upgrade -y
retry_cmd "Remove obsolete packages" apt autoremove -y
retry_cmd "Clean package cache" apt autoclean -y
fi
# -------------------- 2 Download & install keyring --------------------
DEB="liberty-archive-keyring_1.2_all.deb"
URL="https://linux-libre.fsfla.org/pub/linux-libre/liberty/pool/main/libe/liberty-archive-keyring/${DEB}"
if ask_yes_no "Download and install the Liberty keyring?"; then
retry_cmd "download keyring" wget -q "$URL" -O "/tmp/$DEB"
retry_cmd "install keyring" dpkg -i "/tmp/$DEB"
rm -f "/tmp/$DEB"
fi
# -------------------- 3 Verify keyring --------------------
if ask_yes_no "Verify that the correct GPG keys are installed?"; then
retry_cmd "list GPG keys" \
gpg --no-default-keyring --keyring /usr/share/keyrings/liberty-archive-keyring.gpg --list-keys
fi
# -------------------- 4 Refresh repository --------------------
if ask_yes_no "Refresh APT package lists?"; then
retry_cmd "apt-get update" apt-get update
fi
# -------------------- 5 Choose kernel --------------------
if ask_yes_no "Show available Linux‑Libre kernels and let you pick one to install?"; then
mapfile -t kernels < <(
apt-cache search -n '^(linux-(image|headers)-.*(gnu|libre)|linux-libre-)' |
cut -d' ' -f1 |
sort -u
)
if (( ${#kernels[@]} == 0 )); then
warn "No Linux‑Libre kernels found."
exit 1
fi
echo -e "${CYAN}Available kernels:${RESET}"
for i in "${!kernels[@]}"; do
printf " %2d) %s\n" $((i+1)) "${kernels[i]}"
done
echo " 0) Cancel"
while true; do
printf "${YELLOW}Enter the number of the kernel to install [0-%d]: ${RESET}" "${#kernels[@]}"
read -r choice
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 0 && choice <= ${#kernels[@]} )); then
break
fi
warn "Invalid selection."
done
(( choice == 0 )) &selected_kernel="${kernels[choice-1]}"
log "Selected kernel: $selected_kernel"
retry_cmd "install $selected_kernel" apt-get install -y "$selected_kernel"
else
log "User declined to view/install Linux‑Libre kernels; exiting."
exit 0
fi
# -------------------- 6 Set GRUB_DEFAULT to the new GNU kernel --------------------
set_grub_default() {
mapfile -t entries < <(
awk -F"'" '/menuentry/ {print $2}' /boot/grub/grub.cfg |
grep -i gnu |
while IFS= read -r title; do
if [[ "$title" != *">"* ]]; then
printf 'Advanced options for Ubuntu>%s\n' "$title"
else
printf '%s\n' "$title"
fi
done
)
if (( ${#entries[@]} == 0 )); then
warn "No GRUB menu entries containing “gnu” were found."
return 1
fi
selected_entry="${entries[0]}"
log "Setting GRUB_DEFAULT to \"$selected_entry\""
if grep -q '^GRUB_DEFAULT=' /etc/default/grub; then
escaped=$(printf '%s' "$selected_entry" | sed 's/"/\\"/g')
sed -i "s|^GRUB_DEFAULT=.*|GRUB_DEFAULT=\"${escaped}\"|" /etc/default/grub
else
echo "GRUB_DEFAULT=\"${selected_entry}\"" >> /etc/default/grub
fi
retry_cmd "update-grub" update-grub
}
set_grub_default
# -------------------------------------------------
# Phase 1 – first run: ask to reboot
# -------------------------------------------------
if ask_yes_no "Reboot now so the system boots the new Linux‑Libre kernel?"; then
touch "$REBOOT_FLAG"
log "Reboot flag created – rebooting now…"
/sbin/reboot
exit 0
else
log "No reboot will be performed."
exit 0
fi
fi # ← end of “if [[ ! -f $REBOOT_FLAG ]]”
# -------------------------------------------------
# Kernel‑cleanup block (run after a successful reboot)
# -------------------------------------------------
if [[ -f "$REBOOT_FLAG" && ! -f "$CLEAR_FLAG" ]]; then
if ask_yes_no "Remove old non‑gnu kernels now that the new kernel is installed?"; then
touch "$CLEAR_FLAG"
log "Clear‑kernel flag created – starting cleanup…"
# -------------------------------------------------
# Gather old non‑gnu kernels
# -------------------------------------------------
mapfile -t old_kernels < <(
dpkg -l 'linux-image*' 2>/dev/null |
awk '/^ii/ {print $2}' |
grep -vi 'gnu' || true
)
if (( ${#old_kernels[@]} == 0 )); then
warn "No non‑gnu kernels to remove."
else
echo -e "${CYAN}The following packages will be removed:${RESET}"
printf " %s\n" "${old_kernels[@]}"
# -------------------------------------------------
# Purge the old kernels
# -------------------------------------------------
retry_cmd "purge old kernels" \
apt-get --purge autoremove -y "${old_kernels[@]}"
# -------------------------------------------------
# Clean the apt cache
# -------------------------------------------------
retry_cmd "apt autoclean" apt-get autoclean -y
fi
# -------------------------------------------------
# Clean residual files in /boot
# -------------------------------------------------
boot_dir="/boot"
log "Cleaning residual files in $boot_dir …"
# Versions we must keep (current GNU kernel + any other GNU kernels)
mapfile -t keep_versions < <(
dpkg -l 'linux-image-*gnu*' 2>/dev/null |
awk '/^ii/ {print $2}' |
sed 's/^linux-image-//'
)
keep_versions+=("$(uname -r)")
shopt -s nullglob
for file in "$boot_dir"/{vmlinuz,initrd.img,config,System.map}-*; do
ver=${file##*-}
if printf '%s\n' "${keep_versions[@]}" | grep -qx "$ver"; then
log "Preserving $file"
else
log "Removing $file"
rm -f -- "$file"
fi
done
shopt -u nullglob
# Remove stale *.old symlinks
for link in "$boot_dir"/{vmlinuz,initrd.img}.old; do
if [[ -L $link && ! -e $(readlink -f "$link") ]]; then
log "Removing stale symlink $link"
rm -f -- "$link"
fi
done
# -------------------------------------------------
# Final housekeeping – ensure no leftover packages
# -------------------------------------------------
retry_cmd "final apt autoremove" apt-get autoremove -y
retry_cmd "final apt autoclean" apt-get autoclean -y
ok "Kernel cleanup finished."
else
warn "Kernel not cleared."
fi
fi
# -------------------------------------------------
# Final status output – show the active kernel
# -------------------------------------------------
echo -e "\n${GREEN}✅ Current kernel:${RESET} $(uname -r)" Why not use freesh instead? It is being maintained.
https://www.fsfla.org/ikiwiki/selibre/linux-libre/freesh.en.html
Also, why not make your script be GPL-3.0-or-later?
Hello Jxself. Thank you for your reply.
Yes, of course, let the script have the most liberal license available.
I have no objection to GPL-3.0-or-later.
As for the key, I chose the FSF website because when testing the script, there were many problems with downloading from this site https://trisquel.info/files/trisquel-archive-signkey.gpg something to do with processing DNS requests.
And the FSF has very fast servers.
https://linux-libre.fsfla.org/pub/linux-libre/freesh/pool/main/f/freesh-archive-keyring/freesh-archive-keyring_1.3_all.deb
(thanks for the information, I will replace it in my script)
I also don't mind replacing the key download source in the script with the one you suggest.
Today I tested another script (part two). It is the installation of Trisquel repositories in Ubuntu 24.04 LTS.
Everything works, but after a while I see two new updates, one of which is grub (Trisquel)
and errors occur during installation, even when I specify a specific repository. Maybe this is too much ))
It's better to just install the Trisquel ISO, but I'm really looking forward to the CLI version.
# apt list --upgradable grub-efi-amd64-bin/ecne,ecne-updates 2.12-1ubuntu7.3trisquel10 amd64 [upgradable from: 2.12-1ubuntu7.3] # apt-get install grub-efi-amd64-bin=2.12-1ubuntu7.3trisquel10
# ------------------------------------------------------- # Installing Trisquel repositories in Ubuntu 24.04 LTS # # @D-16 With respect to the community | GPL-3.0-or-later # ------------------------------------------------------------ # #!/usr/bin/env bash set -euo pipefail # ------------------------------------------------- # Trisquel APT repository setup # ------------------------------------------------- TRISQUEL_SRC="/etc/apt/sources.list.d/trisquel.sources" # Write the source file (overwrites if it exists) tee "$TRISQUEL_SRC" > /dev/null <<'EOF' # Trisquel repositories for supported software and updates Types: deb URIs: https://mirror.fsf.org/trisquel/ Suites: ecne ecne-updates ecne-security Components: main Signed-By: /usr/share/keyrings/trisquel-archive-keyring.gpg # Source package repositories Types: deb-src URIs: https://mirror.fsf.org/trisquel/ Suites: ecne ecne-updates ecne-security Components: main Signed-By: /usr/share/keyrings/trisquel-archive-keyring.gpg # Optional backports repository (disabled by default) Enabled: no Types: deb deb-src URIs: https://mirror.fsf.org/trisquel/ Suites: ecne-backports Components: main Signed-By: /usr/share/keyrings/trisquel-archive-keyring.gpg EOF # ------------------------------------------------- # 2. Import the Trisquel signing key into a dedicated keyring # ------------------------------------------------- KEYRING="/usr/share/keyrings/trisquel-archive-keyring.gpg" KEYID="B138CA450C05112F" KEY_URL="https://mirror.fsf.org/trisquel/trisquel-archive-signkey.gpg" # Ensure the keyring file exists and has correct permissions touch "$KEYRING" chmod 644 "$KEYRING" # Download the public key file curl -fsSL "$KEY_URL" -o "/tmp/trisquel-archive-signkey.gpg" # Import the key into the dedicated keyring gpg --no-default-keyring --keyring "$KEYRING" --import "/tmp/trisquel-archive-signkey.gpg" echo "Verifying imported key..." gpg --no-default-keyring --keyring "$KEYRING" --list-keys --fingerprint "$KEYID" # ------------------------------------------------- # 3. Refresh APT metadata # ------------------------------------------------- echo "Running apt update..." apt update # ------------------------------------------------- # 4. (Optional) Upgrade packages from the newly added repos # ------------------------------------------------- read -rp "Run a full upgrade now? [y/N] " answer if [[ "$answer" =~ ^[Yy]$ ]]; then apt full-upgrade fi echo "Trisquel repository setup complete."
root@d-16:~# neofetch
.-/+oossssoo+/-. root@d-16
`:+ssssssssssssssssss+:` --------
-+ssssssssssssssssssyyssss+- OS: Ubuntu 24.04.4 LTS x86_64
.ossssssssssssssssssdMMMNysssso. Host: VPS
/ssssssssssshdmmNNmmyNMMMMhssssss/ Kernel: 6.6.65-gnu-rt47-rc2
+ssssssssshmydMMMMMMMNddddyssssssss+ Uptime: 10 mins
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Packages: 738 (dpkg)
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Shell: bash 5.2.21
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Resolution: 1024x768
ossyNMMMNyMMhsssssssssssssshmmmhssssssso Terminal: /dev/pts/0
ossyNMMMNyMMhsssssssssssssshmmmhssssssso CPU: AMD EPYC 7702P (1) @ 1.996GHz
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ GPU: 00:01.0 Red Hat, Inc. QXL paravirtual graphic card
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Memory: 162MiB / 1976MiB
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/
+sssssssssdmydMMMMMMMMddddyssssssss+
/ssssssssssshdmNNNNmyNMMMMhssssss/
.ossssssssssssssssssdMMMNysssso.
-+sssssssssssssssssyyyssss+-
`:+ssssssssssssssssss+:`
.-/+oossssoo+/-.
=====================================================================================================
root@d-16:~# neofetch
,o$$$o. root@d-16
,o$$Y"""Y$$b --------
,o$$$$$$o. ,$$' , Y$$b OS: Trisquel GNU/Linux Ecne (12.0) x86_64
,o$$$$$$$$$$$$o. :$ b Y$$. Host: VPS
,$$"' "Y$$$$o. 'b. ,b d$$$ Kernel: 6.6.65-gnu-rt47-rc2
$$' .d$$$$b '$$$$o 'Y$$$Y d$$$' Uptime: 15 mins
$$' q' 'b '$$$$$o._ _.o$$$$' Packages: 739 (dpkg)
.$$,_ _,d$ ,$$$$$$$$$$$$$$$$Y' Shell: bash 5.2.21
'$$$$aaa$$$' .$$$$$$$$$$$$$$' Resolution: 1024x768
"""" d$$$$"' Terminal: /dev/pts/0
d$$$' .d$$b. CPU: AMD EPYC 7702P (1) @ 1.996GHz
$$$$ .$" 'a$. GPU: 00:01.0 Red Hat, Inc. QXL paravirtual graphic card
$$$$ $b $$. Memory: 171MiB / 1976MiB
'$$$. '$b,,. $$$
'$$$. .$$'
'a$$$o._.o$$a'
'a$$$$a'
========================================================================================================
root@d-16:~# uname -a
Linux d-16 6.6.65-gnu-rt47-rc2 #1.0 SMP PREEMPT_RT Tue Sep 27 12:35:59 EST 1983 x86_64 x86_64 x86_64 GNU/Linux
root@d-16:~# cat /etc/os-release
NAME="Trisquel GNU/Linux"
VERSION="12.0, Ecne"
ID=trisquel
ID_LIKE=debian
PRETTY_NAME="Trisquel GNU/Linux Ecne (12.0)"
VERSION_ID="12.0"
VERSION_CODENAME="ecne"
UBUNTU_CODENAME="noble"
HOME_URL="https://trisquel.info/"
SUPPORT_URL="https://trisquel.info/wiki"
BUG_REPORT_URL="https://gitlab.trisquel.org/trisquel"
PRIVACY_POLICY_URL="https://trisquel.info/legal"
root@d-16:~# grub-install --version
grub-install (GRUB) 2.12-1ubuntu7.3trisquel10
root@d-16:~# grep -E "^\s*menuentry" /boot/grub/grub.cfg
menuentry_id_option="--id"
menuentry_id_option=""
menuentry 'UEFI Firmware Settings' $menuentry_id_option 'uefi-firmware' { The repo you installed is from the liberty repo which hasn't been updated in, like, a year. It's best to use the freesh repository because that is at least current and up to date.
I updated the script with the repository you recommended.
Newer Kernel (Freesh) => https://linux-libre.fsfla.org/pub/linux-libre/freesh/
#!/usr/bin/env bash
# -------------------------------------------------------
# Installing the Linux‑Libre Kernel on Ubuntu 24.04 LTS
#
# This script is licensed under GPL-3.0-or-later
#
# -----------------------------------------------------------
# • Interactive Linux‑Libre installer with colourised output
# • Prompts before every action (questions in yellow)
# • Retries on failure
# • Reboots after installing the new kernel, then optionally removes old kernels
#
# ------------------------------------------------------------------
# ** Before installation** - configure "cron" !
# # crontab -e
# At the very bottom of the configuration file, insert this line with the path to your script, for example:
# @reboot /bin/bash /root/vps.sh
#
# #chmod +x ./vps and run script
#
# -----------------------------------------------
set -euo pipefail
# -------------------- Colour palette --------------------
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
CYAN=$(tput setaf 6)
MAGENTA=$(tput setaf 5)
WHITE=$(tput setaf 7)
BRIGHT_GREEN=$(tput setaf 2)
BRIGHT_GREEN="${BRIGHT_GREEN}$(tput bold)"
RESET=$(tput sgr0)
# -------------------------------------------------
# Paths to flag files
# -------------------------------------------------
REBOOT_FLAG="/root/vps_reboot_done"
CLEAR_FLAG="/root/vps_clear_kernel_done"
# -------------------- helpers --------------------
#log() { printf "${BLUE}[${WHITE}%s${BLUE}]${RESET} %b\n" "$(date +%T)" "$*"; }
log() { printf "${GREEN}[${GREEN}success${GREEN}]${RESET} %b\n" "$*"; }
ok() { printf "${GREEN}[✔] %s${RESET}\n" "$*"; }
fail(){ printf "${RED}[✖] %s${RESET}\n" "$*"; }
warn(){ printf "${YELLOW}[⚠️] %s${RESET}\n" "$*"; }
ask_yes_no() {
while true; do
printf "${BLUE}[INFO] ${RESET}${YELLOW}%s${RESET} [Y/n]: ${RESET}" "$1"
read -r ans
case "$ans" in
[Yy]*) return 0 ;;
[Nn]*) return 1 ;;
*) echo "Please answer y or n." ;;
esac
done
}
retry_cmd() {
local description="$1"
shift
local cmd=("$@")
while true; do
if "${cmd[@]}"; then
ok "$description succeeded"
return 0
else
fail "$description failed"
if ask_yes_no "Retry $description?"; then
continue
else
fail "Aborting."
exit 1
fi
fi
done
}
# -------------------------------------------------
# ONLY run the installation steps if we have NOT rebooted yet
# -------------------------------------------------
if [[ ! -f "$REBOOT_FLAG" ]]; then
# -------------------- 1️⃣ System update --------------------
if ask_yes_no "Do you want to install the Linux‑Libre Kernel?"; then
retry_cmd "Update package lists" apt update -y
retry_cmd "Upgrade packages" apt upgrade -y
retry_cmd "Full upgrade (dist-upgrade)" apt dist-upgrade -y
retry_cmd "Remove obsolete packages" apt autoremove -y
retry_cmd "Clean package cache" apt autoclean -y
fi
# -------------------- 2️⃣ Download & install keyring --------------------
DEB="freesh-archive-keyring_1.3_all.deb"
URL="https://linux-libre.fsfla.org/pub/linux-libre/freesh/pool/main/f/freesh-archive-keyring/${DEB}"
if ask_yes_no "Download and install the Freesh keyring?"; then
retry_cmd "download keyring" wget -q "$URL" -O "/tmp/$DEB"
retry_cmd "install keyring" dpkg -i "/tmp/$DEB"
rm -f "/tmp/$DEB"
fi
# -------------------- 3️⃣ Verify keyring --------------------
if ask_yes_no "Verify that the correct GPG keys are installed?"; then
retry_cmd "list GPG keys" \
gpg --no-default-keyring --keyring /usr/share/keyrings/freesh-archive-keyring.gpg --list-keys
fi
# -------------------- 4️⃣ Refresh repository --------------------
if ask_yes_no "Refresh APT package lists?"; then
retry_cmd "apt-get update" apt-get update
fi
# -------------------- 5️⃣ Choose kernel --------------------
if ask_yes_no "Show available Linux‑Libre Kernels and let you pick one to install?"; then
mapfile -t kernels < <(
apt-cache search -n '^(linux-(image|headers)-.*(gnu|libre)|linux-libre-)' |
cut -d' ' -f1 |
sort -u
)
if (( ${#kernels[@]} == 0 )); then
warn "No Linux‑Libre kernels found."
exit 1
fi
echo -e "${CYAN}Available kernels:${RESET}"
for i in "${!kernels[@]}"; do
printf " %2d) %s\n" $((i+1)) "${kernels[i]}"
done
echo " 0) Cancel"
while true; do
printf "${YELLOW}Enter the number of the kernel to install [0-%d]: ${RESET}" "${#kernels[@]}"
read -r choice
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 0 && choice <= ${#kernels[@]} )); then
break
fi
warn "Invalid selection."
done
(( choice == 0 )) &selected_kernel="${kernels[choice-1]}"
log "Selected kernel: $selected_kernel"
retry_cmd "install $selected_kernel" apt-get install -y "$selected_kernel"
else
log "User declined to view/install Linux‑Libre kernels; exiting."
exit 0
fi
# -------------------- 6️⃣ Set GRUB_DEFAULT to the new GNU kernel --------------------
set_grub_default() {
mapfile -t entries < <(
awk -F"'" '/menuentry/ {print $2}' /boot/grub/grub.cfg |
grep -i gnu |
while IFS= read -r title; do
if [[ "$title" != *">"* ]]; then
printf 'Advanced options for Ubuntu>%s\n' "$title"
else
printf '%s\n' "$title"
fi
done
)
if (( ${#entries[@]} == 0 )); then
warn "No GRUB menu entries containing “gnu” were found."
return 1
fi
selected_entry="${entries[0]}"
log "Setting GRUB_DEFAULT to \"$selected_entry\""
if grep -q '^GRUB_DEFAULT=' /etc/default/grub; then
escaped=$(printf '%s' "$selected_entry" | sed 's/"/\\"/g')
sed -i "s|^GRUB_DEFAULT=.*|GRUB_DEFAULT=\"${escaped}\"|" /etc/default/grub
else
echo "GRUB_DEFAULT=\"${selected_entry}\"" >> /etc/default/grub
fi
retry_cmd "update-grub" update-grub
}
set_grub_default
# -------------------------------------------------
# Phase 1 – first run: ask to reboot
# -------------------------------------------------
if ask_yes_no "Reboot now so the system boots the new Linux‑Libre Kernel?"; then
touch "$REBOOT_FLAG"
log "${CYAN}Log in to the VPS again and run the script to continue the configuration!${RESET}"
/sbin/reboot
exit 0
else
log "No reboot will be performed."
exit 0
fi
fi # ← end of “if [[ ! -f $REBOOT_FLAG ]]”
# -------------------------------------------------
# Kernel‑cleanup block (run after a successful reboot)
# -------------------------------------------------
if [[ -f "$REBOOT_FLAG" && ! -f "$CLEAR_FLAG" ]]; then
if ask_yes_no "Remove old non‑gnu kernels now that the new kernel is installed?"; then
touch "$CLEAR_FLAG"
log "Clear‑kernel flag created – starting cleanup…"
# -------------------------------------------------
# 1️⃣ Gather old non‑gnu kernels
# -------------------------------------------------
mapfile -t old_kernels < <(
dpkg -l 'linux-image*' 2>/dev/null |
awk '/^ii/ {print $2}' |
grep -vi 'gnu' || true
)
if (( ${#old_kernels[@]} == 0 )); then
warn "No non‑gnu kernels to remove."
else
echo -e "${CYAN}The following packages will be removed:${RESET}"
printf " %s\n" "${old_kernels[@]}"
# -------------------------------------------------
# 2️⃣ Purge the old kernels
# -------------------------------------------------
retry_cmd "purge old kernels" \
apt-get --purge autoremove -y "${old_kernels[@]}"
# -------------------------------------------------
# 3️⃣ Clean the apt cache
# -------------------------------------------------
retry_cmd "apt autoclean" apt-get autoclean -y
fi
# -------------------------------------------------
# 4️⃣ Clean residual files in /boot
# -------------------------------------------------
boot_dir="/boot"
log "Cleaning residual files in $boot_dir …"
# Versions we must keep (current GNU kernel + any other GNU kernels)
mapfile -t keep_versions < <(
dpkg -l 'linux-image-*gnu*' 2>/dev/null |
awk '/^ii/ {print $2}' |
sed 's/^linux-image-//'
)
keep_versions+=("$(uname -r)")
shopt -s nullglob
for file in "$boot_dir"/{vmlinuz,initrd.img,config,System.map}-*; do
ver=${file##*-}
if printf '%s\n' "${keep_versions[@]}" | grep -qx "$ver"; then
log "Preserving $file"
else
log "Removing $file"
rm -f -- "$file"
fi
done
shopt -u nullglob
# Remove stale *.old symlinks
for link in "$boot_dir"/{vmlinuz,initrd.img}.old; do
if [[ -L $link && ! -e $(readlink -f "$link") ]]; then
log "Removing stale symlink $link"
rm -f -- "$link"
fi
done
# -------------------------------------------------
# 5️⃣ Final housekeeping – ensure no leftover packages
# -------------------------------------------------
retry_cmd "final apt autoremove" apt-get autoremove -y
retry_cmd "final apt autoclean" apt-get autoclean -y
ok "Kernel cleanup finished."
else
warn "Kernel not cleared."
fi
fi
# -------------------------------------------------
# Final status output – show the active kernel
# -------------------------------------------------
echo -e "\n${GREEN}✅ Current kernel:${RESET} $(uname -r)"
# After the second question (kernel clearing), remove the flags
if [ -f "$REBOOT_FLAG" ] && [ -f "$CLEAR_FLAG" ]; then
# Both steps are done, clean up flags for future runs
rm -f "$REBOOT_FLAG" "$CLEAR_FLAG"
echo -e "${GREEN}[success]${RESET} Flags have been reset."
fi
[INFO] Show available Linux‑Libre Kernels and let you pick one to install? [Y/n]: y
Available kernels:
1) linux-headers-5.10.251-gnu1
2) linux-headers-5.15.201-gnu
3) linux-headers-6.1.164-gnu
4) linux-headers-6.12.71-gnu
5) linux-headers-6.12.74-gnu
6) linux-headers-6.18.13-gnu
7) linux-headers-6.19.3-gnu
8) linux-headers-6.6.127-gnu
9) linux-image-5.10.251-gnu1
10) linux-image-5.15.201-gnu
11) linux-image-6.1.164-gnu
12) linux-image-6.12.71-gnu
13) linux-image-6.12.74-gnu
14) linux-image-6.18.13-gnu
15) linux-image-6.19.3-gnu
16) linux-image-6.6.127-gnu
17) linux-libre-5.10
18) linux-libre-5.10-headers
19) linux-libre-5.15
20) linux-libre-5.15-headers
21) linux-libre-6.1
22) linux-libre-6.1-headers
23) linux-libre-6.12
24) linux-libre-6.12-headers
25) linux-libre-6.18
26) linux-libre-6.18-headers
27) linux-libre-6.19
28) linux-libre-6.19-headers
29) linux-libre-6.6
30) linux-libre-6.6-headers
31) linux-libre-headers
32) linux-libre-lts
33) linux-libre-lts-headers
0) Cancel
root@d-16:~$ neofetch
.-/+oossssoo+/-. root@d-16
`:+ssssssssssssssssss+:` -------
-+ssssssssssssssssssyyssss+- OS: Ubuntu 24.04.4 LTS x86_64
.ossssssssssssssssssdMMMNysssso. Host: VPS
/ssssssssssshdmmNNmmyNMMMMhssssss/ Kernel: 6.18.13-gnu
+ssssssssshmydMMMMMMMNddddyssssssss+ Uptime: 2 mins
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Packages: 740 (dpkg)
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Shell: bash 5.2.21
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Resolution: 1024x768
ossyNMMMNyMMhsssssssssssssshmmmhssssssso Terminal: /dev/pts/0
ossyNMMMNyMMhsssssssssssssshmmmhssssssso CPU: AMD EPYC 7702P (1) @ 1.996GHz
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ GPU: 00:01.0 Red Hat, Inc. QXL paravirtual graphic card
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Memory: 233MiB / 1972MiB
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/
+sssssssssdmydMMMMMMMMddddyssssssss+
/ssssssssssshdmNNNNmyNMMMMhssssss/
.ossssssssssssssssssdMMMNysssso.
-+sssssssssssssssssyyyssss+-
`:+ssssssssssssssssss+:`
.-/+oossssoo+/-. As for adding Trisquel repositories, I don't understand their practical application. I will have two repositories with duplicate programs, and there may be conflicts during installation.

