Ubuntu Arch Style

Ubuntu, Arch Style

by Thomas Castleman

What is Ubuntu, Arch Style?

So this experiment was started because a lot of people LOVE Arch. And some of them with good reason. Arch is arguably (but not necessarily objectively) lighter weight and faster than distros such as Solus, Fedora, Debian, or many other distros. However, there is a segment of the population that would argue that any distro can be used just like Arch and provide the same benefits.

So, I decided to test that claim.

In this experiment, I want to go about installing Ubuntu 18.04 the way you would install Arch:

  • No Gui. Period. Until I install one.
  • Bootstraping the OS onto your drive, manually
  • Manually configuring EVERYTHING. Or nearly everything.
  • No Snaps out of the box. No Flatpaks out of the box. Just the standard, traditional, package manager.

Why Ubuntu, though?

Ubuntu was essentially my first choice for a number of simple reasons:

  • Ubuntu is the most popular distro
  • Ubuntu is about as far from Arch as you can get and still be mainstream (other than MAYBE Elementary OS but that’s not gonna happen here)
  • I know Ubuntu well. So this makes the task easier on me.
  • This shows people who want to run an Arch-like distro, with apt, just what hoops they will need to jump through to do that.

So. How do we do this?

First up, we need a CLI version of Ubuntu. There are are two ways to do this:

  • Ubuntu Server
  • Making our own Ubuntu ISO

For the sake of fun, and being more Arch-like in the install process, I chose to make my own ISO. Cause why not?

NOTES

Little did I know this would delay this project and cause me a lot of headache. Just use Ubuntu Server. It’s easier.

I still documented what all I did though to show how many hoops you have to jump through just to get basicly Arch with apt.

STEP 0: PREREQUISITES

For this entire thing you will need:

  • A Linux distro already installed on a machine with the following packages installed:
  • debootstrap
  • xorriso
  • squashfs-tools
  • coreutils
  • grub-common
  • If you don’t want to install this on hardware, you will need a VM Manager to test with. Otherwise, you just need a way to burn the ISO.
  • You also need a decent internet connection. Be prepared for several hundred megabytes of data to be downloaded.

STEP 1: DEBOOTSTRAP

To make this ISO, we need to be running any of the various Linux distros with debootstrap in their repos. Since I am already running Ubuntu, it’s a simple:

    sudo apt install debootstrap

I won’t go into detail about how exactly you do this, but you need to make a chroot environment of whichever version of Ubuntu you want (I went with Bionic (18.04)), then chroot into it:

    sudo chroot /path/to/chroot/environment

Once inside, I did the following things:

  • I installed debootstrap inside the chroot itself, for the installation process
  • I disabled a few systemd services (I forgot to document which ones though).
  • made sure the chroot was up-to-date (A bit redundent but it’s okay).
  • If you don’t known how to use vim, install nano with:
    apt install nano
  • configure your apt sources:
    nano /etc/apt/sources.list

Add “universe” to the end of the line shown when the file opens. I also added the bionic-updates, bionic-security, and bionic-backports repos to my “Ubuntu-Arch-Style” ISO.

  • Installed live-boot and casper to prevent a kernel panic:
    apt install live-boot casper
  • Installed a kernel since the chroot doesn’t come with one
  • installation can be done with:
    apt install linux-image-generic linux-headers-generic
  • Install squashfs-tools so you can install the OS later:
    apt install squashfs-tools
  • Set a root password so you can login later. This system is temporary, so it’s okay if it’s overly simple. Just run:
    passwd

Once you do all this, exit out by running:

    exit

There is no point in configuring it past here due to the fact that you will not be running the ISO we just made for anything other than installing the OS. Nothing we do to configure it will be carried over anyways, unless you choose to unpack the squashfs to the partition you wish the OS to be on, which is a good idea if you have internet issues like I did.

STEP 2: MAKE A SQUASHFS

This is actually super easy. The start off, make three directories:

    mkdir -p scratch image/live

These will be used to build the ISO and configure it for GRUB to boot.

Next, to make the squashfs we need to run a pretty long command. This will take a while depending on your system’s specs. Feel free to go have a snack while it’s running if you have a dual-core system:

    sudo mksquashfs /path/to/chroot image/live/filesystem.squashfs -comp xz -Xdict-size 8k -e boot

