Building an Archlinux image for Openstack

Prepare environment

# pacman -S libvirt virt-install qemu ebtables dnsmasq firewalld bridge-utils

Start firewall services. Note that "start" only will start the service at this time, but not at boot time, for that use "enable"

# systemctl start firewalld

And then start libvirt so you can start the real work:

# systemctl start libvirtd

Create default network

If your configuration comes out empty when you run:

# virsh net-list

You can create an archive with the following content:

  <forward mode='nat'>
      <port start='1024' end='65535'/>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:57:70:13'/>
  <ip address='' netmask=''>
      <range start='' end=''/>

Make sure to change the network address and range to available addresses that u can use on your network.

Then use:

# virsh net-create filename-created-above.xml

If you already have a similar configuration that doesn't match your own network, then use:

# virsh net-edit

And do the alterations you need to match your usable network.

Following by:

# virsh net-autostart default
# virsh net-start default

You should end up with:

 Name                 State      Autostart     Persistent
 default              active     yes           yes

You can now have a look on the status of the bridge with brctl:

# brctl show
bridge name     bridge id               STP enabled     interfaces
virbr0          8000.525400577013       yes             virbr0-nic

Here there are two things to notice. First is that the interface where the virbr0 was connect by default foes not exist, then I will manually connect that with my real interface, and second, I will do everything in a way that is just temporary to install the machine image, after booting all this configuration will be gone.

WARNING:: This steps may break your connection with the server if you are working remote, this is designed to work locally and in a uninportant computer that you can temporarily do strange configurations and reboot later, this is all a big hack!!

Remove current enslaved interface:

# ip link delete virbr0-nic master virbr0

Thereafter include your real interface:

# ip link set enp0s31f6 master virbr0

It should look like:

bridge name     bridge id               STP enabled     interfaces
virbr0          8000.d481d75ea7b7       yes             enp0s31f6

After this, the last step is to enable the firewall to allow your own network, the easiest and dirtiest way is:

# iptables -I INPUT --src -j ACCEPT

Create an empty image

$ qemu-img create -f qcow2 archlinux.qcow2 10G

Create a virtual domain

# virt-install --name arch --ram 1024 \
  --disk archlinux-spectronet-final.qcow2,format=qcow2 \ 
  --network network=default --graphics vnc,listen= \
  --noautoconsole --os-type=linux \

So let's break this command down so we can understand the options (although you don't really need to be a genius):

  • --name arch will give the name of the "domain" that will be created;
  • --ram 1024 will start a machine with 1GB RAM;
  • --disk archlinux-spectronet-final.qcow2,format=qcow2 reference to the file that we just created above;
  • --network network=default he will hook up the interface of the machine to the network we just configured above;
  • --graphics vnc,listen= tell virt-install to allow graphics, how it will be accessed and to use the (all addresses) to create the socket on port 5900 (if its the first one);
  • --noautoconsole avoid automatic connection to the console;
  • --os-type=linux tyr to improve virtual domain for type of OS running;
  • --cdrom=/data/install/ISO/archlinux-2018.04.01-x86_64.iso is the bootable image that you should have available to make the installation, like the same would dd to a USB or load on VirtualBox.

When you run this command, if everything goes smoothly, you should have:

WARNING  No operating system detected, VM performance may suffer. Specify an OS with --os-variant for optimal results.

Starting install...
Domain installation still in progress. You can reconnect to 
the console to complete the installation process.

The message about --os-variant appears because I am not using such option, as they ignore that Archlinux exists :-p

You might also notice the following:

# netstat -anp | grep -i 5900
tcp        0      0  *               LISTEN      5708/qemu-system-x8

You server image is ready to have the installation.

Connect with VNC

Use your favorite VNC client and point to:

  • If on the the same machine:
  • If remotely: (the IP address we have configured before, remember?)

There we will get:

First Screen

From here you can follow "more or less" the instructions for a new Archlinux installation, but there will be changes that I will describe as follows.

The Installation

To resume, because I expect you already know where to go from here, I will just list the commands I use on the machine and then I will describe the differences ahead:

# fdisk /dev/sda

Make one partition only, default linux, all disk:

mkfs.ext4 /dev/sda1

Mount it:

# mount /dev/sda1 /mnt

Then install the base and a few other things:

pacstrap /mnt base openssh syslinux mc ansible sudo cronie pkgfile cowsay fortune-mod

Feel free to remove some of the things you don't like, except openssh syslinux sudo because we will need this.

# arch-chroot /mnt

And follow the regular configurations:

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

After editing the /etc/locale.gen:

# locale-gen

Also make the locale.conf -- look at the Archlinux install page details about these...

Set your hostname:

# echo 'archlinux-spectronet' > /etc/hostname

