Minimal Ubuntu Install
This article will walk through a minimal and manual installation of Ubuntu, comparable to the Arch Linux installation process.
Inspired by the following Reddit Post: Passing the Time in Quarantine (Installed Ubuntu the Arch Way)
Setup:
Boot Into Live Environment:
- Download the latest desktop or server Iso (I would recommend the desktop Iso for simplicity).
- Create bootable media (using something like Etcher), then boot off of your live media.
- Make sure to select “Try Ubuntu” not “Install Ubuntu” when you get to the Grub menu options.
Requirements:
Make sure your Ubuntu environment has a network connection. If you used the desktop Iso, just use the Network Manager applet in the top right hand corner to connect. I will not get into the details of getting wifi connected via CLI, just use an ethernet cable if you can’t figure it out.
I will assume that UEFI is desired boot mode.
I will also assume that you have elevated to root to run all the remaining commands (sudo su -
).
Installation:
Dependencies:
## Add the Universe repository for arch-install-scripts
add-apt-repository universe
apt-get update
apt-get install -y debootstrap arch-install-scripts
Disk Partitioning:
List your disks and their partitions with the following command:
lsblk
The output will show a list of disks, their partitions and their sizes. My disk is an 80 GB drive named /dev/sda
. Change your drive paths as needed in the following commands to fit your installation.
Now, let’s edit the drive partitions with gdisk
gdisk /dev/sda
Create the EFI partition:
Press n [Enter], 1 [Enter], [Enter], +512M [Enter], ef00 [Enter]
Create the swap partition (I’m just going to use 4GB of swap space):
Press n [Enter], 2 [Enter], [Enter], +4G [Enter], 8200 [Enter]
Create the root partition:
Press n [Enter], 3 [Enter], [Enter], [Enter], [Enter]
Write the changes:
Press w [Enter], Y [Enter]
Partition Formatting:
Use the following commands to format your disk.
mkfs.vfat /dev/sda1
mkswap /dev/sda2 && swapon /dev/sda2
mkfs.btrfs /dev/sda3
Bootstrap Ubuntu:
Mount the partitions we created earlier:
mount /dev/sda3 /mnt
mkdir -p /mnt/boot/efi && mount /dev/sda1 /mnt/boot/efi
Then bootstrap your base Ubuntu install (using Ubuntu 22.04 “Jammy Jellyfish”):
Refer to this article for the ARM64 commands if you’re bootstrapping Ubuntu 20.04 ARM64
debootstrap --arch amd64 jammy /mnt http://archive.ubuntu.com/ubuntu
Edit /mnt/etc/apt/sources.list
to not only have the main
repository but also universe
(community packages) and restricted
(proprietary drivers) and the security repo:
release="jammy"
printf "deb http://archive.ubuntu.com/ubuntu/ ${release} main restricted universe\ndeb http://security.ubuntu.com/ubuntu/ ${release}-security main restricted universe\ndeb http://archive.ubuntu.com/ubuntu/ ${release}-updates main restricted universe\n" > /mnt/etc/apt/sources.list
Create a new fstab for the new installation:
genfstab -U /mnt >> /mnt/etc/fstab
Look at /mnt/etc/fstab
and fix any errors if needed.
Configuring Ubuntu:
Chroot into the new installation:
arch-chroot /mnt
Update repository data and install additional dependencies (modify packages as needed):
apt-get update
## Necessary dependencies
apt-get install -y --no-install-recommends linux-generic linux-image-generic linux-headers-generic initramfs-tools linux-firmware efibootmgr
## Optional/opinionated dependencies
apt-get install -y vim
Set timezone:
dpkg-reconfigure tzdata
Set locale (I use en_US.UTF-8
):
dpkg-reconfigure locales
Set hostname:
Edit /etc/hostname
to equal whatever value you want your computer name to be:
echo 'myhostname' > /etc/hostname
I would also recommend editing /etc/hosts
as described in the Arch wiki:
Arch Wiki: Network Configuration
127.0.0.1 localhost
::1 localhost
127.0.1.1 myhostname.localdomain myhostname
Set root password:
passwd
Then install your preferred desktop environment, display manager, etc. I’ll just use GNOME Shell + GDM as an example because I’m boring:
apt-get install -y gnome-shell gnome-terminal gdm3 firefox
Add a sudo user:
adduser myusername
usermod -aG sudo myusername
Create new directories:
mkdir -p /boot/efi/ubuntu/
mkdir -p /boot/efi/loader/entries
Create a systemd-boot config file /boot/efi/loader/loader.conf
with the following lines:
default ubuntu
timeout 1
editor 0
Then create a boot entry file in /boot/efi/loader/entries/ubuntu.conf, replacing the PARTUUID with the root partition found with blkid
:
title Ubuntu
linux /ubuntu/vmlinuz-generic
initrd /ubuntu/initrd.img-generic
options root=PARTUUID=YOUR_UUID rw
The only problem with using systemd-boot
is that you’d need to manually update the kernels any time a new version of the Linux kernel is installed. To solve this, we will create a post install hook that will update the kernel entries in systemd-boot.
Create /etc/kernel/postinst.d/update-systemd-boot
with the following content, replacing the PARTUUID
variable value with the value of your root PARTUUID found from blkid
:
#!/bin/bash
#
# This is a simple custom kernel hook to populate the systemd-boot entries
# whenever kernels are added or removed during an update.
#
# The PARTUUID of your root partition
PARTUUID="INSERTYOURPARTUUIDHERE"
vmlinuz=$(find /boot -maxdepth 1 -name "vmlinuz-*-generic")
version=$(echo $vmlinuz | grep -o -P "\d+\.\d+\.\d+\-\d+" | sort -V | head -n -1)
latest=$(echo $vmlinuz | grep -o -P "\d+\.\d+\.\d+\-\d+" | sort -V | tail -n 1)
echo ">> COPYING ${latest}-generic. LATEST VERSION."
cat << EOF > /boot/efi/loader/entries/ubuntu.conf
title Ubuntu
linux /ubuntu/vmlinuz-generic
initrd /ubuntu/initrd.img-generic
options root=PARTUUID=${PARTUUID} rw
EOF
for file in initrd.img vmlinuz; do
cp "/boot/${file}-${latest}-generic" "/boot/efi/ubuntu/${file}-generic"
done
for ver in $version; do
echo ">> COPYING ${ver}-generic."
cat << EOF > /boot/efi/loader/entries/ubuntu-${ver}.conf
title Ubuntu ${ver}
linux /ubuntu/vmlinuz-${ver}-generic
initrd /ubuntu/initrd.img-${ver}-generic
options root=PARTUUID=${PARTUUID} rw
EOF
for file in initrd.img vmlinuz; do
cp "/boot/${file}-${ver}-generic" "/boot/efi/ubuntu/${file}-${ver}-generic"
done
done
Make the script executable and symlink it to another relevant location:
chmod +x /etc/kernel/postinst.d/update-systemd-boot
ln -s /etc/kernel/postinst.d/update-systemd-boot /etc/kernel/postrm.d/update-systemd-boot
Setup Systemd-boot:
bootctl --path=/boot/efi install
Now, execute the hook script to move the kernel images to the correct directories for our systemd-boot
config to recognize them:
/etc/kernel/postinst.d/update-systemd-boot
Verify boot entries:
bootctl list
I have noticed that Ubuntu has this annoying habit of installing Grub for you, so let’s prevent grub packages from installing:
Place the following in /etc/apt/preferences.d/grub
:
Package: grub-common grub-gfxpayload-lists grub-pc grub-pc-bin grub2-common
Pin: release *
Pin-Priority: -1
Exit:
Use the exit
command to get out of the chroot.
Then reboot!
reboot