STEP 3: CONFIGURE FOR BOOT WITH GRUB

This part is also easy, but has a lot of steps. So bear with me here.

We need to copy the vmlinuz image and initrd.img to the folder “image” we made earlier:

    sudo cp /path/to/chroot/boot/vmlinuz-* image/vmlinuz
sudo cp /path/to/chroot/boot/initrd.img-* image/initrd

Now that we have done that, comes the time to actually make our own config files! WOO!

Make a file in our “scratch” directory named “grub.cfg” and open it for editing:

    touch scratch/grub.cfg #doing this with nano is redundant but it's fine
nano scratch/grub.cfg

Once you have it open, put in the following config:

    search --set=root --file /Ubuntu-Arch-Style

insmod all_video

set default="0"
set timeout=30

menuentry "Ubuntu Arch Style" {
  linux /vmlinuz boot=live quiet                      
  initrd /initrd
}

menuentry "Ubuntu Arch Style NOMODESET" {
  linux /vmlinux boot=live quiet nomodeset
  initrd /initrd
}
EOF

This will give us a grub menu to use when we boot. The “nomodeset” option is a little extra, so you don’t really need it if you wanna leave it off. But in some very rare cases it may be useful.

Next, we need to make the “Ubuntu-Arch-Style” file we just mentioned in that config in “image”:

    touch image/Ubuntu-Arch-Style

Now we need to give GRUB something to actually run when it boots. For this, we will be making a hybrid ISO, meaning it can boot on either UEFI or BIOS.

For the BIOS run these commands:

    grub-mkstandalone --format=i386-pc --output=scratch/core.img --install-modules="linux normal iso9660 biosdisk memdisk search tar ls" --modules="linux normal iso9660 biosdisk search" --locales="" --fonts=""  "boot/grub/grub.cfg=scratch/grub.cfg"
cat /usr/lib/grub/i386-pc/cdboot.img scratch/core.img > scratch/bios.img

Next, we need to set up for UEFI. This process is a little more involved:

    grub-mkstandalone --format=x86_64-efi --output=scratch/bootx64.efi --locales="" --fonts=""  "boot/grub/grub.cfg=scratch/grub.cfg"
(cd scratch && dd if=/dev/zero of=efiboot.img bs=1M count=10 && mkfs.vfat efiboot.img && mmd -i efiboot.img efi efi/boot && mcopy -i efiboot.img ./bootx64.efi ::efi/boot/ )

STEP 4: MAKE THE ISO

Now the fun part. Time to run one extremely long command to build our ISO file for us. And that command is:

    sudo xorriso -as mkisofs -iso-level 3 -full-iso9660-filenames -volid "Ubuntu Arch Style" -eltorito-boot boot/grub/bios.img -no-emul-boot -boot-load-size 4 -boot-info-table --eltorito-catalog boot/grub/boot.cat --grub2-boot-info --grub2-mbr /usr/lib/grub/i386-pc/boot_hybrid.img -eltorito-alt-boot -e EFI/efiboot.img -no-emul-boot -append_partition 2 0xef scratch/efiboot.img -output "$HOME/Downloads/Ubuntu-Arch-Style.iso" -graft-points image /boot/grub/bios.img=scratch/bios.img /EFI/efiboot.img=scratch/efiboot.img
sudo chmod 600 Ubuntu-Arch-Style.iso
sudo chown USERNAME:USERNAME Ubuntu-Arch-Style.iso

Make sure to replace USERNAME with your username. At this point, you should have an ISO that is named “Ubuntu-Arch-Style.iso” that is roughly 400-500 MB in size.

STEP 5: BOOT THE ISO

You should be able to write the ISO file we just made to a USB drive. For time reasons, I booted it in a Virtual Machine with VirtualBox.

I suggest booting with EFI, this will allow you to install the boot loader we use later.

When you boot up, you should just have a black screen for a few seconds, then be greeted by the TTY login screen for Ubuntu!

Use ‘root’ as the username and the password you set in step 1 to login.

STEP 6: Installing Ubuntu, in the Arch Style

