Diff for "InstallCDCustomization"


Differences between revisions 17 and 93 (spanning 76 versions)
Revision 17 as of 2006-09-08 17:55:23
Size: 18977
Editor: c-67-168-174-83
Comment:
Revision 93 as of 2020-01-28 16:26:26
Size: 32310
Editor: akrosikam
Comment: Updated ISO links to reflect currently-supported releases
Deletions are marked like this. Additions are marked like this.
Line 11: Line 11:
||<tablestyle="float:right; font-size: 0.9em; width:40%; background:#F1F1ED; margin: 0 0 1em 1em;" style="padding:0.5em;">'''Contents'''[[BR]][[TableOfContents(3)]]||

The process of customizing or "remastering" Ubuntu install CDs is not especially complex, but it is a little tedious and finicky. This page documents all the problems you might find; if it doesn't, please edit it!

The Ubuntu install CD (since Ubuntu 6.06, the 'alternative install' or 'server' CD) has three main parts: a bootloader (ISOLINUX on amd64/i386 systems, yaboot on powerpc) and its configuration, which start everything up; debian-installer (also known as d-i), which in this case is really a specialised miniature Ubuntu system; and a Debian-style repository structure, which is what takes up all that space on the disk in the directories "pool" and "dists". Building a new CD may involve modifications to all three parts.
||<tablestyle="float:right; font-size: 0.9em; width:40%; background:#F1F1ED; margin: 0 0 1em 1em;" style="padding:0.5em;"><<TableOfContents(3)>>||

The process of customizing or "remastering" Ubuntu installation CDs is not especially complex, but it is a little tedious and finicky.

The Ubuntu installation CD (since Ubuntu 6.06, the 'alternative install' or 'server' CD) has three main parts: a boot-loader (Isolinux on AMD64/x86 systems, yaboot on PowerPC) and its configuration (which starts everything up); debian-installer (also known as d-i, which in this case is really a specialized miniature Ubuntu system); and a Debian-style repository structure, which is what takes up disk space in the directories "pool" and "dists". Building a new CD may involve modifications to all three parts.

This page shows a simple recipe for customizing the CD. It assumes that you copy the contents of the installation CD to `/opt/cd-image/` on your local system and create a couple of other dirs in `/opt/`. Modify as needed.

{{attachment:IconsPage/note.png}} You might speed up the development cycle by using a virtual Ubuntu session, for example, using VirtualBox. You can then use the .ISO file to test rather than burning a CD. If you do, please note that you need to perform ALL operations described here on the GUEST system. Note that with VirtualBox, during an installation (Host key)-F4 will display the installation output and (Host key)-F1 will return you to the general status screen. Note that the host key is set to the right Ctrl key by default.

{{attachment:IconsPage/note.png}} This guide is for the 'Alternative Install' or 'Server Install' CDs. There is a page referring to customization of the [[LiveCDCustomization | Desktop (Live) CD]], and another guide on [[LiveCDCustomizationFromScratch | how to create a Live CD without using an existing CD at all.]]

Although the 'Server Install' images are supposed to fit on usual CD media, you may as well use DVD or BD (Blu-ray) media. In the following text, read "CD" as "CD, DVD, or BD".

At least since release 12.04, the images also work from USB stick or other hard-disk-like storage devices. USB stick on amd64 UEFI works since 14.04.

= Get the ISO =

Below is a list of original images which you can use :

||'''Type'''||||'''Ubuntu 16.04 LTS'''||||'''Ubuntu 18.04 LTS'''||||'''Ubuntu 19.10'''||
||Alternate||||n/a||||n/a||||n/a||
||Server||||[[http://releases.ubuntu.com/16.04/ubuntu-16.04.6-server-i386.iso|i386]]|[[http://releases.ubuntu.com/16.04/ubuntu-16.04.6-server-amd64.iso|amd64]]||||[[http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.3-server-amd64.iso|amd64]]||||[[http://cdimage.ubuntu.com/releases/19.10/release/ubuntu-19.10-server-amd64.iso|amd64]]||

As time goes by, some will vanish or be replaced. But [[http://releases.ubuntu.com/|releases.ubuntu.com]] will hopefully continue to show a list of available release directories with some `*server*.iso` images in them.
Line 19: Line 39:
Copy the entire installation CD to a directory on your hard drive. This guide will assume your CD image is in /opt/cd-image/, but you can put it wherever you like.  It will take around 1GB of hard drive space.

If you have an ISO file, you can mount it and copy files out of it without burning it to CD: `mount -o loop /path/to/iso /some/mountpoint`.

You can use '''rsync''' to copy the CD, or just 
Copy the entire installation CD to a directory on your hard drive. This guide will assume your CD image is in /opt/cd-image/, but you can put it wherever you like. It will take around 1GB of hard drive space.

If you have an ISO file, you can mount it and copy files out of it without burning it to CD:
{{{
mount -o loop /path/to/iso /some/mountpoint
}}} Use "Gmount-iso" program for a GUI method of mounting iso files. You can also try "ISO Master" to access the iso file directly without mounting
.

You can use '''rsync''' to copy the CD:
{{{
rsync -av /cdrom/ /opt/cd-image
}}}

or just
Line 28: Line 56:
}}} }}}

Note: the -p option for mkdir creates the leadin directories if they don't already exist. In this example, /opt is created if it doesn't already exist.
Line 32: Line 62:
If you use a filemanager program like Nautilus, be sure to launch it with "gksu nautilus" and mark "Show Hidden Files" from "View" menu or you miss some important files. After the copy is done, change file ownership from "root" if you don't plan to do the rest of the work with sudo.
Line 34: Line 66:
When the CD boots up, a Linux kernel is started and the installation tasks are initiated. The installer's default behaviour can be modified through the use of a "preseed" file, which feeds d-i answers to questions normally asked by debconf, or in other contexts. If you look closely at your install CD, you'll see that certain options (e.g. "server", "expert", "oem") already have preseed files assigned to them.

Suppose you are installing Ubuntu on a bunch of identical computers, and you already know the answers to certain questions (what country and time zone you're in, what keyboard you have, how the network should be configured, how you want to partition the hard disk, etc). You can "preseed" the answers to these questions in a very simple configuration file.
When the CD boots up, a Linux kernel is started and the installation tasks are initiated. The installer's default behavior can be modified through the use of a "preseed" file, which feeds d-i answers to questions normally asked by debconf, or in other contexts. If you look in the `preseed` folder in the install CD, you'll see that certain options (e.g. "server", "expert", "oem") already have preseed files assigned to them.  The [[https://help.ubuntu.com/lts/installation-guide/amd64/apb.html|installation guide]] has a detailed appendix on preseeding.

Suppose you are installing Ubuntu on a bunch of identical computers, and you already know the answers to certain questions (what country and time zone you're in, what keyboard you have, how the network should be configured, how you want to partition the hard disk, etc). You can "preseed" the answers to these questions in a very simple configuration file. There're several ways to setup the boot-loader configuration.
Line 40: Line 72:
We will create a preseed file called 'firewall.seed', which will live in the /preseed folder of the CD-ROM. We tell d-i where to find this file by modifying the bootloader configuration file, located in isolinux/isolinux.cfg, to pass appropriate parameters on the kernel command line. In /opt/cd-image/isolinux/isolinux.cfg, add a new section labelled like this:

__Ubuntu 5.10 and older:__

{{{
LABEL firewall
  kernel /install/vmlinuz
  append preseed/file=/cdrom/preseed/firewall.seed preseed/locale=en_NZ kbd-chooser/method=us vga=normal initrd=/install/initrd.gz ramdisk_size=12288 root=/dev/rd/0 rw --
}}}

__Ubuntu 6.06 and newer:__
We will create a preseed file called 'firewall.seed', which will live in the /preseed folder of the CD-ROM. We tell d-i where to find this file by modifying the boot-loader configuration file, located in isolinux/isolinux.cfg (or in 8.10 or later, isolinux/text.cfg), to pass appropriate parameters on the kernel command line. In /opt/cd-image/isolinux/isolinux.cfg, add a new section labeled like this:
Line 56: Line 78:
  append preseed/file=/cdrom/preseed/firewall.seed debian-installer/locale=en_NZ kbd-chooser/method=us initrd=/install/initrd.gz ramdisk_size=16384 root=/dev/ram rw quiet --
}}}

If you want to set the default action to booting with your custom seed, change the DEFAULT line to read 'DEFAULT firewall'.
  append preseed/file=/cdrom/preseed/firewall.seed debian-installer/locale=en_NZ console-setup/layoutcode=us initrd=/install/initrd.gz ramdisk_size=16384 root=/dev/ram rw quiet --
}}}
If you want to set the default selected menu item to your custom seed, change the DEFAULT line to read 'DEFAULT firewall'.

