Skip to content

Prerequisites Setup Tutorial

This tutorial walks you through setting up the necessary prerequisites to launch a VM instance in OpenStack.

Step 1: Install Required Tools

First, check if the tools are already installed:

which openstack && openstack --version
which qemu-img && qemu-img --version

If not installed, install the OpenStack client and QEMU utilities:

sudo apt update && sudo apt install -y python3-openstackclient qemu-utils

Step 2: Download and Upload an Image

First, check if the image is already uploaded:

openstack image list | grep -i ubuntu

If the image doesn't exist, download the Ubuntu 24.04 cloud image:

curl -fLO https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

Convert the image from qcow2 to raw format:

qemu-img convert -p -f qcow2 noble-server-cloudimg-amd64.img -O raw ubuntu-24.04.raw

Upload the image to OpenStack:

openstack image create ubuntu-24.04 \
  --file ubuntu-24.04.raw \
  --disk-format raw \
  --container-format bare \
  --public \
  --property hw_disk_bus=virtio \
  --property hw_cdrom_bus=ide \
  --property hw_rng_model=virtio \
  --property hw_qemu_guest_agent=yes \
  --property os_type=linux \
  --property os_distro=ubuntu \
  --property os_admin_user=ubuntu

Verify the image was uploaded:

openstack image list

Step 3: Verify Existing Resources

Check available flavors:

openstack flavor list

Step 4: Create Network Infrastructure

List existing networks for your project:

openstack network list --project $(openstack token issue -c project_id -f value)
Expected output
+--------------------------------------+-----------+--------------------------------------+
| ID                                   | Name      | Subnets                              |
+--------------------------------------+-----------+--------------------------------------+
| 0ec65d2c-3c38-4cd1-913f-5bea96419e79 | local-net | 1522af84-f26b-41da-bc28-3a69bb18a2d8 |
+--------------------------------------+-----------+--------------------------------------+

If you already have a network, you can skip creating a new one. Otherwise, create a new network:

openstack network create local-net
Expected output
+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   | nova                                 |
| availability_zones        |                                      |
| created_at                | 2025-10-26T18:43:53Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | 9d02ddbd-7a41-4d0a-ba74-dc700cc8dfcb |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | None                                 |
| is_vlan_transparent       | None                                 |
| mtu                       | 1442                                 |
| name                      | local-net                            |
| port_security_enabled     | True                                 |
| project_id                | b906e38839a341c39675e68dfdaf3c67     |
| provider:network_type     | geneve                               |
| provider:physical_network | None                                 |
| provider:segmentation_id  | 561                                  |
| qos_policy_id             | None                                 |
| revision_number           | 1                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      |                                      |
| updated_at                | 2025-10-26T18:43:54Z                 |
+---------------------------+--------------------------------------+

Create a subnet for the network:

openstack subnet create local-subnet \
  --network <network-id> \
  --subnet-range 10.0.0.0/24 \
  --gateway 10.0.0.1 \
  --dns-nameserver 8.8.4.4 \
  --dns-nameserver 8.8.8.8
Expected output
+----------------------+--------------------------------------+
| Field                | Value                                |
+----------------------+--------------------------------------+
| allocation_pools     | 10.0.0.2-10.0.0.254                  |
| cidr                 | 10.0.0.0/24                          |
| created_at           | 2025-10-26T18:52:53Z                 |
| dns_nameservers      | 8.8.4.4, 8.8.8.8                     |
| enable_dhcp          | True                                 |
| gateway_ip           | 10.0.0.1                             |
| name                 | local-subnet                         |
| network_id           | 9d02ddbd-7a41-4d0a-ba74-dc700cc8dfcb |
+----------------------+--------------------------------------+

Step 5: Verify Network to Router Connection

Router Access

The main router is typically created by the admin in their project. Regular users cannot list routers outside their project, but networks can be connected to this router by the admin. Your network should already be connected to the admin's router.

Check if your network is already connected to a router by listing ports on your network:

openstack port list --network local-net

Look for a port with IP matching your gateway (e.g., 10.0.31.1) that has status ACTIVE. To verify it's connected to a router:

openstack port show <port-id>

The device_owner field should show network:router_interface if properly connected.