Once you login, we can start following the Arch Wiki on how to install Arch. However, a word of caution first:

Arch and Ubuntu are different OSs (obviously). As such, not all commands they use to install Arch will work. So, in some places things will be harder. However, in others, they will also be easier.

So, just look up in your favorite search engine “How to Install Arch Linux” and follow the link to the Arch wiki!

STEP 7: FORMATTING YOUR DRIVE

This should be very similar to Arch.

Run fdisk -l to view connected devices you can install to.

I have one partition on a single drive, at /dev/sda, so to begin partitioning, I ran:

    fdisk /dev/sda

Edit that command for the drive you want to install to.

Follow the fdisk instructions and commands to format your drive so you have at least one partition, of type “Linux Native”. If you are using UEFI, make sure to make a second partition for that.

Once you have done that, run:

    mkfs.ext4 /dev/sda1

replacing /dev/sda1 with your drive’s location.

Next, mount it on /mnt by running the following command:

    mount /dev/sda1 /mnt

STEP 8: INSTALL THE SYSTEM

The following steps are done offline because I had issues connecting to the internet. This means all the changes I made to the squashfs will carry over.

Now, we need to locate where the squashfs we made earlier ended up in our live system. When we run:

    lsblk

We can see that the squashfs is MOUNTED at /lib/live/mount/medium/rootfs/filesystem.squashfs HOWEVER, this is NOT where the squashfs file is actually stored. This is a folder, to which the squashfs file is mounted. Thankfully, the squashfs is probably nearby. Mine was located in /lib/live/mount/medium/live. I would check in a similar place on your system.

Once you figure out where your squashfs file is, run this command to extract it to /mnt, which is the path to our internal drive:

    cd /mnt
unsquashfs /path/to/filesystem.squashfs

NOTE

unsquashfs DOES have the ability to extract to a specific directory. But at time of writing, this was broken.
The methods used here, while longer and more round-about, are more reliable.

At this point, a LOT of text should start flying by on screen. Relax. This is the squashfs file being extracted. Just let the computer do it’s work. This process should take a few minutes.

Once it gets done, run the following commands to get everything moved to the correct spots:

    file_list=$(ls squashfs-root)
for each in $file_list; do
mv -v /mnt/squashfs-root/$each /mnt/$each
done

Finally, if you are able to get internet working (we had trouble with that) run these commands to get your kernel re-installed, as it doesn’t get into the squashfs:

    install=$(apt-cache depends linux-headers-generic linux-image-generic | grep '[ |]Depends: [^<]' | cut -d: -f2 | tr -d ' ')
apt install -y --reinstall linux-headers-generic linux-image-generic $install

STEP 9: CONFIGURE FSTAB

If this is not done, your system won’t boot.

First, run:

    lsblk -f

And take note of the UUID coloumn. We suggest writing down the UUID for the parition you installed to. This will be important.

Next, run:

    nano /etc/fstab

And replace the contents of the file with this:

    UUID=<Your-UUID> / ext4 defaults 0 1

NOTE

If you install the package arch-install-scripts in the ISO it comes with a command called genfstab.
This command will generate an fstab file for you. Read the help dialog before using it.

Then save the file and exit.

STEP 10: CONFIGURE TIME AND LANGUAGE

These are pretty easy. Dig through /usr/share/zoneinfo and find a location in your timezone, then run:

    ln -sf /usr/share/zoneinfo/Region/City /etc/localtime

To set your current time. Then, to set your language, run:

    nano /etc/locale.gen

And un-comment ‘en_US.UTF-8 UTF-8’ and any other locales you need. Once you save this file and exit, run:

    locale-gen

Then, run:

    nano /etc/locale.conf

And set LANG equal to your desired locale:

    LANG=en_US.UTF-8

STEP 11: SET HOSTNAME

Now we need to set our host-name. Open /etc/hostname:

    nano /etc/hostname

This will likely contain the host-name of the system you made the initial chroot on. So, change it to something else. I set mine to ‘UBUNTU-ARCH-STYLE’.

Then, open /etc/hosts:

    nano /etc/hosts

And add this line:

    127.0.1.1   <your-host-name>.localdomain <your-host-name>