For totally automatic installation with a predefined language (in this example, Estonian), you need to add some more parameters:
{{{
LABEL firewall
  menu label ^Firewall installation (Estonian)
  kernel /install/vmlinuz
  append file=/cdrom/preseed/firewall.seed debian-installer/locale=et_EE console-setup/layoutcode=et localechooser/translation/warn-light=true localechooser/translation/warn-severe=true initrd=/install/initrd.gz ramdisk_size=16384 root=/dev/ram rw quiet
 --
}}}
To make the installer autochoose the default option and start installing after a timeout, add this line to isolinux/isolinux.cfg (in all versions).
{{{
timeout 10
}}}

{{attachment:IconsPage/note.png}} Timeout values are in tenths of a second, therefore a timeout value of 10 is equal to one second.
Line 63: Line 99:
(On Ubuntu 6.06 and older, use `kbd-chooser/method=us` rather than `console-setup/layoutcode=us`.)

== Changing grub.cfg to identify your preseed ==

We will create a preseed file called 'custom.seed', which will live in the /preseed folder of the CD-ROM. We tell d-i where to find this file by modifying the boot-loader configuration file, located in boot/grub/grub.cfg, to pass appropriate parameters on the kernel command line. In /opt/cd-image/boot/grub/grub.cfg, add a new section labeled like this:

{{{
menuentry "Install Ubuntu Server custom" {
  set gfxpayload=keep
  linux /install/vmlinuz file=/cdrom/preseed/custom.seed debian-installer/locale=en_US console-setup/layoutcode=us quiet ---
  initrd /install/initrd.gz
}
}}}
Line 65: Line 115:
A preseed file looks something like this (from the default ubuntu-server.seed on the 6.06 CD):

   {{{
# Always install the server kernel.
d-i base-installer/kernel/override-image string linux-server
# Don't install usplash.
d-i base-installer/kernel/linux/extra-packages-2.6 string
# Desktop system not installed; don't waste time and disk space copying it.
d-i archive-copier/desktop-task string ubuntu-standard
d-i archive-copier/ship-task string
# Only install the standard system and language packs.
d-i pkgsel/install-pattern string ~t^ubuntu-standard$
d-i pkgsel/language-pack-patterns string
# No language support packages.
d-i pkgsel/install-language-support boolean false
}}}

attachment:IconsPage/note.png The version of this file on some Breezy CD images was buggy: it set base-config/package-selection to `"~tubuntu-standard"` rather than `"~t^ubuntu-standard$"`. Use the new format in preference; the old one will break with Ubuntu 6.06 and newer.)

