Autoinstalling ubuntu-server 20.04.3 from the live-iso

Hi,

As promised, here the actions I have made in orde to autoinstall ubuntu-server 20.04.3 from the live-iso.

I used following references:

https://louwrentius.com/understanding-the-ubuntu-2004-lts-server-autoinstaller.html
https://itectec.com/ubuntu/ubuntu-automated-20-04-server-installation-using-pxe-and-live-server-image/

How I applied it in our environment:

  • make iso available in Foreman
    mkdir -p /var/www/html/pub/installation_media/ISO
    cd /var/www/html/pub/installation_media/ISO
    wget https://releases.ubuntu.com/20.04.3/ubuntu-20.04.3-live-server-amd64.iso
  • mount the iso to /mnt in order to copy necessary files needed for correct PXE-booting:
mount ubuntu-20.04.3-live-server-amd64.iso /mnt/
mkdir -p /var/lib/tftpboot/ubuntu/focal
cd /var/lib/tftpboot/ubuntu/focal
cp cp /mnt/casper/vmlinuz .
cp /mnt/casper/initrd .
chmod 644 *
umount /mnt
  • created a new partition table template using the cloud-init format.
  • created the following new templates:
    • preseed pxelinux using the correct config for cloud-init autoinstall.
    • provisioning template using the new cloud-init format.
    • snippet preseed_netplan_setup in order to configure the network config configured for the host (bonds, bridges, vlans, and normal interfaces, which is used in the new provisioning template
    • snippet preseed_netplan_generic_interface that configures the ipv4 and ipv6 for each interface if configured, wich is used by the snippet preseed_netplan_setup.
  • create a new location where the necessary cloud-init files meta-data and user-data should be provided.
    The user-data is the combination of new provisioning template and the new partition table.
    See below manual actions I have done.
  • create new installtion media “Ubuntu 20 ISO” in Foreman with path “http://< foreman server >/pub/installation_media/ISO/ubuntu-20.04.3-live-server-amd64.iso” and Family “Debian”.
    And of course linked to the necessary location(s) and organization(s).
  • Creating Operating System “Ubuntu 20.04” pointing to the new installation media and linking the new partioning table and template(s).

When applying build server in Foreman the new PXElinux template generates a new file in /var/lib/tftpboot/pxelinux.cfg with following content:

DEFAULT linux autoinstall
LABEL linux autoinstall
    KERNEL ubuntu/focal/vmlinuz
    INITRD ubuntu/focal/initrd
    APPEND ip=dhcp url=http://< foreman server >/pub/installation_media/ISO/ubuntu-20.04.3-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://< foreman server >/pub/preseed/autoinstall/< hostname.short >/ root=/dev/ram0 ramdisk_size=1500000 fsck.mode=skip

Bacause Foreman, correct me if I’m wrong, can not generate the new files meta-data and user-data in /pub/preseed/autoinstall/< hostname.short > I created them manually:

  • mkdir /var/www/html/pub/preseed/autoinstall/< hostname.short >/
  • cd /var/www/html/pub/preseed/autoinstall/< hostname.short >/
  • create meta-data file which may contain always the same like:
cat > meta-data <<EOF
instance-id: focal-autoinstall
EOF
  • create the user-data file which contains the cloud-init autoinstall configuration.
    As described above it will contain the content of the new provisioning template with content of the snippet netplan_setup and the config of partitioning table.
    In order to have the content I did a preview of the new provisioning template linked to the host.
  • these 2 files should have permission 644.

With this setup I was able to provision my test-host Ubuntu 20.04.3

I know this doesn’t cover al possible methods of net-booting, but might be a good start.

Anyway, I hope that this can be a base for someone in order to make the necessary changes in the Foreman/Katello.

Please let me know where I can make the new templates available, and of course let me know if additional info is required.

As said in my previous post, this is not yep 100% complete, I still need to find out how to configure the following in the cloud-init file:

  • install/config puppet on the host
  • applying the subscription in foreman which configures the apt repo pointing to the repo’s configured the activation key

If someone is able to apply this before me, I would appreciate it to share this as well.

4 Likes

Here the templates and partition table I have created:

Provisionig template:

Snippets used by the provisionig template:

PXElinux template:

Partition table (LVM example):

1 Like

Thank you for the OP and templates. If you don’t mind, I will collect all of them, make some edits and put them into a single patch. There are some edits required and I will prepare Ubuntu mock for snapshot tests so we can start testing them via CI as more of editing is expected from other users.

But this is a fantastic start, thank you so much!

2 Likes

Hi,

FYI …

Im still trying to find out how to automate the remaining actions like the installation and configuration of the puppet-agent, subscribing the host in foreman, and so on.

As the autoinstall makes use of a snap, configuration of files like for puppet, creation of extra users, … can not be done in the provided provisioning file as all those actions would be exectuted within the snap and would not be available on the installed system.

Therefor, the identity-config in the cloud-config needs te be removed and th econfig of it as well all additional things to be done should be configured in the file using a separate block “user-data”.

Example:

#cloud-config
autoinstall:
  version: 1
...
  user-data:
    hostname: < host-name >
    write_files:
      - path: /etc/puppetlabs/puppet/puppet.conf
        content: |
          [main]
          [agent]
          pluginsync      = true
          report          = true
          ca_server       = < foreman-server fqdn >
          certname        = < hostname fqdn >
          server          = < foreman-server fqdn >
          environment     = production
        owner: 'root:root'
        permissions: '0644'
        defer: true
    users:
      - default
      - name: < user defined during manual install >
        gecos: < Description user >
        lock_passwd: false
        passwd: < hashed_password >
        groups:
          - adm
          - sudo
...
  storage:
    config:
...

As soon I have a working solution I will provide all details as well modified template-files.

1 Like

Thanks again for your templates, I have slightly updated them, fixed few problems, added partitioning layout and added snapshot tests.

See here: Fixes #32632 - initial verison of Ubuntu autoinstall templates by lzap · Pull Request #9076 · theforeman/foreman · GitHub

I would suggest to do what we do for the old installer. We have a “Preseed Finish” template that performs all these tasks and it is downloaded by curl at the end of the installation:

Can’t you do the same? This way all these post-install steps are actually shared between the two installer which is a big win for the transition period.

@lzap, I’d like to help test-driving the PR

Wasn’t there a trick with theforeman to track PRs?

I’m trying to make it work with jammy jellyfish, since we really need it for our new laptops. And I see focal is now hardcoded in the templates. Would it be possible to make that variable?

Thanks!

2 Likes

@lzap ,
Yeah, I was starting with the user-data-block, but this results in some issues, so I’m now making a finisch script that will do the necessary actions.

Meanwhile, all actions aI have done manually are working fine:

  • install/configure puppet-agent, with installing katallo-ca-cert
  • installing the necessary packages from https://apt.atix.de in order to subscribe the host in foreman.

Now it is just a matter of putting this all together in the finish script which will be run at first boot.
I’ll keep you informed as soon I have tthe final solution.

1 Like

Not sure what you mean, you can import templates from particular branch via a rake task. Search for rake -T “template” word.

Thanks, just extract the PXE files into your TFTP smart proxy and make sure it matches the PXELinux template paths and you are good to go. Please drop comments in the PR or maybe we can simply merge it and you guys can carry on and add more stuff.

@lzap ,

Update:

I have created a finish script based on a clone of ‘preseed default finish’ that will be executed at first boot after the host has been installed with ubuntu 20.04.
Therefor the cloud-init autoinstall file “user-data” will need some additional configurations to make it possible to execute it at first boot:

  user-data:
    runcmd:
      - wget -Y off <%= @static ? "'#{foreman_url('finish', static: 'true')}'" : foreman_url('finish') %> -O /tmp/finish.sh
      - chmod +x /tmp/finish.sh
      - /tmp/finish.sh

I just need to make one more small change in it in order to apply a custom snippet for those who want to apply some additional actions which are not part of the default finish-actions, like for example creating specific additional users, installing additional packages, …

The template will execute following actions at first-boot:

  • configure /etc/hosts with the ip, fqdn and short hostname (necessary for actions that will follow)
  • execute the actions in the custom snippet if it exist
  • add ssh-key for foreman-proxy to roots authorized_keys file
  • install alien in order to install the katello-ca-consumer.rpm (probably not necessary for those who have installed foreman on a system with Ubuntu/Debian, so might need some modifications)
  • install/configure and execute the puppet-agent in order to sign the host in foreman
  • install the ‘subscription manager’ from Atix
  • subscribe the host in foreman with the subscription manager
  • move the initial sources.list file to foreman_backup_sources.list as it will not be necassary anymore (can be removed if desired)
  • send the end of installation to foreman
  • and finaly, when the host has the new boolean parameter ‘upgrade_OS’ = ‘true’, it will upgrade the OS and perform a reboot afterwards.

As of tomorrow I’m going to review and adapt the templates were needed and as soon they are ready I will make them available in github.

Of course, they probably might need some changes, but they will be a good start for the community to implement them in the product.

Note:
Despite the subscription works, there is still one thing not going well.
The host reports for ‘Errata’: “No installed packages and/or enabled repositories have been reported by subscription-manager.” which results the host gets the status “Warning”

I hope that someone from Atix would be so kind to provide us the solution for this.

Question:
Have you or someone else already worked out a solution in order to create the cloud-init autoinstall “user-data” file in /var/www/html/pub/preseed/autoinstall/< hostname-short >?
If so, is it possible for me to apply the changes in our foreman 3.0.1 / katello 4.2.1 environment, and how?

@lzap Thanks for your reply, I left a review but no action has been taken so far.

@lzap ,

Here the modified and new templates:

Please let me know if you need more info.

2 Likes

@atix will probably know more but I think the RPM package only contains a certificate that should already be available as a plain file on /pub or at least it used to be. Maybe we should consider publishing it again if its no longer the case so alien is not necessary.

Yeah Debian Errata is @atix’s domain.

Remind me why you cannot use the build-in Foreman’s userdata endpoint?

And why you did not use the default finish preseed template? What was wrong with it?

Edit: Initially I did not see the wget command now I see it.

Ok I have incorporated your latest changes into my big PR:

I do not like introducing a new Default Finish template tho, there is already a one, can you simply extend it with parameters or snippet_if_exists so you would be able to extend it as you wish?

@ezr-ondrej let’s merge the PR so @langesmalle can file smaller improvements based on that, I really don’t have much time for this at the moment.

As described in the initial post, the PXElinux template generates a file in /var/lib/tftpboot/pxelinux.cfg/ with following content:

DEFAULT linux autoinstall
LABEL linux autoinstall
    KERNEL ubuntu/focal/vmlinuz
    INITRD ubuntu/focal/initrd
    APPEND ip=dhcp url=http://< foreman server >/pub/installation_media/ISO/ubuntu-20.04.3-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://< foreman server >/pub/preseed/autoinstall/< hostname.short >/ root=/dev/ram0 ramdisk_size=1500000 fsck.mode=skip

For each host you provision the part autoinstall ds=nocloud-net;s=http://< foreman server >/pub/preseed/autoinstall/< hostname.short >/ needs to have 2 files, meta-data and the user-data, where the last one contains the cloud-config how the host should be build.
Based on the docu I referred to.

As multiple host provisions might be launched simultaneously I have decided to create them in a separate path for each host. I have not tested it by using other paths/locations for these files.

As I’m not a developer I was trying to find out a solution to make it possible to provision a host with the new method Ubuntu implemented.
So I was hoping that which what I created as a solution, Foreman developers would be able to implement it in a correct way in the product.

But if necessary I will have a look at the build-in userdata endpoint if it is possible to migrate my solution in it.

I started from a clean template in order to create a finish script that would work as expected.
It might be possible to merge it in the existing one, but at the moment I do not have the time as well to have a look at it.
If no one else has looked at it in the meantime I will pick it up as soon as I have time for.

Yeah sorry I missed it above, the thing is we actually do have both endpoints in Foreman now:

config/routes.rb
469:  get 'userdata/meta-data', controller: 'userdata', action: 'metadata', format: 'text'
470:  get 'userdata/user-data', controller: 'userdata', action: 'userdata', format: 'text'

Userdata can be fully customized, however, metadata is hardcoded in the codebase:

  def metadata
    data = {
      :'instance-id' => "i-#{Digest::SHA1.hexdigest(@host.id.to_s)[0..17]}",
      :hostname => @host.name,
      :mac => @host.mac,
      :'local-ipv4' => @host.ip,
      :'local-hostname' => @host.name,
    }
    render plain: data.map { |key, value| "#{key}: #{value}" }.join("\n")
  end

Is there anything we can change in this design what would enable you to do what you want to do?

Understood, the problem is that we do not want to ship several fine-tuned templates because every single environment is different. What we are doing is shipping a single but extendable template for each individual type which serves as a good starting point for others. Not a problem, we can just use our standard finish template for now, unless there is something really missing.

Apologies I was on a short vacation, I will check PRs soon, I hope we can change the big one (my PR) into develop so you guys can start improving it.

Hey! I’m currently working on integrating the new autoinstall method into Foreman. Thanks for providing the great tutorial @langesmalle!
I’m already deploying 20.04.3 hosts with custom userdata templates as suggested by @lzap. Now, I want to automate the whole integration & I see the following steps:

  • Fix installation media such that it provides the correct kernel files (see here)
  • In order to configure the network with cloud-init, a network identifier must be set. Previous templates didn’t need an explicit identifier and it would be generated during installation. So, the name wasn’t set in the provisioning template, but now it seems like it must be generated here
  • AFAIK cloud-init and the corresponding userdata/user-data API endpoint is usually used for image-based deplyoment. When using image-based deployment instead of the regular host creation, we must use a different template. Therefore, we must differentiate between these two use cases.

What do you think about it @lzap? Idk whether my approach for the PR is feasible or whether it would be better to create the operating system type Ubuntu, since the different kernel file names to Debian may be seen as a major difference which justifies a new operating system class.

2 Likes

Hey, thanks for the patch.

How this is supposed to work? Foreman currently cannot download PXE from Ubuntu mirrors, because they simply aren’t there. Have you seen: RFC: Rearchitecting how PXE files are deployed ?

Can you describe the full end to end workflow?

You’re right, it still needs some location with the extracted iso files. With the patch, the user can define an installation media path where the extracted image files are placed (for example, the pub folder of the Foreman itself). Then, the Foreman is going to look for the re-named/non-zipped files (vmlinuz instead of linux and initrd instead of initrd.gz) if the Ubuntu version is higher than 20.04.2.

Isn’t renaming the solution? I mean, currently it’s broken and this patch does not solve this, I am not sure if this is worth doing.

Do you mean renaming the boot files manually so they’re detected by Foreman again or renaming the expected file names in Foreman as it’s proposed by the patch?
I tested the former by renaming vmlinuz to linux and compressing the init file to initrd.gz, so they look the same like before. This enables Foremen to detect the files again, but the boot process of the VM won’t work since it’s explicitly looking for an uncompressed initrd.
So, I think we should add this exception for newer Ubuntu versions from 20.04.3 in Foreman itself as it’s done in the patch.

What do you think about the second point, I described earlier?

In order to configure the network with cloud-init, a network identifier must be set. Previous templates didn’t need an explicit identifier and it would be generated during installation. So, the name wasn’t set in the provisioning template, but now it seems like it must be generated here

For me, the cloud-init templates crash if I don’t set the network identifier name manually. Can we prevent this by generating a default name that is used if none is given?

1 Like