STEP 12: UPDATE INITRAMFS

This is simple enough if it decides to work:

    update-initramfs -u

If it doesn’t, you can do:

    mkinitramfs -o /boot/inirrd.img-$(uname --release)

STEP 13: SET A NEW PASSWORD

Again, simple:

    passwd

STEP 14: INSTALL SYSTEMD-BOOT

We were gonna use GRUB, But this was a pain and wasn’t working. So, we are using systemd-boot instead because it is easier to set up.

Because of this, if you booted using Legacy/BIOS mode, this won’t work.

First up, make a few directories in /boot/efi:

    mkdir -p /boot/efi/loader/entries /boot/efi/Ubuntu

Because systemd-boot is picky, we need to tell it to relax:

    export SYSTEMD_RELAX_ESP_CHECKS=1
echo "export SYSTEMD_RELAX_ESP_CHECKS=1" >> /etc/environment

Now we can actually install systemd-boot:

    bootctl --path=/boot/efi install

And configure it:

    echo -e "default Ubuntu\ntimeout 5\neditor 1" > /boot/efi/loader/loader.conf
chattr -i /boot/efi/loader/loader.conf

That chattr command makes the file immutable, thus protecting it from deletion later down the line.

`The next bit of config is complex…ish. If you want, you can copy the following text into a script, and it will set it up so that systemd-boot will get updated, just like GRUB would have been, every time you get a new kernel. Just make sure to pass the device path so it works. Or, manually set ROOT to it.

#!/bin/bash
ROOT="$1"
echo " ### systemd-boot-config.sh STARTED ### " 1>&2
mkdir -p /etc/kernel/postinst.d /etc/kernel/postrm.d
echo "#!/bin/bash
#
# This is a simple kernel hook to populate the systemd-boot entries
# whenever kernels are added or removed.
#



# The UUID of your disk.
UUID=\"$(blkid -s PARTUUID -o value $ROOT)\"

# The LUKS volume slug you want to use, which will result in the
# partition being mounted to /dev/mapper/CHANGEME.
#VOLUME=\"CHANGEME\"

# Any rootflags you wish to set.
ROOTFLAGS=\"quiet splash init=/lib/systemd/systemd\"



# Our kernels.
KERNELS=()
FIND=\$(ls -A /boot | grep \"vmlinuz-*\")
for each in \$FIND; do
KERNELS+=\"/boot/\$each \"
done

# There has to be at least one kernel.
if [ \${#KERNELS[@]} -lt 1 ]; then
echo -e \"\e[2msystemd-boot\e[0m \e[1;31mNo kernels found.\e[0m\"
exit 1
fi



# Perform a nuclear clean to ensure everything is always in perfect sync.
rm /boot/efi/loader/entries/*.conf
rm -rf /boot/efi/Ubuntu
mkdir /boot/efi/Ubuntu



# Copy the latest kernel files to a consistent place so we can keep
# using the same loader configuration.
LATEST=\"\$(echo \$KERNELS | sed 's/\/boot\/vmlinuz//g' | sed 's/ /\n/g' | sed 's/.old//g' | sed '/^[[:space:]]*$/d' | sort -nr | head -n1)\"
echo -e \"\e[2msystemd-boot\e[0m\e[1;32m\${LATEST}\e[0m\"
for FILE in config initrd.img System.map vmlinuz; do
  cp \"/boot/\${FILE}\${LATEST}\" \"/boot/efi/Ubuntu/\${FILE}\"
  cat << EOF > /boot/efi/loader/entries/Ubuntu.conf
title   Ubuntu
linux   /Ubuntu/vmlinuz
initrd /Ubuntu/initrd.img
options root=PARTUUID=\$UUID \${ROOTFLAGS}
EOF
done



# Copy any legacy kernels over too, but maintain their version-based
# names to avoid collisions.
if [ \${#KERNELS[@]} -gt 1 ]; then
LEGACY=\"\$(echo \$KERNELS | sed 's/\/boot\/vmlinuz//g' | sed 's/ /\n/g' | sed 's/.old//g' | sed '/^[[:space:]]*$/d' | sort -nr | sed s/\$LATEST//g)\"
for VERSION in \${LEGACY[@]}; do
  echo -e \"\e[2msystemd-boot\e[0m\e[1;32m\${VERSION}\e[0m\"
  for FILE in config initrd.img System.map vmlinuz; do
      cp \"/boot/\${FILE}\${VERSION}\" \"/boot/efi/Ubuntu/\${FILE}\${VERSION}\"
      cat << EOF > /boot/efi/loader/entries/Ubuntu\${VERSION}.conf
title   Ubuntu \${VERSION}
linux   /Ubuntu/vmlinuz\${VERSION}
initrd /Ubuntu/initrd.img\${VERSION}
options root=PARTUUID=\$UUID \${ROOTFLAGS}
EOF
  done
done
fi



# Success!
exit 0" > /etc/kernel/postinst.d/zz-update-systemd-boot
cp /etc/kernel/postinst.d/zz-update-systemd-boot /etc/kernel/postrm.d/zz-update-systemd-boot
# Set the right owner.
chown root: /etc/kernel/postinst.d/zz-update-systemd-boot
chown root: /etc/kernel/postrm.d/zz-update-systemd-boot
# Set the right permissions.
chmod 0755 /etc/kernel/postinst.d/zz-update-systemd-boot
chmod 0755 /etc/kernel/postrm.d/zz-update-systemd-boot
#set up the loaders
/etc/kernel/postinst.d/zz-update-systemd-boot || /etc/kernel/postrm.d/zz-update-systemd-boot
echo " ### systemd-boot-config.sh CLOSED ### " 1>&2

After you run that script and it completes successfully… All we need to do is make our initramfs:

    mkinitramfs -o /boot/inirrd.img-$(uname --release)

Then copy it and our kernel image over into /boot/efi:

    cp /boot/vmlinuz-$(uname --release) /boot/efi/vmlinuz
cp /boot/initrd.img-$(uname --release) /boot/efi/initrd.img

Make a couple links:

    ln /boot/initrd.img-$(uname --release) /boot/initrd.img
ln /boot/vmlinuz-$(uname --release) /boot/vmlinuz

And we SHOULD be done!

…With installation…

Assuming you have something that boots correctly you should be able to login like we did earlier, use apt to install whatever DE/WM and DM you want. You might also want to install X11, but it’s likely it will get pulled in along with your DE/WM of choice.

Just be sure to make yourself a user account:

    useradd -m USERNAME

Replace USERNAME with your desired username. This will create a super basic user account for you, with no sudo access.

At this point, though, I stopped working on this because the amount of time and energy invested wasn’t worth it. We ran into almost every issue in the book, from kernel panics, to no internet, to GRUB breaking, and everything in between.

Wrapping Up

So the moral of the story?

Yes, yes you can get something like Arch with other distros. Should you though?

Well, this is where people who say that distros are good have one of their main arguments come into play.

It’s much quicker and easier to find a distro you kinda like and modify it to suit your needs. Any Linux noob with basic terminal/package manager know-how can do it. And that’s the point of distros, if you ask me: to provide a starting point closer to what the end user really wants, saving them work.

If you really want to learn how a distro works, or do some sort of crazy modification in it’s guts, this might just be for you. But be prepared to put in a lot of hard work, but also be prepared to learn a lot too, about how the best OS on the planet works under the hood.

Share This

Share on twitter
Share on facebook
Share on linkedin
Share on pinterest
Share on reddit
Share on tumblr
Share on telegram
Share on stumbleupon
Share on email
Share on print

Author Info

Comments

Notable Replies

  1. I thought that as well as light weight the whole point of ARCH is install once and and just keep updated and you always have the latest and greatest software (until it breaks that is) Anything based on Ubuntu is never going to be at the cutting edge even using a point release as software packages only get security fixes between LTS or point releases.

  2. trst says:

    Respect. Not in the slightest bit appealing to me but I have to commend a good effort when I see one :stuck_out_tongue_winking_eye:

Continue the discussion at discourse.bigdaddylinux.com

Participants

Recent Posts

Recent Comments

Post comments are integrated with our Discourse forum. Each posts links to the specific discussion thread or you can visit the forum directly at https://discourse.bigdaddylinux.com/