If you are new to Linux, creating a custom distribution is no easy challenge. If you are looking for a way to customize a Ubuntu variant, then you are in luck because this tutorial will hold your hand through the process. Along the way you will learn important terminal commands and gain a greater understanding of the Linux operating system. This tutorial elaborates on this one and adds other important information on customizing.


Host Linux OS

We first need an environment to work in. You can install Linux on your machine and dual boot it. You can also create a VirtualBox guest and work inside of that. Your last option is to create a LiveCD or LiveUSB and use an ext4 partition on your hard drive to work from. The partition must be ext4 to retain Linux file permissions. This last option will most certainly give you many headaches.


Let's do everything as root shall we? Open a terminal to work in for the remainder of the project. Then enter this command followed by your user password to get a root session in the terminal.

sudo -s

Required Applications

First we need to install squashfs-tools and genisoimage to create a compressed filesystem for live booting and a completed ISO image. We can use aptitude for this very purpose. We will later use aptitude to install and uninstall applications in our customized distribution.

apt-get install squashfs-tools genisoimage

Setting up our working directories

Create a directory to work inside then "cd" (change directory) to it. This can be anywhere. I like to put mine in /var/tmp/.

# create our working directory
mkdir /var/tmp/livecd/
# change directory to it
cd /var/tmp/livecd/ 

Create a temporary folder to mount the downloaded ISO so we can then copy the contents of that ISO to a permanent directory. You can do this with an archive manager and file browser if you choose. Here are the commands.

# make our temporary directory to mount the ISO
mkdir mnt/
# make our permanent directory to move the contents of the ISO
mkdir extract-cd/
# mount the ISO
mount -o loop,ro /path/to/LinuxDistro.iso mnt/
# copy the contents into the permanent directory
rsync --exclude=/casper/filesystem.squashfs -a mnt/ extract-cd

Now we need to uncompress the file system in the ISO to do our customizing.

# uncompress the file system
unsquashfs mnt/casper/filesystem.squashfs
# rename the created folder to 'edit'
mv squashfs-root edit 
# we are done with the ISO. Unmount it
umount mnt

CHROOT Environment

Now we can change any files in the 'edit' directory and they will manifest in our final ISO. Let's add some DNS servers to our resolv.conf file, change the hosts file, and setup our working chroot environment. First we need to figure out our X server situation so we can open GUI programs on the destination ISO. We will also copy any '.deb' files we want to install into the chroot environment. If you need to change your ISO after finalizing it you must return to this step and do everything again.

# copy our '.deb' files for future installing
cp /path/to/application.deb edit/
# record the first value for the next command
xauth list $DISPLAY 
# The value will be 'username/unix:0' or something similar
# This step must be done every time you want to run a GUI application
# in the chroot environment. Annoying, I know.
# Authorize our chroot environment to use our host X server
xauth extract edit/.Xauthority username/unix:0
# copy our host environments DNS servers
cp /etc/resolv.conf edit/etc/
# copy our hosts environments hosts file 
cp /etc/hosts edit/etc 
# setup everything so our installations and application runnings work
mount --bind /dev edit/dev
# finally start working in our destination chroot environment
chroot edit 
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devpts none /dev/pts
# Setup localization
export HOME=/root
export LC_ALL=C
export XAUTHORITY=/.Xauthority
# required to correctly install applications
dbus-uuidgen > /var/lib/dbus/machine-id
dpkg-divert --local --rename --add /sbin/initctl
ln -s /bin/true /sbin/initctl

Customization Finally!

Now we can run programs, install applications, and uninstall unneeded applications. Here I will list various things that I have done to my distribution.

add-apt-repository ppa:killhellokitty/themes.ppa # A repository for my favorite dark theme
apt-get update # update our package database
apt-get install dorian-theme # Install my favorite dark theme
apt-get install gparted # install a partition manager
apt-get install gdmap # install a directory size visualizer
apt-get install sublime-text # install a syntax highlighting text editor
apt-get install dconf-tools # For finalizing edits to the theme and desktop environment
apt-get install dconf-editor # For editing the theme and desktop environment
apt-get install live-usb-install # For creating bootable LiveUSB sticks with persistence
apt-get install conky # Desktop overlay to show various system variables
# Compiz is a window manager with better visuals and power tools. It's used in Linux Mint Cinnamon
apt-get install compiz libdecoration0-dev compizconfig-settings-manager compiz-plugins compiz-plugins-extra 
dpkg -i /application.deb # install any '.deb' files that we previously copied
apt-get remove libre-office* # remove libreoffice
apt-get remove thunderbird* # remove thunderbird
apt-get remove pidgin* # remove pidgin
apt-get remove gimp* # remove gimp
# # # You may break the whole thing if you use this command. Use at your own risk.
# # # It's better and easier to use the 'Update Manager' GUI application
apt-get upgrade