First notice the format. There are 4 fields:
A preseed file has 4 fields per line:
Line 91: Line 121:
attachment:IconsPage/important.png d-i expects there to be [:http://d-i.alioth.debian.org/manual/en.i386/apbs03.html:exactly one tab or space between variable type and variable value] (any other space is seen as being part of the value)

attachment:IconsPage/important.png The version of d-i used in 5.10 does not allow lines to be broken by the '\' character - this was introduced as of 6.06.

The easiest way to create a preseed file is to start with an example and modify it. There is a good
[http://archive.ubuntu.com/ubuntu/dists/breezy/main/installer-i386/current/doc/manual/en/apcs01.html preseed example in the Breezy installation manual]. You could also check out [http://wiki.debian.org/DebianInstaller/Preseed Debian's wiki page on preseeding the installer] - 6.06 and higher use the Etch version of the Debian installer.

Note: debconf-get-selections may not be installed on your system. It is part of the debconf-utils package.
You may install it thus:

{{{
sudo apt-get install debconf-utils
}}}

If you can't find the option you're looking for, try executing the following commands:

{{{
It looks something like this (from the default ubuntu-server.seed on the 16.04 CD):

   {{{
# Suggest LVM by default.
d-i partman-auto/init_automatically_partition string some_device_lvm
d-i partman-auto/init_automatically_partition seen false
# Install the Ubuntu Server seed.
tasksel tasksel/force-tasks string server
# Only install basic language packs. Let tasksel ask about tasks.
d-i pkgsel/language-pack-patterns string
# No language support packages.
d-i pkgsel/install-language-support boolean false
# Only ask the UTC question if there are other operating systems installed.
d-i clock-setup/utc-auto boolean true
# Verbose output and no boot splash screen.
d-i debian-installer/quiet boolean false
d-i debian-installer/splash boolean false
# Install the debconf oem-config frontend (if in OEM mode).
d-i oem-config-udeb/frontend string debconf
# Wait for two seconds in grub
d-i grub-installer/timeout string 2
# Add the network and tasks oem-config steps by default.
oem-config oem-config/steps multiselect language, timezone, keyboard, user, network, tasks
}}}

{{attachment:IconsPage/important.png}} d-i expects there to be [[http://d-i.alioth.debian.org/manual/en.i386/apbs03.html|exactly one tab or space between variable type and variable value]] (any other space is seen as being part of the value)

The easiest way to create a preseed file is to start with an example and modify it:
  1. The Ubuntu installation guide ([[https://help.ubuntu.com/16.04/installation-guide/amd64/apb.html|16.04]]) has examples of many common preseed directives. (Bear in mind that you may need to modify some to work on older versions.)
  2. You could check out [[http://wiki.debian.org/DebianInstaller/Preseed|Debian's wiki page on preseeding the installer]] - 6.06 and higher are aligned with Etch and newer versions of the Debian installer, although there are some important differences that apply to preseeding.
  3. If you can't find the option you're looking for you can generate a comprehensive preseed file based on your own install time choices by using `debconf-get-selections`

`debconf-get-selections` usage:
{{{
sudo apt-get install debconf-utils # It is part of the debconf-utils package.
Line 112: Line 160:
This will output a list of all debconf options you've chosen throughout your install; you can pick options out of this and put them into your preseed file. 

attachment:IconsPage/warning.png debconf-get-selections prints '''2''' spaces between variable type and variable value. For Breezy, you need to change this to one space before putting the line in a preseed file. 
This will output a list of all debconf options you've chosen throughout your install; you can pick options out of this and put them into your preseed file.

{{attachment:IconsPage/warning.png}} debconf-get-selections prints '''2''' spaces between variable type and variable value. You need to change this to one space before putting the line in a preseed file.
Line 118: Line 166:
__Ubuntu 5.10 and older:__

Package installation is controlled by the `base-config/package-selection` directive in the preseed. To install nothing, you can leave the value blank; to instruct d-i to install extra packages, or a minimal set, set this to an aptitude pattern. (To learn about patterns, see the aptitude documentation -- install ''aptitude-doc'' and read /usr/share/doc/aptitude/html/index.html).

For instance, to install an SSH server along with the standard installation, use this line:

{{{
base-config base-config/package-selection string ~t^ubuntu-standard$|~n^openssh-server$
}}}

~t marks a Task, added by the `ExtraOverride` line below. ~n is the name of a package - see aptitude documentation for details on patterns.

__Ubuntu 6.06 and newer:__

base-config has been removed from debian-installer: use
{{attachment:IconsPage/important.png}} base-config has been removed from debian-installer since Ubuntu 6.06.

In Ubuntu 6.06 and older:
Line 137: Line 174:
In Ubuntu 8.04 and newer: (packages may be separated with commas and/or spaces and continued to another line with a back-slash):

{{{
d-i pkgsel/include string gstreamer0.10-plugins-base \
 gstreamer0.10-plugins-good \
 gstreamer0.10-plugins-ugly \
 gstreamer0.10-plugins-bad
}}}

{{attachment:IconsPage/warning.png}} The installer can not install packages which rely on services that would normally be running in an installed system, but which are not running in the environment of the Debian installer. One example of this would be packages which create or modify a database at installation time, and require a postgresql or mysql server to be running. In this case, you will need to use a postinst script, start the necessary database server in the /target chroot, and then call "apt-install" (if outside the chroot environment) or apt-get (inside the chroot).
Line 139: Line 187:
A different mechanism is used to install additional languages. Preseed the detailed locale question asked by the installer in expert mode. See the first column of `/usr/share/i18n/SUPPORTED` for the locale names you can use here. For example, to add support for Bengali and Tamil, use this line:   A different mechanism is used to install additional languages. Preseed the detailed locale question asked by the installer in expert mode. See the first column of `/usr/share/i18n/SUPPORTED` for the locale names you can use here. For example, to add support for Bengali and Tamil, use this line:
Line 145: Line 193:
=== Running a Final Script ===
You can run a script in the final part of the installation. The following example runs a script that has been copied onto the installation CD in the setup/install folder. This script runs in the target environment, thus can run scripts in any language (e.g. Python or Perl) that has been installed on the target system.

{{{
d-i preseed/late_command string chroot /target bash /cdrom/setup/install/settings.sh
}}}

{{attachment:IconsPage/warning.png}} The above command may not work on 8.10 or later; to copy the script to the target and then execute it, try this:

{{{
d-i preseed/late_command string cp /cdrom/finisher/finisher.sh /target/root/; chroot /target chmod +x /root/finisher.sh; chroot /target bash /root/finisher.sh
}}}

Generally, a script run from the seed file via late_command, cannot interact with the user. If you need to interact, there are generally three options:

 * Create a custom UDEB that interacts with debconf, and include it with the CD.
 * Create a 'firstrun' script that executes the first time the system boots, and disables itself on completion.
 * [[/AccessDebconfFromYourScript|Access debconf directly within your script]].

{{attachment:IconsPage/warning.png}} A preseed script run via late_command that attempts to run "chroot /target apt-get ..." (or similar) may run into problems (e.g. file descriptor 3 not found in the postinst stage of some packages, dash being one example). This is caused by your script inheriting environment variables from the already running installer. To solve this, clear the environment variables in your script before calling apt-get:
{{{
unset DEBCONF_REDIR
unset DEBCONF_FRONTEND
unset DEBIAN_HAS_FRONTEND
unset DEBIAN_FRONTEND
}}}
Line 147: Line 222:
Probably the prime motivation to build your own install CDs is to modify which packages are installed; in particular you may want to add some packages to the CD.  

The easiest way to do this is to build an 'extras' repository structure, containing only your extra .debs, and merge these into the CD file hierarchy before rebuilding the .ISO image.  This guide will step you through how to do this.

This requires you to generate the Packages files that defines what files are in your repository; the Release file that indexes your Packages files, and the signed Release.gpg file, approving the repository as being official.  
Probably the prime motivation to build your own install CDs is to modify which packages are installed; in particular you may want to add some packages to the CD.

The easiest way to do this is to build an 'extras' repository structure, containing only your extra .debs, and merge these into the CD file hierarchy before rebuilding the .ISO image. This guide will step you through how to do this.

This requires you to generate the Packages files that defines what files are in your repository; the Release file that indexes your Packages files, and the signed Release.gpg file, approving the repository as being official.
Line 155: Line 230:
{{attachment:IconsPage/important.png}} The following example references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate.
Line 157: Line 234:
    {{{ {{{
Line 159: Line 236:
mkdir -p dists/dapper/extras/binary-i386 pool/extras/ isolinux preseed
}}}

Put all the extra .debs you want on your CD into `pool/extras`.    Create the file `dists/dapper/extras/binary-i386/Release` with the following content:

    {{{
Archive: dapper
Version: 6.06
Component: extras

Origin: Ubuntu
Label: Ubuntu
Architecture: i386
}}}

O
n the [:/Scripts:scripts page] there is a useful script that will strip out all of the packages from your CD image that are not currently installed. You will need to run `apt-ftparchive` (below) to generate the Packages file.
mkdir -p pool/extras/
}}}

Put all the extra .debs you want on your CD into `pool/extras`.

On the [[/Scripts|scripts page]] there is a useful script that will strip out all of the packages from your CD image that are not currently installed. You will need to run `apt-ftparchive` (below) to generate the Packages file.
Line 179: Line 245:
In order to sign the Release file, we need to use GPG. The install system will then check the signature against the public keys held in the package ubuntu-keyring.  You do not have a private key that matches one of the ones in the shipped ubuntu-keyring, so we need to build a custom version of the ubuntu-keyring package. Install the `gnupg` package if you do not have it already. In order to sign the Release file, we need to use GPG. The install system will then check the signature against the public keys held in the package ubuntu-keyring. You do not have a private key that matches one of the ones in the shipped ubuntu-keyring, so we need to build a custom version of the ubuntu-keyring package. Install the `gnupg` package if you do not have it already.
Line 183: Line 249:
In another directory (I use `/opt/build/`), we will download the source for the ubuntu-keyring package, unpack it, add our own GPG key, and rebuild the package.  These steps import the 2 Ubuntu public signing keys into your main keyring, then exports them, along with your own public signing key, into a replacement keyring. "YOURKEYID" should be replaced with the 8-digit hexadecimal code that gpg tells you when you do the --list-keys command."Signing Key Name" is what you used in the previous step, when running `gpg --gen-key`.

To clarify, below is an example 'gpg --list-keys' response.  In this example, "YOURKEYID" immediately follows the '/' on the line beginning with 'pub' (which in this example is '437D05B5'.)
In another directory (I use `/opt/build/`), we will download the source for the ubuntu-keyring package, unpack it, add our own GPG key, and rebuild the package. These steps import the 2 Ubuntu public signing keys into your main keyring, then exports them, along with your own public signing key, into a replacement keyring. "YOURKEYID" should be replaced with the 8-digit hexadecimal code that gpg tells you when you do the --list-keys command. "Signing Key Name" is what you used in the previous step, when running `gpg --gen-key`.

To clarify, below is an example 'gpg --list-keys' response. In this example, "YOURKEYID" immediately follows the '/' on the line beginning with 'pub' (which in this example is '437D05B5'.)
Line 194: Line 260:
Note: the following example requires the fakeroot package which may not be installed on your system.
You may install it thus:

{{{
sudo apt-get install fakeroot
}}}
If you change the package's version number (e.g. using `dch`), then make sure that the version number you choose does not contain a "`-`" character: if it does, then you'll be converting the package away from the "native" format and you will have to do some extra steps. It's simpler to use a version number such as "`2012.05.19+custom1`", putting your preferred local part after the "`+`" character.
Line 203: Line 264:
    {{{ {{attachment:IconsPage/important.png}} The following example references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate.

{{{
cd /opt/build
sudo apt-get install fakeroot # requires the fakeroot package which may not be installed on your system.
Line 205: Line 270:
cd ubuntu-keyring-2005.01.12.1/keyrings cd ubuntu-keyring-2012.05.19/keyrings
Line 208: Line 273:
gpg --export FBB75451 437D05B5 YOURKEYID > ubuntu-archive-keyring.gpg
cd .. (you are now on ubuntu-keyring-2005.01.12.1)
gpg --export FBB75451 437D05B5 C0B21F32 EFE21092 YOURKEYID > ubuntu-archive-keyring.gpg
cd ..    # you are now on ubuntu-keyring-2012.05.19
Line 211: Line 276:
cd .. (you are now on the directory where you started, in the example, /opt/build) cd ..  # you are now on the directory where you started, in the example, /opt/build
Line 217: Line 282:
== Generate a new filesystem.squashfs with the updated ubuntu-archive-keyring.gpg ==

To prevent the possible issue during installation, we need to regenerate filesystem.squashfs by updating the ubuntu-archive-keyring.gpg we just exported. There are three paths to being replaced:
 
 * $chroot/usr/share/keyrings/ubuntu-archive-keyring.gpg
 * $chroot/etc/apt/trusted.gpg
 * $chroot/var/lib/apt/keyrings/ubuntu-archive-keyring.gpg

Furthermore, filesystem.size also needs to be updated:
{{{
cd new-squashfs-root
du -sx --block-size=1 ./ | cut -f1 > /opt/cd-image/install/filesystem.size
}}}
Line 220: Line 298:
apt-ftparchive builds the Packages and Packages.gz files, needed by the installer. In order to use apt-ftparchive, we will need to provide it with some configuration and some index files.

We will put the index files in /opt/indices:

    
{{{
mkdir -p /opt/indices
`apt-ftparchive` builds the `Packages` and `Packages.gz` files, needed by the installer. In order to use `apt-ftparchive` we will need to provide it with some configuration and some index files.

{{attachment:IconsPage/important.png}} If you will be adding .deb files to pool/universe (eg. customizing xubuntu) you will also need to wget extra.universe and universe files.

We will put the index files in `/opt/indices`:
{{{
mkdir -p /opt/indices /opt/apt-ftparchive
Line 227: Line 306:
DIST=dapper; wget http://archive.ubuntu.com/ubuntu/indices/override.$DIST.{extra.main,main,main.debian-installer,restricted,restricted.debian-installer}
}}}

Create the files "apt-ftparchive-deb.conf, "apt-ftparchive-udeb.conf", "apt-ftparchive-extras.conf", and "release.conf" in a directory (/opt/apt-ftparchive), substituting /opt/cd-image/ for the path to your CD image directory, and /opt/indices/ for the location of the index files, if they differ.

__apt-ftparchive-deb.conf:__
DIST=xenial
for SUFFIX in extra.main main main.debian-installer restricted restricted.debian-installer; do
  wget http://archive.ubuntu.com/ubuntu/indices/override.$DIST.$SUFFIX
done
}}}

Create the files `apt-ftparchive-deb.conf`, `apt-ftparchive-udeb.conf`, `apt-ftparchive-extras.conf`, and `release.conf` in a directory (`/opt/apt-ftparchive`), substituting `/opt/cd-image/` for the path to your CD image directory, and `/opt/indices/` for the location of the index files, if they differ.

{{attachment:IconsPage/important.png}} The .conf files shown here are sufficient if you are ONLY making changes to .deb files under pool/main and pool/restricted. If you are adding security updates to a Xubuntu customized CD, though, you will be updating .deb files under pool/universe also, so you will need to add lines to `apt-ftparchive-deb.conf` for universe, similar to the lines shown for main. You will also need to run extraoverride.pl for universe as well as for main - see below.

__/opt/apt-ftparchive/apt-ftparchive-deb.conf:__
Line 244: Line 328:
  Packages "dists/dapper/main/binary-i386/Packages";
  BinOverride "/opt/indices/override.dapper.main";
  ExtraOverride "path/to/indices/override.dapper.extra.main";
  Packages "dists/xenial/main/binary-amd64/Packages";
  BinOverride "/opt/indices/override.xenial.main";
  ExtraOverride "/opt/indices/override.xenial.extra.main";
Line 250: Line 334:
 Packages "dists/dapper/restricted/binary-i386/Packages";
 BinOverride "/opt/indices/override.dapper.restricted";
;
 Packages "dists/xenial/restricted/binary-amd64/Packages";
 BinOverride "/opt/indices/override.xenial.restricted";
};
Line 266: Line 350:
The ExtraOverride component above is needed to add the Task header to main packages, referenced from the preseed file with ~t<task name>. This is not supplied - but can be extracted from the existing main Packages file with a simple perl script :- The !ExtraOverride component above is needed to add the `Task:` line to main packages, referenced from the preseed file with ~t<task name>. This is not supplied - but can be extracted from the existing main Packages file with the simple perl script below.
Line 269: Line 353:
#! /usr/bin/perl \#!/usr/bin/env perl
Line 273: Line 357:
# extraoverride.pl < /media/cdrom0/dists/dapper/main/binary-i386/Packages > path/to/indices/override.dapper.extra.main # extraoverride.pl < /opt/cd-image/dists/xenial/main/binary-amd64/Packages >> /opt/indices/override.xenial.extra.main
Line 278: Line 362:
        if (/^$/) {         if (/^$/ && defined($task)) {
Line 280: Line 364:
                undef $package;
                undef $task;
Line 291: Line 377:
__apt-ftparchive-udeb.conf:__ {{attachment:IconsPage/note.png}} If customizing Xubuntu, and adding new .deb files to pool/universe, run this script for the universe repository also.

{{attachment:IconsPage/note.png}} The !ExtraOverride process can be optional to skip it.

__/opt/apt-ftparchive/apt-ftparchive-udeb.conf:__
Line 303: Line 393:
  Packages "dists/dapper/main/debian-installer/binary-i386/Packages";
  BinOverride "/opt/indices/override.dapper.main.debian-installer";
  Packages "dists/xenial/main/debian-installer/binary-amd64/Packages";
  BinOverride "/opt/indices/override.xenial.main.debian-installer";
Line 308: Line 398:
  Packages "dists/dapper/restricted/debian-installer/binary-i386/Packages";
  BinOverride "/opt/indices/override.dapper.restricted.debian-installer";
  Packages "dists/xenial/restricted/debian-installer/binary-amd64/Packages";
  BinOverride "/opt/indices/override.xenial.restricted.debian-installer";
Line 324: Line 414:
__apt-ftparchive-extras.conf:__ __/opt/apt-ftparchive/apt-ftparchive-extras.conf:__
Line 336: Line 426:
  Packages "dists/dapper/extras/binary-i386/Packages";   Packages "dists/xenial/extras/binary-amd64/Packages";
Line 351: Line 441:
__release.conf__ {{attachment:IconsPage/important.png}}
You need to build the Packages file in ''dists/xenial/extras/binary-amd64/Packages'' using ''dpkg-scanpackages''. See [[http://www.debian.org/doc/manuals/repository-howto/repository-howto|here]] for an explanation.

{{attachment:IconsPage/important.png}} The following example of creating Packages references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate. Use apt-ftparchive to finish above step.

{{{
cd /opt/cd-image
apt-ftparchive packages pool/extras > dists/stable/extras/binary-amd64/Packages
gzip -c dists/stable/extras/binary-amd64/Packages | tee dists/stable/extras/binary-amd64/Packages.gz > /dev/null
}}}

__/opt/apt-ftparchive/release.conf__
Line 358: Line 460:
APT::FTPArchive::Release::Suite "dapper";
APT::FTPArchive::Release::Version "6.06";
APT::FTPArchive::Release::Codename "dapper";
APT::FTPArchive::Release::Architectures "i386";
APT::FTPArchive::Release::Suite "xenial";
APT::FTPArchive::Release::Version "16.04";
APT::FTPArchive::Release::Codename "xenial";
APT::FTPArchive::Release::Architectures "amd64";
Line 363: Line 465:
APT::FTPArchive::Release::Description "Ubuntu 6.06 LTS"; APT::FTPArchive::Release::Description "Ubuntu 16.04 LTS";
Line 367: Line 469:
   
{{{
BUILD=/opt/firewall-image-dapper/

{{{
BUILD=/opt/cd-image
Line 371: Line 473:
DISTNAME=dapper DISTNAME=xenial
Line 376: Line 478:
apt-ftparchive -c $APTCONF generate /opt/apt-ftparchive/apt-ftparchive-extra.conf apt-ftparchive -c $APTCONF generate /opt/apt-ftparchive/apt-ftparchive-extras.conf
Line 384: Line 486:

= Burning the CD =

At this point, you have a directory which is ready to be collected into an .ISO file and then burnt to a CD.
"YOURKEYID" is the key id you put in your own compiled keyring package before.

= Preparing the bootable medium =

At this point, you have a directory which is ready to be collected into an .ISO file and then burnt to a CD or copied to a USB stick.
Line 391: Line 494:
__x86 (i386) and x86_64 (AMD64)__ __x86 and AMD64__
Line 405: Line 508:
__x86 and AMD64 with isohybrid__

The original `i386` and `amd64` ISOs have a Master Boot Record (MBR) which makes them bootable from USB stick via legacy BIOS firmware.
{{{
# The MBR x86 machine code bytes from the original ISO are known to match
# the isolinux.bin file inside that ISO. So copy them to a file in /tmp/.
OLD_IMAGE=/path/to/iso
MBR_FILE=/tmp/ubuntu_isohybrid_mbr.img
dd if="$OLD_IMAGE" bs=1 count=446 of="$MBR_FILE"

IMAGE=custom.iso
BUILD=/opt/cd-image/

xorriso -as mkisofs -r -V "Custom Ubuntu Install CD" \
            -cache-inodes -J -l \
            -isohybrid-mbr "$MBR_FILE" \
            -partition_offset 16 \
            -c isolinux/boot.cat \
            -b isolinux/isolinux.bin \
               -no-emul-boot -boot-load-size 4 -boot-info-table \
            -o "$IMAGE" \
            "$BUILD"
            "$BUILD"

rm "$MBR_FILE"
}}}

__AMD64 with isohybrid and UEFI__

Additionally to the MBR for legacy BIOS, the `amd64` ISOs since 14.04 can boot from CD and from USB stick via the modern UEFI firmware. Its entry point is marked for USB stick by the MBR partition entry 2, which points to the data content of file `/boot/grub/efi.img`. Together with UEFI bootability from CD this is achieved by the additional options from `-eltorito-alt-boot` to `-isohybrid-gpt-basdat`.
{{{
OLD_IMAGE=/path/to/iso
MBR_FILE=/tmp/ubuntu_isohybrid_mbr.img
dd if="$OLD_IMAGE" bs=1 count=446 of="$MBR_FILE"

IMAGE=custom.iso
BUILD=/opt/cd-image/

xorriso -as mkisofs -r -V "Custom Ubuntu Install CD" \
            -cache-inodes -J -l \
            -isohybrid-mbr "$MBR_FILE" \
            -c isolinux/boot.cat \
            -b isolinux/isolinux.bin \
               -no-emul-boot -boot-load-size 4 -boot-info-table \
            -eltorito-alt-boot \
            -e boot/grub/efi.img \
               -no-emul-boot -isohybrid-gpt-basdat \
            -o "$IMAGE" \
            "$BUILD"

rm "$MBR_FILE"
}}}
Line 407: Line 563:
Download [http://people.ubuntu.com/~cjwatson/hfs.map the HFS map], then use the following command:  Download [[http://people.ubuntu.com/~cjwatson/hfs.map|the HFS map]], then use the following command:
Line 416: Line 572:
            -hfs-volid Ubuntu/PowerPC_dapper \             -hfs-volid Ubuntu/PowerPC_hardy \
Line 425: Line 581:
mkisofs -r -V 'Custom Ubuntu 5.10 install ia64' \ mkisofs -r -V 'Custom Ubuntu Install CD' \
Line 432: Line 588:
== Burning the image to CD ==

To detect the location of your CD drive, try `cdrecord --scanbus`. For a primary IDE CD drive on /dev/hdc:

{{{
sudo nice -18 cdrecord dev=ATA:0,1,0 --speed=24 --blank=fast -v -gracetime=2 -tao $IMAGE
}}}

You will burn a lot of coasters in experimenting with this process, so please use rewritable media!
== Burning the image to CD, DVD, or Blu-ray ==

{{{
sudo xorriso -as cdrecord dev=/dev/sr0 blank=as_needed -v $IMAGE
}}}

The first optical drive of a contemporary GNU/Linux system has address `/dev/sr0`. If in doubt, run the following command to learn about the existing drives and their /dev file adresses.
{{{
sudo xorriso -devices
}}}

If your drive or media are old, then you might burn a lot of coasters in experimenting with this process. Re-usable media can ease the pain: CD-RW, DVD-RW, DVD+RW, DVD-RAM, BD-RE.

== Putting an isohybrid image onto USB stick ==

If the `x86 and AMD` image was made by `xorriso` with `isohybrid` options, or if the `x86 and AMD` image was postprocessed by SYSLINUX program `isohybrid`, then it will boot from USB stick or hard disk, too.

Such an image is not to be unpacked and installed to the USB stick by a program like 'Rufus' or 'UNetbootin', but rather to be written plainly to the base device file of the USB stick. This implies that the partition table of the stick will be overwritten and thus all data on the stick will become unaccessible, if not overwritten.

=== Verify device address or make a backup ===

The main problem on a GNU/Linux system is that you need superuser power to overwrite the whole USB stick, and that this power suffices to also spoil the content of your hard disk.

So first verify that the device file address really leads to the intended device (e.g. by reading a few megabytes and watching it blink). If the USB stick is supposed to be Linux device "/dev/sdh":
{{{
sudo umount /dev/sdh*
dd if=/dev/sdh of=/dev/null bs=1024 count=100000
}}}
or by making a backup of its complete content in a compressed disk file:
{{{
sudo umount /dev/sdh*
dd if=/dev/sdh | gzip >"$HOME"/red_usb_stick.gz
}}}
(Your `/dev/sd` address will probably end by a lower letter than "h". But this paragraph is all about not to spoil `/dev/sda` and other hard disks by mistake.)

=== Write to USB stick ===

Once you are convinced that this is the right device file address, copy the ISO image onto the USB stick by:
{{{
sudo dd if="$IMAGE" bs=1M of=/dev/sdh ; sync
}}}

=== Eventually restore backup ===

To later restore the original content of the USB stick, take the same care to really use the correct address and then:
{{{
dd if="$HOME"/red_usb_stick.gz | sudo gunzip >/dev/sdh
}}}
Of course, the Ubuntu ISO image will be overwritten by this restore run.
Line 444: Line 640:
You can now boot off your CD. Select the new menu item you created. If you've used preseeding to stop the CD asking questions, the installation could be totally automatic. You can now boot off your CD or USB stick. Select the new menu item you created. If you've used preseeding to stop the CD asking questions, the installation could be totally automatic.
Line 449: Line 645:
 * If you get a red d-i screen, check the error message (use Alt-F2, Alt-F3 etc to cycle through the terminals to read the log), and fix your CD appropriately.  * If you get a red d-i screen, check the error message (use Alt-F2, Alt-F3 etc to cycle through the terminals to read the log), and fix your CD appropriately. The log file is /var/log/syslog , check the last lines.
Line 453: Line 649:
Check out some [:/Scripts:install CD customization scripts] that can be used to automate this process.  * Check out some [[/Scripts|install CD customization scripts]] that can be used to automate this process.

Introduction

The process of customizing or "remastering" Ubuntu installation CDs is not especially complex, but it is a little tedious and finicky.

The Ubuntu installation CD (since Ubuntu 6.06, the 'alternative install' or 'server' CD) has three main parts: a boot-loader (Isolinux on AMD64/x86 systems, yaboot on PowerPC) and its configuration (which starts everything up); debian-installer (also known as d-i, which in this case is really a specialized miniature Ubuntu system); and a Debian-style repository structure, which is what takes up disk space in the directories "pool" and "dists". Building a new CD may involve modifications to all three parts.

This page shows a simple recipe for customizing the CD. It assumes that you copy the contents of the installation CD to /opt/cd-image/ on your local system and create a couple of other dirs in /opt/. Modify as needed.

IconsPage/note.png You might speed up the development cycle by using a virtual Ubuntu session, for example, using VirtualBox. You can then use the .ISO file to test rather than burning a CD. If you do, please note that you need to perform ALL operations described here on the GUEST system. Note that with VirtualBox, during an installation (Host key)-F4 will display the installation output and (Host key)-F1 will return you to the general status screen. Note that the host key is set to the right Ctrl key by default.

IconsPage/note.png This guide is for the 'Alternative Install' or 'Server Install' CDs. There is a page referring to customization of the Desktop (Live) CD, and another guide on how to create a Live CD without using an existing CD at all.

Although the 'Server Install' images are supposed to fit on usual CD media, you may as well use DVD or BD (Blu-ray) media. In the following text, read "CD" as "CD, DVD, or BD".

At least since release 12.04, the images also work from USB stick or other hard-disk-like storage devices. USB stick on amd64 UEFI works since 14.04.

Get the ISO

Below is a list of original images which you can use :

Type

Ubuntu 16.04 LTS

Ubuntu 18.04 LTS

Ubuntu 19.10

Alternate

n/a

n/a

n/a

Server

i386|amd64

amd64

amd64

As time goes by, some will vanish or be replaced. But releases.ubuntu.com will hopefully continue to show a list of available release directories with some *server*.iso images in them.

Copy the CD to your hard drive

Copy the entire installation CD to a directory on your hard drive. This guide will assume your CD image is in /opt/cd-image/, but you can put it wherever you like. It will take around 1GB of hard drive space.

If you have an ISO file, you can mount it and copy files out of it without burning it to CD:

mount -o loop /path/to/iso /some/mountpoint

Use "Gmount-iso" program for a GUI method of mounting iso files. You can also try "ISO Master" to access the iso file directly without mounting.

You can use rsync to copy the CD:

rsync -av /cdrom/ /opt/cd-image

or just

mkdir -p /opt/cd-image
cp -rT /cdrom /opt/cd-image

Note: the -p option for mkdir creates the leadin directories if they don't already exist. In this example, /opt is created if it doesn't already exist.

Be sure to catch the folder .disk - if you try and copy /cdrom/*, it will ignore the .disk folder, as Bash expands the * to mean "everything it can see".

If you use a filemanager program like Nautilus, be sure to launch it with "gksu nautilus" and mark "Show Hidden Files" from "View" menu or you miss some important files. After the copy is done, change file ownership from "root" if you don't plan to do the rest of the work with sudo.

Modify installer behaviour using a Preseed file

When the CD boots up, a Linux kernel is started and the installation tasks are initiated. The installer's default behavior can be modified through the use of a "preseed" file, which feeds d-i answers to questions normally asked by debconf, or in other contexts. If you look in the preseed folder in the install CD, you'll see that certain options (e.g. "server", "expert", "oem") already have preseed files assigned to them. The installation guide has a detailed appendix on preseeding.

Suppose you are installing Ubuntu on a bunch of identical computers, and you already know the answers to certain questions (what country and time zone you're in, what keyboard you have, how the network should be configured, how you want to partition the hard disk, etc). You can "preseed" the answers to these questions in a very simple configuration file. There're several ways to setup the boot-loader configuration.

Changing isolinux.cfg to identify your preseed

We will create a preseed file called 'firewall.seed', which will live in the /preseed folder of the CD-ROM. We tell d-i where to find this file by modifying the boot-loader configuration file, located in isolinux/isolinux.cfg (or in 8.10 or later, isolinux/text.cfg), to pass appropriate parameters on the kernel command line. In /opt/cd-image/isolinux/isolinux.cfg, add a new section labeled like this:

LABEL firewall
  menu label ^Firewall installation
  kernel /install/vmlinuz
  append  preseed/file=/cdrom/preseed/firewall.seed debian-installer/locale=en_NZ console-setup/layoutcode=us initrd=/install/initrd.gz ramdisk_size=16384 root=/dev/ram rw quiet --

If you want to set the default selected menu item to your custom seed, change the DEFAULT line to read 'DEFAULT firewall'.

For totally automatic installation with a predefined language (in this example, Estonian), you need to add some more parameters:

LABEL firewall
  menu label ^Firewall installation (Estonian)
  kernel /install/vmlinuz
  append  file=/cdrom/preseed/firewall.seed debian-installer/locale=et_EE console-setup/layoutcode=et localechooser/translation/warn-light=true localechooser/translation/warn-severe=true initrd=/install/initrd.gz ramdisk_size=16384 root=/dev/ram rw quiet
 --

To make the installer autochoose the default option and start installing after a timeout, add this line to isolinux/isolinux.cfg (in all versions).

timeout 10

IconsPage/note.png Timeout values are in tenths of a second, therefore a timeout value of 10 is equal to one second.

You must specify a locale and keyboard on the command line, as these questions are asked before the seed is loaded. You can also set DEBCONF_PRIORITY here to ensure you don't see any unnecessary debconf questions.

(On Ubuntu 6.06 and older, use kbd-chooser/method=us rather than console-setup/layoutcode=us.)

Changing grub.cfg to identify your preseed

We will create a preseed file called 'custom.seed', which will live in the /preseed folder of the CD-ROM. We tell d-i where to find this file by modifying the boot-loader configuration file, located in boot/grub/grub.cfg, to pass appropriate parameters on the kernel command line. In /opt/cd-image/boot/grub/grub.cfg, add a new section labeled like this:

menuentry "Install Ubuntu Server custom" {
  set gfxpayload=keep
  linux  /install/vmlinuz file=/cdrom/preseed/custom.seed debian-installer/locale=en_US console-setup/layoutcode=us quiet ---
  initrd /install/initrd.gz
}

Writing the preseed file

A preseed file has 4 fields per line:

  1. identity of the program which will pick up this command
  2. name of the variable whose value will be passed
  3. variable type
  4. value of variable

It looks something like this (from the default ubuntu-server.seed on the 16.04 CD):

  • # Suggest LVM by default.
    d-i     partman-auto/init_automatically_partition       string some_device_lvm
    d-i     partman-auto/init_automatically_partition       seen false
    # Install the Ubuntu Server seed.
    tasksel tasksel/force-tasks     string server
    # Only install basic language packs. Let tasksel ask about tasks.
    d-i     pkgsel/language-pack-patterns   string
    # No language support packages.
    d-i     pkgsel/install-language-support boolean false
    # Only ask the UTC question if there are other operating systems installed.
    d-i     clock-setup/utc-auto    boolean true
    # Verbose output and no boot splash screen.
    d-i     debian-installer/quiet  boolean false
    d-i     debian-installer/splash boolean false
    # Install the debconf oem-config frontend (if in OEM mode).
    d-i     oem-config-udeb/frontend        string debconf
    # Wait for two seconds in grub
    d-i     grub-installer/timeout  string 2
    # Add the network and tasks oem-config steps by default.
    oem-config      oem-config/steps        multiselect language, timezone, keyboard, user, network, tasks

IconsPage/important.png d-i expects there to be exactly one tab or space between variable type and variable value (any other space is seen as being part of the value)

The easiest way to create a preseed file is to start with an example and modify it:

  1. The Ubuntu installation guide (16.04) has examples of many common preseed directives. (Bear in mind that you may need to modify some to work on older versions.)

  2. You could check out Debian's wiki page on preseeding the installer - 6.06 and higher are aligned with Etch and newer versions of the Debian installer, although there are some important differences that apply to preseeding.

  3. If you can't find the option you're looking for you can generate a comprehensive preseed file based on your own install time choices by using debconf-get-selections

debconf-get-selections usage:

sudo apt-get install debconf-utils    # It is part of the debconf-utils package.
debconf-get-selections --installer > somefile.txt
debconf-get-selections >> somefile.txt

This will output a list of all debconf options you've chosen throughout your install; you can pick options out of this and put them into your preseed file.

IconsPage/warning.png debconf-get-selections prints 2 spaces between variable type and variable value. You need to change this to one space before putting the line in a preseed file.

Installing extra packages in your preseed file

IconsPage/important.png base-config has been removed from debian-installer since Ubuntu 6.06.

In Ubuntu 6.06 and older:

d-i     pkgsel/install-pattern          string ~t^ubuntu-standard$|~n^openssh-server$

In Ubuntu 8.04 and newer: (packages may be separated with commas and/or spaces and continued to another line with a back-slash):

d-i     pkgsel/include  string  gstreamer0.10-plugins-base \
 gstreamer0.10-plugins-good \
 gstreamer0.10-plugins-ugly \
 gstreamer0.10-plugins-bad

IconsPage/warning.png The installer can not install packages which rely on services that would normally be running in an installed system, but which are not running in the environment of the Debian installer. One example of this would be packages which create or modify a database at installation time, and require a postgresql or mysql server to be running. In this case, you will need to use a postinst script, start the necessary database server in the /target chroot, and then call "apt-install" (if outside the chroot environment) or apt-get (inside the chroot).

Installing language support

A different mechanism is used to install additional languages. Preseed the detailed locale question asked by the installer in expert mode. See the first column of /usr/share/i18n/SUPPORTED for the locale names you can use here. For example, to add support for Bengali and Tamil, use this line:

d-i localechooser/supported-locales multiselect bn_IN, ta_IN

Running a Final Script

You can run a script in the final part of the installation. The following example runs a script that has been copied onto the installation CD in the setup/install folder. This script runs in the target environment, thus can run scripts in any language (e.g. Python or Perl) that has been installed on the target system.

d-i preseed/late_command string chroot /target bash /cdrom/setup/install/settings.sh

IconsPage/warning.png The above command may not work on 8.10 or later; to copy the script to the target and then execute it, try this:

d-i preseed/late_command string cp /cdrom/finisher/finisher.sh /target/root/; chroot /target chmod +x /root/finisher.sh; chroot /target bash /root/finisher.sh

Generally, a script run from the seed file via late_command, cannot interact with the user. If you need to interact, there are generally three options:

  • Create a custom UDEB that interacts with debconf, and include it with the CD.
  • Create a 'firstrun' script that executes the first time the system boots, and disables itself on completion.
  • Access debconf directly within your script.

IconsPage/warning.png A preseed script run via late_command that attempts to run "chroot /target apt-get ..." (or similar) may run into problems (e.g. file descriptor 3 not found in the postinst stage of some packages, dash being one example). This is caused by your script inheriting environment variables from the already running installer. To solve this, clear the environment variables in your script before calling apt-get:

unset DEBCONF_REDIR
unset DEBCONF_FRONTEND
unset DEBIAN_HAS_FRONTEND
unset DEBIAN_FRONTEND

Modify pool structure to include more packages

Probably the prime motivation to build your own install CDs is to modify which packages are installed; in particular you may want to add some packages to the CD.

The easiest way to do this is to build an 'extras' repository structure, containing only your extra .debs, and merge these into the CD file hierarchy before rebuilding the .ISO image. This guide will step you through how to do this.

This requires you to generate the Packages files that defines what files are in your repository; the Release file that indexes your Packages files, and the signed Release.gpg file, approving the repository as being official.

Create an "Extras" component

IconsPage/important.png The following example references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate.

Create directories for your new component (substituting your version where appropriate):

cd /opt/cd-image
mkdir -p pool/extras/

Put all the extra .debs you want on your CD into pool/extras.

On the scripts page there is a useful script that will strip out all of the packages from your CD image that are not currently installed. You will need to run apt-ftparchive (below) to generate the Packages file.

Generating a new ubuntu-keyring .deb to sign your CD

In order to sign the Release file, we need to use GPG. The install system will then check the signature against the public keys held in the package ubuntu-keyring. You do not have a private key that matches one of the ones in the shipped ubuntu-keyring, so we need to build a custom version of the ubuntu-keyring package. Install the gnupg package if you do not have it already.

To create a signing key, enter gpg --gen-key. Accept the defaults, (for this use, it is probably OK to use "No expiry"). For your Real Name and E-mail address, you might like to use something like "XXX Signing Key" and "packages@xxx.example.org". Enter an appropriate passphrase.

In another directory (I use /opt/build/), we will download the source for the ubuntu-keyring package, unpack it, add our own GPG key, and rebuild the package. These steps import the 2 Ubuntu public signing keys into your main keyring, then exports them, along with your own public signing key, into a replacement keyring. "YOURKEYID" should be replaced with the 8-digit hexadecimal code that gpg tells you when you do the --list-keys command. "Signing Key Name" is what you used in the previous step, when running gpg --gen-key.

To clarify, below is an example 'gpg --list-keys' response. In this example, "YOURKEYID" immediately follows the '/' on the line beginning with 'pub' (which in this example is '437D05B5'.)

gpg --list-keys
pub   1024D/437D05B5 2006-09-08
uid                  XXX Signing Key <packages@xxx.example.org>
sub   2048g/79164387 2006-09-08

If you change the package's version number (e.g. using dch), then make sure that the version number you choose does not contain a "-" character: if it does, then you'll be converting the package away from the "native" format and you will have to do some extra steps. It's simpler to use a version number such as "2012.05.19+custom1", putting your preferred local part after the "+" character.

Here is an example, which you will need to customize to suit your own setup:

IconsPage/important.png The following example references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate.

cd /opt/build
sudo apt-get install fakeroot   # requires the fakeroot package which may not be installed on your system.
apt-get source ubuntu-keyring
cd ubuntu-keyring-2012.05.19/keyrings
gpg --import < ubuntu-archive-keyring.gpg
gpg --list-keys "Signing Key Name"
gpg --export FBB75451 437D05B5 C0B21F32 EFE21092 YOURKEYID > ubuntu-archive-keyring.gpg
cd ..    # you are now on ubuntu-keyring-2012.05.19
dpkg-buildpackage -rfakeroot -m"Your Name <your.email@your.host>" -kYOURKEYID
cd ..  # you are now on the directory where you started, in the example, /opt/build
cp ubuntu-keyring*deb /opt/cd-image/pool/main/u/ubuntu-keyring

You will end up with a udeb file for the installer, and a .deb file for the system. Both files need to be copied into the main component of your CD, because the CD will not check the extras directory.

Generate a new filesystem.squashfs with the updated ubuntu-archive-keyring.gpg

To prevent the possible issue during installation, we need to regenerate filesystem.squashfs by updating the ubuntu-archive-keyring.gpg we just exported. There are three paths to being replaced:

  • $chroot/usr/share/keyrings/ubuntu-archive-keyring.gpg
  • $chroot/etc/apt/trusted.gpg
  • $chroot/var/lib/apt/keyrings/ubuntu-archive-keyring.gpg

Furthermore, filesystem.size also needs to be updated:

cd new-squashfs-root
du -sx --block-size=1 ./ | cut -f1 > /opt/cd-image/install/filesystem.size

Building the repository with apt-ftparchive

apt-ftparchive builds the Packages and Packages.gz files, needed by the installer. In order to use apt-ftparchive we will need to provide it with some configuration and some index files.

IconsPage/important.png If you will be adding .deb files to pool/universe (eg. customizing xubuntu) you will also need to wget extra.universe and universe files.

We will put the index files in /opt/indices:

mkdir -p /opt/indices /opt/apt-ftparchive
cd /opt/indices/
DIST=xenial
for SUFFIX in extra.main main main.debian-installer restricted restricted.debian-installer; do
  wget http://archive.ubuntu.com/ubuntu/indices/override.$DIST.$SUFFIX
done

Create the files apt-ftparchive-deb.conf, apt-ftparchive-udeb.conf, apt-ftparchive-extras.conf, and release.conf in a directory (/opt/apt-ftparchive), substituting /opt/cd-image/ for the path to your CD image directory, and /opt/indices/ for the location of the index files, if they differ.

IconsPage/important.png The .conf files shown here are sufficient if you are ONLY making changes to .deb files under pool/main and pool/restricted. If you are adding security updates to a Xubuntu customized CD, though, you will be updating .deb files under pool/universe also, so you will need to add lines to apt-ftparchive-deb.conf for universe, similar to the lines shown for main. You will also need to run extraoverride.pl for universe as well as for main - see below.

/opt/apt-ftparchive/apt-ftparchive-deb.conf:

  • Dir {
      ArchiveDir "/opt/cd-image/";
    };
    
    TreeDefault {
      Directory "pool/";
    };
    
    BinDirectory "pool/main" {
      Packages "dists/xenial/main/binary-amd64/Packages";
      BinOverride "/opt/indices/override.xenial.main";
      ExtraOverride "/opt/indices/override.xenial.extra.main";
    };
    
    BinDirectory "pool/restricted" {
     Packages "dists/xenial/restricted/binary-amd64/Packages";
     BinOverride "/opt/indices/override.xenial.restricted";
    };
    
    Default {
      Packages {
        Extensions ".deb";
        Compress ". gzip";
      };
    };
    
    Contents {
      Compress "gzip";
    };

The ExtraOverride component above is needed to add the Task: line to main packages, referenced from the preseed file with ~t<task name>. This is not supplied - but can be extracted from the existing main Packages file with the simple perl script below.

  • \#!/usr/bin/env perl
    # extraoverride.pl
    # generate ExtraOverride file
    # use as follows :-
    # extraoverride.pl < /opt/cd-image/dists/xenial/main/binary-amd64/Packages >> /opt/indices/override.xenial.extra.main
    
    while (<>) {
            chomp;
            next if /^ /;
            if (/^$/ && defined($task)) {
                    print "$package Task $task\n";
                    undef $package;
                    undef $task;
            }
            ($key, $value) = split /: /, $_, 2;
            if ($key eq 'Package') {
                    $package = $value;
            }
            if ($key eq 'Task') {
                    $task = $value;
            }
    }

IconsPage/note.png If customizing Xubuntu, and adding new .deb files to pool/universe, run this script for the universe repository also.

IconsPage/note.png The ExtraOverride process can be optional to skip it.

/opt/apt-ftparchive/apt-ftparchive-udeb.conf:

  • Dir {
      ArchiveDir "/opt/cd-image/";
    };
    
    TreeDefault {
      Directory "pool/";
    };
    
    BinDirectory "pool/main" {
      Packages "dists/xenial/main/debian-installer/binary-amd64/Packages";
      BinOverride "/opt/indices/override.xenial.main.debian-installer";
    };
    
    BinDirectory "pool/restricted" {
      Packages "dists/xenial/restricted/debian-installer/binary-amd64/Packages";
      BinOverride "/opt/indices/override.xenial.restricted.debian-installer";
    };
    
    Default {
      Packages {
        Extensions ".udeb";
        Compress ". gzip";
      };
    };
    
    Contents {
      Compress "gzip";
    };

/opt/apt-ftparchive/apt-ftparchive-extras.conf:

  • Dir {
      ArchiveDir "/opt/cd-image/";
    };
    
    TreeDefault {
      Directory "pool/";
    };
    
    BinDirectory "pool/extras" {
      Packages "dists/xenial/extras/binary-amd64/Packages";
    };
    
    Default {
      Packages {
        Extensions ".deb";
        Compress ". gzip";
      };
    };
    
    Contents {
      Compress "gzip";
    };

IconsPage/important.png You need to build the Packages file in dists/xenial/extras/binary-amd64/Packages using dpkg-scanpackages. See here for an explanation.

IconsPage/important.png The following example of creating Packages references Ubuntu 16.04 ("xenial"). Substitute your version where appropriate. Use apt-ftparchive to finish above step.

cd /opt/cd-image
apt-ftparchive packages pool/extras > dists/stable/extras/binary-amd64/Packages
gzip -c dists/stable/extras/binary-amd64/Packages | tee dists/stable/extras/binary-amd64/Packages.gz > /dev/null

/opt/apt-ftparchive/release.conf

This is the configuration file for apt-ftparchive. Change to suit your distribution version:

  • APT::FTPArchive::Release::Origin "Ubuntu";
    APT::FTPArchive::Release::Label "Ubuntu";
    APT::FTPArchive::Release::Suite "xenial";
    APT::FTPArchive::Release::Version "16.04";
    APT::FTPArchive::Release::Codename "xenial";
    APT::FTPArchive::Release::Architectures "amd64";
    APT::FTPArchive::Release::Components "main restricted extras";
    APT::FTPArchive::Release::Description "Ubuntu 16.04 LTS";

To build the repository, sign it, and update the MD5SUM file, you can use a script like this:

BUILD=/opt/cd-image
APTCONF=/opt/apt-ftparchive/release.conf
DISTNAME=xenial

pushd $BUILD
apt-ftparchive -c $APTCONF generate /opt/apt-ftparchive/apt-ftparchive-deb.conf
apt-ftparchive -c $APTCONF generate /opt/apt-ftparchive/apt-ftparchive-udeb.conf
apt-ftparchive -c $APTCONF generate /opt/apt-ftparchive/apt-ftparchive-extras.conf
apt-ftparchive -c $APTCONF release $BUILD/dists/$DISTNAME > $BUILD/dists/$DISTNAME/Release

gpg --default-key "YOURKEYID" --output $BUILD/dists/$DISTNAME/Release.gpg -ba $BUILD/dists/$DISTNAME/Release
find . -type f -print0 | xargs -0 md5sum > md5sum.txt
popd

"YOURKEYID" is the key id you put in your own compiled keyring package before.

Preparing the bootable medium

At this point, you have a directory which is ready to be collected into an .ISO file and then burnt to a CD or copied to a USB stick.

Building the ISO image

x86 and AMD64

IMAGE=custom.iso
BUILD=/opt/cd-image/

mkisofs -r -V "Custom Ubuntu Install CD" \
            -cache-inodes \
            -J -l -b isolinux/isolinux.bin \
            -c isolinux/boot.cat -no-emul-boot \
            -boot-load-size 4 -boot-info-table \
            -o $IMAGE $BUILD

x86 and AMD64 with isohybrid

The original i386 and amd64 ISOs have a Master Boot Record (MBR) which makes them bootable from USB stick via legacy BIOS firmware.

# The MBR x86 machine code bytes from the original ISO are known to match
# the isolinux.bin file inside that ISO. So copy them to a file in /tmp/.
OLD_IMAGE=/path/to/iso
MBR_FILE=/tmp/ubuntu_isohybrid_mbr.img
dd if="$OLD_IMAGE" bs=1 count=446 of="$MBR_FILE"

IMAGE=custom.iso
BUILD=/opt/cd-image/

xorriso -as mkisofs -r -V "Custom Ubuntu Install CD" \
            -cache-inodes -J -l \
            -isohybrid-mbr "$MBR_FILE" \
            -partition_offset 16 \
            -c isolinux/boot.cat \
            -b isolinux/isolinux.bin \
               -no-emul-boot -boot-load-size 4 -boot-info-table \
            -o "$IMAGE" \
            "$BUILD"
            "$BUILD"

rm "$MBR_FILE"

AMD64 with isohybrid and UEFI

Additionally to the MBR for legacy BIOS, the amd64 ISOs since 14.04 can boot from CD and from USB stick via the modern UEFI firmware. Its entry point is marked for USB stick by the MBR partition entry 2, which points to the data content of file /boot/grub/efi.img. Together with UEFI bootability from CD this is achieved by the additional options from -eltorito-alt-boot to -isohybrid-gpt-basdat.

OLD_IMAGE=/path/to/iso
MBR_FILE=/tmp/ubuntu_isohybrid_mbr.img
dd if="$OLD_IMAGE" bs=1 count=446 of="$MBR_FILE"

IMAGE=custom.iso
BUILD=/opt/cd-image/

xorriso -as mkisofs -r -V "Custom Ubuntu Install CD" \
            -cache-inodes -J -l \
            -isohybrid-mbr "$MBR_FILE" \
            -c isolinux/boot.cat \
            -b isolinux/isolinux.bin \
               -no-emul-boot -boot-load-size 4 -boot-info-table \
            -eltorito-alt-boot \
            -e boot/grub/efi.img \
               -no-emul-boot -isohybrid-gpt-basdat \
            -o "$IMAGE" \
            "$BUILD"

rm "$MBR_FILE"

Power PC

Download the HFS map, then use the following command:

IMAGE=custom.iso
BUILD=/opt/cd-image/

mkisofs -r -V "Custom Ubuntu Install CD" \
            --netatalk -hfs -probe -map hfs.map \
            -chrp-boot -iso-level 2 -part -no-desktop \
            -hfs-bless $BUILD/install \
            -hfs-volid Ubuntu/PowerPC_hardy \
            -o $IMAGE $BUILD

ia64

IMAGE=custom.iso
BUILD=/opt/cd-image/

mkisofs -r -V 'Custom Ubuntu Install CD' \
        -o $IMAGE -no-emul-boot \
        -J -b boot/boot.img -c boot/boot.catalog $BUILD
  • $IMAGE is just the location of your iso image.

Burning the image to CD, DVD, or Blu-ray

sudo xorriso -as cdrecord dev=/dev/sr0 blank=as_needed -v $IMAGE

The first optical drive of a contemporary GNU/Linux system has address /dev/sr0. If in doubt, run the following command to learn about the existing drives and their /dev file adresses.

sudo xorriso -devices

If your drive or media are old, then you might burn a lot of coasters in experimenting with this process. Re-usable media can ease the pain: CD-RW, DVD-RW, DVD+RW, DVD-RAM, BD-RE.

Putting an isohybrid image onto USB stick

If the x86 and AMD image was made by xorriso with isohybrid options, or if the x86 and AMD image was postprocessed by SYSLINUX program isohybrid, then it will boot from USB stick or hard disk, too.

Such an image is not to be unpacked and installed to the USB stick by a program like 'Rufus' or 'UNetbootin', but rather to be written plainly to the base device file of the USB stick. This implies that the partition table of the stick will be overwritten and thus all data on the stick will become unaccessible, if not overwritten.

Verify device address or make a backup

The main problem on a GNU/Linux system is that you need superuser power to overwrite the whole USB stick, and that this power suffices to also spoil the content of your hard disk.

So first verify that the device file address really leads to the intended device (e.g. by reading a few megabytes and watching it blink). If the USB stick is supposed to be Linux device "/dev/sdh":

sudo umount /dev/sdh*
dd if=/dev/sdh of=/dev/null bs=1024 count=100000

or by making a backup of its complete content in a compressed disk file:

sudo umount /dev/sdh*
dd if=/dev/sdh | gzip >"$HOME"/red_usb_stick.gz

(Your /dev/sd address will probably end by a lower letter than "h". But this paragraph is all about not to spoil /dev/sda and other hard disks by mistake.)

Write to USB stick

Once you are convinced that this is the right device file address, copy the ISO image onto the USB stick by:

sudo dd if="$IMAGE" bs=1M of=/dev/sdh ; sync

Eventually restore backup

To later restore the original content of the USB stick, take the same care to really use the correct address and then:

dd if="$HOME"/red_usb_stick.gz | sudo gunzip >/dev/sdh

Of course, the Ubuntu ISO image will be overwritten by this restore run.

Testing

You can now boot off your CD or USB stick. Select the new menu item you created. If you've used preseeding to stop the CD asking questions, the installation could be totally automatic.

Troubleshooting

  • If your CD fails to read, try re-burning it, possibly at a slower speed.
  • If you get a red d-i screen, check the error message (use Alt-F2, Alt-F3 etc to cycle through the terminals to read the log), and fix your CD appropriately. The log file is /var/log/syslog , check the last lines.

See also

InstallCDCustomization (last edited 2020-01-28 16:26:26 by akrosikam)