Create the /etc/fstab file:

# cat /etc/fstab
proc            /proc   proc    nodev,noexec,nosuid     0       0
/dev/vda1       /       ext4    errors=remount-ro       0       1

So here you should notice the /dev/vda1 , that's is indeed correct for Openstack. You see everything happening with /dev/sda1 but in preparation for when this machine is booting on the openstack environment we will referr the root disk as /dev/vda1.

Enable some basic services:

# systemctl enable dhcpcd
# systemctl enable cronie
# systemctl enable sshd

Create one user that will be able to make some changes on the system now and might be the same user that you will use to access the machine later:

# useradd -m hacker

Add the new user to sudoers:

# echo "hacker ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

Add Yaourt to the end of your pacman.conf, because we will need to build cloud-init:

Server =$arch
SigLevel = Never

Next update the database adn install a few more things:

# pacman -Sy --noconfirm yaourt base-devel python-pip python2-requests python2-urllib3 python2-chardet git

Update PIP:

# pip install --upgrade pip

Install some pendency to build cloud-init (not sure if this still necessary but in any case...)

# pip install requestbuilder

sudo to user hacker, so we can install cloud-init

# su - hacker
$ yaourt -S cloud-init --noconfirm

Next, lets build another package with the use hacker:

$ git clone

Go inside the mkinitcpio-growrootfs and edit the file growfs-hook and right ontop, add a variable, it should look like this:

run_hook() {

  echo "GrowRootFS: Starting with ${root}"

The finally make the package and install it:

$ makepkg --skipchecksums
$ sudo pacman -U mkinitcpio-growrootfs-0.1.-5-any.pkg.tar.xz

Then lets get back as root and finish some other configurations:

Enable clout-init right away:

systemctl enable cloud-init

Now we need to tell to the initcpio or the "booting procedure" from Archlinux, to run a script to grow the root parition if that size has changed. This will certainly happen on the first boot from the firtual machine, because it will have a "nice flavor" to it and on the flavor the main partition is set to a size. (But hopefully you know how openstack works and I don't need to diverge from our main focus here :)

Edit the file /etc/mkinitcpio.conf and add growfs to the variable HOOKS, it should be after filesystems:

HOOKS=(base udev autodetect modconf block filesystems growfs keyboard fsck)

Then run again to rebuild:

# mkinitcpio -p linux

Next, edit the file /etc/cloud/cloud.cfg and change the following to the end ot the file:

# System and/or distro specific settings
# (not accessible to handlers/transforms)
   # This will affect which distro class gets used
   distro: arch
   # Default user name + that default users groups (if added/used)
     name: hacker
     lock_passwd: True
     gecos: Builder User
     groups: [adm, audio, floppy, video, wheel]
     sudo: ["ALL=(ALL) NOPASSWD:ALL"]
     shell: /bin/bash
   # Other config here will be given to the distro class and/or path classes
      cloud_dir: /var/lib/cloud/
      templates_dir: /etc/cloud/templates/
   ssh_svcname: sshd

And you must add the following contents:

 init: "> /var/log/cloud-init.log"

datasource_list: [ OpenStack, Ec2, None  ]

    metadata_urls: [ '' ]
    dsmode: net

WARNING: the indentation on this file is important, remember to use two spaces for create proper scope

This file will tell your virtual machine's cloud-init system where is the API location from your Openstack Nova Services, where he is going to download the SSH key, figure out some other details necessary to run properly.

So the IP address added at the end of the file, must be an accessible Openstack Nova API address, which is accessible to your virtual machines.

Now make your finishing touches, changing your /etc/issue file with relevant and exciting information about the virtual machine.

Edit and make the /etc/bash.bashrc with your fancy configurations.

Change the root password to something that you can distribute the machine with.

If you want, change the password of the user hacker as well.

And lastly here, remove the /etc/machine-id file, so you can reuse this image infinitely.

Make it boot

Well this step is actually simple, using this method. Just use syslinux as you normally would, but referr to root partition as /dev/vda1.

On the /boot/syslinux/syslinux.cfg set the APPEND lines to:

APPEND root=/dev/vda1 rw

Do whatever other alterations you want, i.e.: enable graphs, change background, blablabla..

Install it:

syslinux-install_update -iam

You can now stop the domain to make the file free for manipulation:

virsh destroy arch

Where arch is the option --name we have given on the start of the process.

Load on Openstack

You have two options:

  • Load via nova interface, loading a new image on the system;
  • Load via command line:

[root@openstack # . keystonerc_admin
[root@openstack images(keystone_admin)]# glance image-create --name 'arch-spectronet' --disk-format qcow2 --container-format bare --file /images/archlinux.qcow2

Then lauch your new instance!