Skip to content

Incus Challenges

These are here for anybody new who wants to try and learn more about terraform / incus by doing.

These challenges were created in part using AI. If something does not make sense reach out to me @Hugh Sweazy on discord.

Challenge 1: Launch a Single Instance

Difficulty: Easy
Goal: Get comfortable with the basic workflow of defining an Incus instance in Terraform, launching it, and destroying it.

Make sure to create a profile and associate it with all your resouces

Tasks:

  1. Create a Terraform configuration file (main.tf).
  2. Define a resource of type incus_instance to create an Ubuntu container. Use the default ubuntu/22.04 image.
  3. Name the instance my-first-container.
  4. Push the code to gitlab and let the pipeline run.
  5. Check the plan output and see if everything checks out.
  6. Run the apply pipeline job
  7. After a successful apply job run check the Incus UI, make sure to select your profile in the top left.
  8. Once confirmed, run terraform destroy to clean up the resource.

Challenge 2: Networking and Instance Communication

Difficulty: Medium
Goal: Understand how to create custom networks and connect multiple instances to them.

Make sure to create a profile and associate it with all your resouces

Tasks:

  1. Define an incus_network resource to create a new bridge network named private-net.
  2. Define two incus_instance resources, instance-1 and instance-2.
  3. Attach both instances to the private-net you created.
  4. Assign static IPv4 addresses to each instance within the network's subnet (e.g., 10.0.1.10 for instance-1 and 10.0.1.11 for instance-2). You may need to configure the network's IP range.
  5. Use a provisioner "remote-exec" block within the instance-1 resource to run a command that pings instance-2's IP address to verify connectivity.
  6. Apply the configuration and check the output to ensure the ping was successful.
  7. Destroy the resources.

Challenge 3: Configuration with Profiles and Cloud-Init

Difficulty: Medium
Goal: Learn how to apply a common configuration to instances using Incus profiles and customize them at launch with cloud-init.

Make sure to create a profile and associate it with all your resouces

Tasks:

  1. Define an incus_profile resource named web-server-profile.
  2. In this profile, set resource limits, for example, limits.cpu \= "1" and limits.memory \= "512MB".
  3. Define a single incus_instance named web-server.
  4. Assign the web-server-profile to this instance.
  5. In the incus_instance resource, use the user_data argument to provide a cloud-init configuration.
  6. The cloud-init script should perform the following actions:
  7. Update package lists (apt-get update).
  8. Install the nginx web server (apt-get install -y nginx).
  9. Start and enable the nginx service.
  10. Apply the configuration and use incus exec web-server -- systemctl status nginx to verify that Nginx is running inside the container.
  11. Destroy the resources.

Challenge 4: Managing Storage

Difficulty: Hard
Goal: Understand how to create and manage dedicated storage volumes and attach them to instances, which is crucial for stateful applications.

Make sure to create a profile and associate it with all your resouces

Tasks:

  1. Manually create a new storage pool if you only have the default. For example: incus storage create data dir.
  2. In your Terraform configuration, define an incus_storage_volume resource.
  3. Name the volume app-data.
  4. Assign it to the data storage pool you created.
  5. Define an incus_instance named database-server.
  6. Use the incus_storage_volume_attachment resource to attach the app-data volume to the database-server instance.
  7. Specify the attachment path inside the container as /mnt/data.
  8. Use a provisioner "remote-exec" to create a file on the attached volume, for example: touch /mnt/data/test.txt.
  9. Apply the configuration.
  10. Verify the volume is attached and the file exists by running incus exec database-server -- ls /mnt/data.
  11. Destroy the resources.

Challenge 5: Dynamic Inventory for Ansible

Difficulty: Hard
Goal: Integrate Terraform with another tool, Ansible. This challenge involves creating multiple instances and dynamically generating a configuration file that another tool can use.

Make sure to create a profile and associate it with all your resouces

Tasks:

  1. Use the count meta-argument in your incus_instance resource block to create three identical instances with a common prefix (e.g., web-prod-1, web-prod-2, web-prod-3).
  2. Ensure these instances are connected to a network where they have predictable IP addresses.
  3. Use the local_file resource from the hashicorp/local provider to generate an Ansible inventory file named inventory.ini.
  4. The content of the local_file resource should be dynamically generated using Terraform's template syntax.
  5. The inventory file should have a group named [webservers].
  6. Iterate through the created Incus instances and add each instance's IP address to the [webservers] group. The result should look something like this:
    [webservers]
    10.0.1.21
    10.0.1.22
    10.0.1.23

  7. Apply the configuration and verify that the inventory.ini file is created correctly in your project directory.

  8. (Bonus) Write a simple Ansible playbook to install a package on the webservers group and run it using ansible-playbook -i inventory.ini my-playbook.yml to confirm your dynamic inventory works.
  9. Destroy all resources.