Manual Ubuntu Installation from Scratch
Views: 16
Because the Ubuntu-Server installation does not offer the device configuration (see Multi-Disk Encryption Magic), I need to install Ubuntu manually from scratch. This is also a good training to understand what magic the Ubuntu installer does. Here my hard disk configuration is already done according to Multi-Disk Encryption Magic, so this blog does not cover device setup. I just expect you have partitions ready to mount:
- one disk (hdd/ssd) prepared as boot device (if not, see below)
- one partition for
/boot - one partition for
/(root) - only for UEFI devices: one partition to mount to
/boot/uefi - optional: a swap partition
The partitions in /boot and below must not be encrypted, all other partitions can be encrypted, and in fact I recommend to encrypt them.
Boot the Installation Environment
Just download the latest Ubuntu Desktop ISO image and copy it to an installation USB-stick. Then boot your new computer from that stick. When the installer starts, choose your language and keyboard-layout, connect to the network, then choose Try Ubuntu
to stop the installer.
On the left upper side of the desktop, there is a button to get the launch pad. Click on the launcher with the Ubuntu logo on the very bottom of the launch pad and start a console from there.
Remote Installation
Optionally you can run everything from remote using SSH. The advantage of this is, that you can sit on your normal computer with your favorite environment, instead of doing everything from the limited installer desktop.
For this, just install the SSH server and set a password for the default user named ubuntu:
sudo apt-get update sudo apt-get install -y openssh-server passwd
Check the IP address of the device you want to install. You find it from the network settings, just open the settings from the Ubuntu launcher. In this example, let’s say it is 192.168.0.8.
On your favorite computer, which must be in the same local network, open a console and run:
ssh -o PubkeyAuthentication=no ubuntu@192.168.0.8
Now you’re ready for remote installation.
Ubuntu Installation
The whole installation is done as root. Be careful, be aware that you could damage anything. Get root:
sudo -Hi
Prepare Target Filesystems
Make sure, all partitions are ready, e.g. open encrypted filesystems. In my case, this is: cryptsetup open /dev/big/big crypt. The LVMs are the automatically ready. In this example, I install:
- swap on
/dev/crypt/swap /on/dev/big/root/booton/dev/sdd2- BIOS boot in
/dev/sdd1 - MBR (Master Boot Record) on
/dev/sdd - no uefi (very old server from 2014)
Be aware that device names may change, i.e. those in /dev/sd*, so you will need to add the UUIDs to your fstab and crypttab configuration.
Prepare Boot Drive
BIOS (Legacy)-Boot, GPT-Disk
Without UEFI, you need a special 1MB BIOS boot partition. I’ll boot from `/dev/sdd`, so I create it in `/dev/sdd1`. The following steps destroy the device `/dev/sdd` and all it’s content. The following steps create a new GPT label, which destroys all existing partitions, then creates and initializes a BIOS boot partition as first partition, so partition 1 in /dev/sdd1:
parted /dev/sdd mklabel gpt parted /dev/sdd mkpart biosboot 1MiB 2MiB parted /dev/sdd set 1 bios_grub on
UEFI Boot Setup
On modern UEFI based systems, you need an EFI partition (FAT32, ca. 512MB with esp flag). I’ll boot from `/dev/sdd`, so I create it in `/dev/sdd1`. The following steps destroy the device `/dev/sdd` and all it’s content. The following steps create a new GPT label, which destroys all existing partitions, then creates and initializes an EFI partition as first partition, so partition 1 in /dev/sdd1:
parted /dev/sdd mklabel gpt parted /dev/sdd mkpart ESP fat32 1MiB 513MiB parted /dev/sdd set 1 esp on mkfs.vfat -F32 /dev/sdd1
Boot Partition
All systems, legacy and UEFI, need a boot partition. I create it as /dev/sdd2 with ext4 file system on the same disk I prepared above. Again, this destroys previous data on the disk:
parted /dev/sdd mkpart boot ext4 2MiB 100% mkfs.ext4 /dev/sdd2
Root Partition and Swap
I always use a large root partition without further splitting up, so I format (destroy) my device on /dev/crypt/root and initialize swap on /dev/crypt/swap:
mkfs.ext4 /dev/crypt/root mkswap /dev/crypt/swap
Mount Filesystems
Now everything is ready to be mounted to /mnt (you can mount it wherever you want, /mnt is somehow a standard place). On legacy non UEFI systems, skip the last two steps to mount /boot/efi. It is important that you first mount the upper paths, then the lower paths:
mount /dev/crypt/root /mnt mkdir /mnt/boot mount /dev/sdd2 /mnt/boot mkdir /mnt/boot/efi # on UEFI BIOS only mount /dev/sdd1 /mnt/boot/efi # on UEFI BIOS only
Bootstrap Minimal Ubuntu Base System
There is a script debootstrap that downloads and installs a minimal debian system into a directory. All you need to specify is the release code name (e.g. noble for Ubuntu 24.04 LTS) and the target directory:
apt-get update apt-get install -y debootstrap debootstrap noble /mnt
Switch to New Ubuntu
Now we can chroot to the new system:
mount --bind /dev /mnt/dev mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys chroot /mnt
All we do now is applied to the new system that we setup.
Language, Localisation
To setup any localisation, e.g. German (de) in Switzerland (CH), save it to /etc/default/locale and generate the corresponding locales:
echo "LANG=de_CH.UTF-8" > /etc/default/locale locale-gen de_CH.UTF-8
Host Name
To setup a host name, just store it in /etc/hostname, e.g. if you name your computer server01:
echo server01 > /etc/hostname echo "127.0.1.1 server01" >> /etc/hosts
Create a User
If you want to be able to login after your computer restarts, you must create a user on your name. And if you want to execute administration tasks from that user, you need to give it root access through sudo by adding it to the sudo group. In this example, let’s name the user me:
adduser me usermod -aG sudo me
Configure APT Package Sources
Simple
Typically you want all Ubuntu sources, so add them, the simplest way is to use apt-add-repository:
apt-get install -y software-properties-common add-apt-repository -y main add-apt-repository -y universe add-apt-repository -y multiverse add-apt-repository -y restricted add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-updates main restricted universe multiverse" add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-security main restricted universe multiverse" add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-backports main restricted universe multiverse" apt update
Fancy
Alternatively you can install everything manually without dependency on software-properties-common by writing into /etc/apt/sources.list:
CODENAME=$(lsb_release -cs) cat > /etc/apt/sources.list <<EOF deb http://archive.ubuntu.com/ubuntu $CODENAME main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu $CODENAME-updates main restricted universe multiverse deb http://security.ubuntu.com/ubuntu $CODENAME-security main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu $CODENAME-backports main restricted universe multiverse EOF apt update
Install Necessary System Packages
You may need the following packages:
- Base System, choose your flavour, i.e. one of e.g.:
ubuntu-standardubuntu-baseubuntu-minimalubuntu-serverubuntu-server-minimalubuntu-desktopubuntu-dektop-minimalkubuntu-desktop- …
- for LVM:
lvm2 - for encrypted boot disks:
cryptsetup-initramfs - to allow SSH access:
openssh-server - and always: linux-image-generic grub-pc systemd-sysv
Example:
apt-get install -y ubuntu-standard linux-image-generic grub-pc \
lvm2 cryptsetup-initramfs \
openssh-server
Encrypted Filesystems in CryptTab
To be able to mount encrypted filesystems at boot, you must enter them in /etc/crypttab. in my example, the device /dev/big/big is encrypted. First I need it’s LUKS-UUID: cryptsetup luksUUID /dev/big/big, this is how I reference it in my /etc/crypttab. Be sure to always use UUIDs, unless you’re absolutely sure, the name you refer to will never change.
You can use vi or install vim to edit /etc/crypttab, or if it is just one device, you can use this script, just adapt DEVICE in the first line to your needs:
DEVICE=/dev/big/big LUUID=$(cryptsetup luksUUID $DEVICE) cat > /etc/crypttab <<EOF crypt UUID=$LUUID none luks,discard EOF
Verify that the file content makes sense and UUID is set correctly, e.g. cat /etc/crypttab results in my system to:
crypt UUID=eb3e94f0-2d76-4e92-b3ce-0e2911d9448e none luks,discard
All Filesystems in FSTab
You must add all filesystems you’ll need in /etc/fstab, including pseudo filesystems, here again, you may use an editor to set it up, or you can use cat, just change the variables. Again, don’t add the EFI part if you are on a legacy system and don’t add the SWAP part if you don’t have a swap partition:
SWAP=/dev/crypt/swap ROOT=/dev/crypt/root BOOT=/dev/sdd2 EFI=/dev/sdd1 cat > /etc/fstab <<EOF proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /run tmpfs defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 UUID=$(blkid -s UUID -o value $ROOT) / ext4 defaults 0 1 UUID=$(blkid -s UUID -o value $BOOT) /boot ext4 defaults 0 2 UUID=$(blkid -s UUID -o value $EFI) /boot/efi vfat defaults 0 2 UUID=$(blkid -s UUID -o value $SWAP) none swap sw 0 0 EOF
On my legacy system, this results in:
proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /run tmpfs defaults 0 0 tmpfs /tmp tmpfs defaults 0 0 UUID=442880bf-1b95-4b53-8c48-7e64d787b0d0 / ext4 defaults 0 1 UUID=4e077e0e-bf0d-405e-b1be-19c6e013ee75 /boot ext4 defaults 0 2 UUID=72e6dea6-d286-4427-8e56-74ba8f779fa8 none swap sw 0 0
Configure DHCP Network
Netplan and the Resolver require some packages, either libnss-resolve (old Ubuntu, e.g. focal) or systemd-resolved (new Ubuntu, e.g. noble):
apt-get install -y netplan.io systemd-sysv systemd-resolved
DNS Resolver
For DNS-Resolver, the hosts: line in file /etc/nsswitch.conf must contain resolve as hosts: files resolve [!UNAVAIL=return] dns. You can edit it manually or with a script:
sed -i 's/^hosts:.*$/hosts: files resolve [!UNAVAIL=return] dns/g' /etc/nsswitch.conf
NetPlan Configuration
To configure the network, you need to setup a netplan configuration. Use ip -br link to find all available network devices. Also here, you can create /etc/netplan/01-netcfg.yaml manually or with a script:
IFACES=$(ip -br link | awk '$2 ~ /UP|DOWN/ {print $1}')
cat > /etc/netplan/01-netcfg.yaml <<EOF
network:
version: 2
renderer: networkd
ethernets:
$(
for IFACE in $IFACES; do
echo " $IFACE:"
echo " dhcp4: true"
done
)
EOF
On my server, there are two network interfaces eno1 and eno2, so the resulting file /etc/netplan/01-netcfg.yaml is:
network:
version: 2
renderer: networkd
ethernets:
eno1:
dhcp4: true
eno2:
dhcp4: true
Setup InitRamFS and Kernel
Finally make sure our system boots and finds it’s kernel and initial filesystem. First of all, if you have LVm and encrypted filesystems and if you need to enter the password at boot time, this must be enabled:
echo "CRYPTSETUP=y" > /etc/cryptsetup-initramfs/conf-hook echo "ASKPASS=y" >> /etc/cryptsetup-initramfs/conf-hook echo "LVM=yes" > /etc/initramfs-tools/conf.d/lvm
Finally initialize GRUB and the initial ram filesystem, in my case, I install GRUB on /dev/sdd. For those on legacy systems without EFI, just skip the first grub-install line:
update-initramfs -u -k all update-grub grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu grub-install /dev/sdd
You’re done! Just reboot and make sure you unplug your temporary Ubuntu boot device before restarting:
exit reboot
Hint: For those who used SSH during the installation, the key now has changed and you’ll need to remove the old SSH key of this machine. That’s not a bug nor an issue. So here: ssh-keygen -f ~/.ssh/known_hosts -R 192.168.0.8