Expected output
+-------------------------+--------------------------------------------------------------------------+
| Field                   | Value                                                                    |
+-------------------------+--------------------------------------------------------------------------+
| device_owner            | network:router_interface                                                 |
| fixed_ips               | ip_address='10.0.31.1', subnet_id='1522af84-f26b-41da-bc28-3a69bb18a2d8' |
| status                  | ACTIVE                                                                   |
...
+-------------------------+--------------------------------------------------------------------------+

If your network is not connected to a router, contact your OpenStack administrator to attach your subnet to the main router.

Step 6: Configure Security Groups

List existing security groups:

openstack security group list --project $(openstack token issue -c project_id -f value)
Expected output
+--------------------------------------+---------+------------------------+----------------------------------+------+
| ID                                   | Name    | Description            | Project                          | Tags |
+--------------------------------------+---------+------------------------+----------------------------------+------+
| 8588f135-cb9d-446a-b58f-5afcfe13ee67 | default | Default security group | ac3554ce3338436fb6f40c27fc0344af | []   |
+--------------------------------------+---------+------------------------+----------------------------------+------+

Check existing security group rules:

openstack security group rule list <security-group-id>

Look for existing ICMP and TCP port 22 rules. If they don't exist, add them:

Add ICMP rule (for ping):

openstack security group rule create --proto icmp <security-group-id>
Expected output
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| created_at              | 2025-10-26T19:04:46Z                 |
| description             |                                      |
| direction               | ingress                              |
| ether_type              | IPv4                                 |
| id                      | 26834604-b9c1-465a-8ed1-39e17be07080 |
| name                    | None                                 |
| port_range_max          | None                                 |
| port_range_min          | None                                 |
| project_id              | b906e38839a341c39675e68dfdaf3c67     |
| protocol                | icmp                                 |
| remote_address_group_id | None                                 |
| remote_group_id         | None                                 |
| remote_ip_prefix        | 0.0.0.0/0                            |
| revision_number         | 0                                    |
| security_group_id       | a9d2e9ee-c625-45ab-9300-ccaa0a47712f |
| tags                    | []                                   |
| tenant_id               | b906e38839a341c39675e68dfdaf3c67     |
| updated_at              | 2025-10-26T19:04:46Z                 |
+-------------------------+--------------------------------------+

Add SSH rule:

openstack security group rule create --proto tcp --dst-port 22 <security-group-id>
Expected output
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| created_at              | 2025-10-26T19:04:55Z                 |
| description             |                                      |
| direction               | ingress                              |
| ether_type              | IPv4                                 |
| id                      | 34a1a928-6a90-4754-b772-f33d1cbe2b5b |
| name                    | None                                 |
| port_range_max          | 22                                   |
| port_range_min          | 22                                   |
| project_id              | b906e38839a341c39675e68dfdaf3c67     |
| protocol                | tcp                                  |
| remote_address_group_id | None                                 |
| remote_group_id         | None                                 |
| remote_ip_prefix        | 0.0.0.0/0                            |
| revision_number         | 0                                    |
| security_group_id       | a9d2e9ee-c625-45ab-9300-ccaa0a47712f |
| tags                    | []                                   |
| tenant_id               | b906e38839a341c39675e68dfdaf3c67     |
| updated_at              | 2025-10-26T19:04:55Z                 |
+-------------------------+--------------------------------------+

Step 7: Verify SSH Keys

List your SSH keypairs:

openstack keypair list
Expected output
+-----------+-------------------------------------------------+------+
| Name      | Fingerprint                                     | Type |
+-----------+-------------------------------------------------+------+
| bootstrap | 7f:2c:6f:62:5a:44:1b:08:4d:55:c2:2c:31:9c:cd:1f | ssh  |
+-----------+-------------------------------------------------+------+
Accessing Private Key (generated in the onboarding process)

SSH keypairs like bootstrap are automatically generated and managed by the system. The private key (e.g., bootstrap.pem) is stored in S3 storage and can be downloaded from there or retrieved using the Voyager API (coming soon).

If you don't have a keypair, you can create one or import an existing public key. Ensure you have at least one keypair to use for SSH access to instances.