Customizing the Theme and Desktop Environment

Now we can start running applications within the chroot environment to customize them. Lots of applications won't work. Most of the pre-installed applications do work though. The dconf-editor is daunting and will get wonky when you have to make changes after creating a final ISO. You are forewarned. This step is the most time consuming and most frustrating as the documentation on customizing is kept to a minimum to deter spin-off distributions.

# open dconf-editor to customize desktop environment variables
# Open the control center in Linux Mint Mate to customize keyboard shortcuts, wallpaper, etc...
# compile all changes. You must create this directory if it is not created already.
dconf-tools update /etc/skel/.config/dconf/

You can optionally copy your host environment settings outside of the chroot environment.

# exit the chroot environment
# create the config directory
mkdir /etc/skel/.config/dconf/
# copy of the whole directory and its files
cp -r ~/.config/dconf/ edit/etc/skel/.config

One final note is where to put configuration files for every user that is created including the liveCD user.


This folder is what the system looks in to create the home folder for any subsequent users. So copy all of your configuration files here while outside of your chroot environment.

# exit chroot environment
# copy custom bash commands file
cp ~/.bashrc edit/etc/skel/
# copy our conky configuration file 
cp ~/.conkyrc edit/etc/skel/

The Final Steps

Now we must clean up everything we did inside the chroot environment, create the compressed filesystem, update files used to boot, and create our finished ISO. We will start inside the chroot environment.

# enter the chroot environment
chroot edit
# remove any unused dependencies
apt autoremove
# clean up after installing applications 
apt clean
# Remove tmp files and our terminal history 
rm -rf /tmp/* ~/.bash_history
# Delete the file used to allow our chroot to show gui applications 
rm /.Xauthority 
# close the chroot environment
rm /var/lib/dbus/machine-id
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
umount /proc || umount -lf /proc
umount /sys
umount /dev/pts
# exit the chroot environment
umount edit/dev || umount -lf edit/dev
# this folder was created by 'xauth' and must be removed
rm edit/home/username

Create the ISO

Now for the mundane steps to creating the custom ISO. You can copy and paste the commands freely.

# make the manifest writable
chmod +w extract-cd/casper/filesystem.manifest
# write the manifest
sudo chroot edit dpkg-query -W --showformat='${Package} ${Version}\n' > extract-cd/casper/filesystem.manifest 
cp extract-cd/casper/filesystem.manifest extract-cd/casper/filesystem.manifest-desktop
sed -i '/ubiquity/d' extract-cd/casper/filesystem.manifest-desktop
sed -i '/casper/d' extract-cd/casper/filesystem.manifest-desktop
# remove the old filesystem
rm extract-cd/casper/filesystem.squashfs
# Compress the filesystem
# You may append '-comp xz' at the end for a savings of about 200MB
# This takes much longer to compress 
mksquashfs edit extract-cd/casper/filesystem.squashfs
# make sure the bootloader knows how big the filesystem is 
printf $(sudo du -sx --block-size=1 edit | cut -f1) > extract-cd/casper/filesystem.size
# remove the md5sums 
rm extract-cd/MD5SUMS
# change directory to the extract-cd directory
cd extract-cd
# recreate the md5sums 
find -type f -print0 | sudo xargs -0 md5sum | grep -v isolinux/ | sudo tee MD5SUMS 
# Make the ISO!
mkisofs -D -r -V "$IMAGE_NAME" -cache-inodes -J -l -b isolinux/isolinux.bin -c isolinux/ -no-emul-boot -boot-load-size 4 -boot-info-table -o ../CustomDistro.iso .

There you have it! A customized Linux distribution. You can archive it for system recovery, create bootable USB sticks and CDs, or distribute it to multiple workstations that require the same tools. Make note, the 'filesystem.squashfs' file can't be larger than 4GB if you want to put the ISO on a USB stick.