Step 8: Launch a Test Instance

First, gather the required IDs:

Get network ID:

openstack network list --project $(openstack token issue -c project_id -f value)
Expected output
+--------------------------------------+-----------+--------------------------------------+
| ID                                   | Name      | Subnets                              |
+--------------------------------------+-----------+--------------------------------------+
| 0ec65d2c-3c38-4cd1-913f-5bea96419e79 | local-net | 1522af84-f26b-41da-bc28-3a69bb18a2d8 |
+--------------------------------------+-----------+--------------------------------------+

Get security group ID:

openstack security group list --project $(openstack token issue -c project_id -f value)
Expected output
+--------------------------------------+---------+------------------------+----------------------------------+------+
| ID                                   | Name    | Description            | Project                          | Tags |
+--------------------------------------+---------+------------------------+----------------------------------+------+
| 8588f135-cb9d-446a-b58f-5afcfe13ee67 | default | Default security group | ac3554ce3338436fb6f40c27fc0344af | []   |
+--------------------------------------+---------+------------------------+----------------------------------+------+

Get keypair name:

openstack keypair list
Expected output
+-----------+-------------------------------------------------+------+
| Name      | Fingerprint                                     | Type |
+-----------+-------------------------------------------------+------+
| bootstrap | 7f:2c:6f:62:5a:44:1b:08:4d:55:c2:2c:31:9c:cd:1f | ssh  |
+-----------+-------------------------------------------------+------+

Create a test VM with all configured resources.

Choosing the Right Flavor

Flavors come in two types:

  • Flavors with disk (names ending in "e" like c1e.small, m1e.small, s1e.small): Can boot directly from an image
  • Flavors without disk (like c1.small, m1.small, s1.small): Require volume-backed instances using --boot-from-volume

Option 1: Using a flavor with disk (e.g., c1e.small):

openstack server create test-ubuntu-24 \
  --image ubuntu-24.04 \
  --flavor c1e.small \
  --network <network-id> \
  --key-name <keypair-name> \
  --security-group <security-group-id>

Option 2: Using a volume-backed instance (for flavors with 0 disk):

openstack server create test-ubuntu-24-volume \
  --flavor c1.small \
  --network <network-id> \
  --key-name <keypair-name> \
  --security-group <security-group-id> \
  --boot-from-volume 20 \
  --image ubuntu-24.04

The --boot-from-volume 20 parameter automatically creates a 20GB root volume from the image.

Example with actual values (volume-backed):

openstack server create test-ubuntu-24-volume \
  --flavor c1.small \
  --network 0ec65d2c-3c38-4cd1-913f-5bea96419e79 \
  --key-name bootstrap \
  --security-group 8588f135-cb9d-446a-b58f-5afcfe13ee67 \
  --boot-from-volume 20 \
  --image ubuntu-24.04

Step 9: Allocate and Attach Floating IP

Check your running instances:

openstack server list
Expected output
+--------------------------------------+------------------------+--------+---------------------------+---------------------+-----------+
| ID                                   | Name                   | Status | Networks                  | Image               | Flavor    |
+--------------------------------------+------------------------+--------+---------------------------+---------------------+-----------+
| 24e5f31d-f518-4572-a2ee-7b9542edfb2a | test-ubuntu-24-volume  | ACTIVE | local-net=10.0.31.211     | N/A (booted from    | c1.small  |
|                                      |                        |        |                           | volume)             |           |
| c259948e-1a9a-4cd0-bc51-adee98291dfc | test-ubuntu-24         | ACTIVE | local-net=10.0.31.132     | ubuntu-24.04        | c1e.small |
+--------------------------------------+------------------------+--------+---------------------------+---------------------+-----------+

List available external networks:

openstack network list --external
Expected output
+--------------------------------------+--------+--------------------------------------+
| ID                                   | Name   | Subnets                              |
+--------------------------------------+--------+--------------------------------------+
| 48c4a529-f244-491e-a798-e9adcd64e2bb | office | 5fdce4df-7993-46bc-b3e4-69bc739afb20 |
+--------------------------------------+--------+--------------------------------------+

Allocate a floating IP from the external network:

openstack floating ip create office
Expected output
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| created_at          | 2025-10-29T12:13:38Z                 |
| floating_ip_address | 192.168.4.251                        |
| floating_network_id | 48c4a529-f244-491e-a798-e9adcd64e2bb |
| id                  | f0350cc8-db41-402a-9cbf-078e9ca3ee26 |
| status              | DOWN                                 |
+---------------------+--------------------------------------+

Associate the floating IP with your instance:

openstack server add floating ip <server-name> <floating-ip>
Example:
openstack server add floating ip test-ubuntu-24-volume 192.168.4.251

Verify the floating IP is attached:

openstack server show test-ubuntu-24-volume

Look for the addresses field which should show both the private IP and floating IP:

addresses | local-net=10.0.31.211, 192.168.4.251

Step 10: SSH into the Instance

Connect to your instance using SSH. You'll need to specify the private key that corresponds to the keypair you used when creating the instance.

If your SSH key is not in the default location (~/.ssh/id_rsa), you need to specify it with the -i flag:

ssh -i <path-to-private-key> ubuntu@<floating-ip>
Accessing Private Key (generated in the onboarding process)

SSH keypairs like bootstrap are automatically generated and managed by the system. The private key (e.g., bootstrap.pem) is stored in S3 storage and can be downloaded from there or retrieved using the Voyager API (coming soon).

Example:
ssh -i ~/.ssh/bootstrap.pem ubuntu@192.168.4.251

SSH Key Permissions

Ensure your private key has the correct permissions (600):

chmod 600 ~/.ssh/bootstrap.pem

The default user for Ubuntu cloud images is ubuntu. Your SSH key (configured in Step 7) will be used for authentication.


Command Reference

openstack image create - Common options

openstack image create - Creates a new image in the OpenStack Image service (Glance).

--disk-format <format> - Specifies the disk image format. Common formats include:

  • raw: A raw disk image (often preferred for Ceph).
  • qcow2: A QEMU copy-on-write format (supports features like snapshots).
  • vhd: A Microsoft Virtual Hard Disk format.
  • vmdk: A VMware Virtual Machine Disk format.

--container-format <format> - Specifies the container format (if any) used to encapsulate the image. Common formats include:

  • bare: No container format (the image is just the raw disk image).
  • ovf: Open Virtualization Format (an open standard for packaging virtual appliances).
  • aki: Amazon Kernel Image (used for Amazon Machine Images).
  • ari: Amazon Ramdisk Image (used for Amazon Machine Images).

--public - Makes the image accessible to all projects (tenants) within your OpenStack cloud. If you omit this, the image will be private to your current project.
--private - Makes the image private to your current project.

--property <key=value> - Allows you to set custom properties (metadata) on the image. These properties can be used to provide additional information about the image or to influence how instances are launched from it. Common properties include:

  • hw_disk_bus: Specifies the disk bus type (e.g., virtio, ide, scsi).
  • hw_cdrom_bus: Specifies the CD-ROM bus type (e.g., ide).
  • hw_rng_model: Random number generator model (e.g., virtio).
  • hw_qemu_guest_agent: Enable QEMU guest agent support.
  • os_type: Operating system type (e.g., linux, windows).
  • os_distro: Linux distribution name (e.g., ubuntu, centos).
  • os_admin_user: Default admin username for the OS.

--file <file_path> - Specifies the path to the image file you want to upload.

openstack flavor create - Common options
  • --id <ID>: (Optional) A unique ID for the flavor. If you use --id auto, OpenStack will generate a UUID.
  • --ram <MB>: The amount of RAM in MB.
  • --disk <GB>: The size of the root disk in GB.
  • --ephemeral <GB>: (Optional) The size of a temporary (ephemeral) disk in GB.
  • --vcpus <number>: The number of virtual CPUs.
  • --swap <MB>: (Optional) The amount of swap space in MB.
  • --rxtx-factor <factor>: (Optional) A factor for network bandwidth allocation.
  • --public: (Optional) Makes the flavor accessible to all projects.
  • --private: (Optional) Makes the flavor accessible only to your project.
  • --property <key=value>: (Optional) Sets custom properties (metadata) on the flavor.
  • <flavor_name>: The name you assign to the flavor.