Introduction

Ansible is my go-to IaC tool. Why? Because unlike other tools it just requires SSH or WinRM access to a machine. I prefer this method for simplicity rather than creating a master/slave relationship.

LXD is also my go-to container and virtual machine manager. Sure, we can debate all day the pros and cons and compare to “Docker”. Although, I must state for local development, I will use Docker and Docker Compose, but for production, I prefer LXD, which runs an OS as a container and can utilize the benefits of a VM.

In short, technology is subjective, you choose what you like, and I like these tools. Of course, another tool to consider, for development, would be Vagrant. I love Hashicorp! … I had to mention it. lol.

Code

Assuming you have Python, Ansible and LXD installed, to quickly create a playbook, I always opt to use Ansible Generator. Simply install via pip install -U ansible-generator and run ansible-generate -p playbook_name. Add a role as well ansible-generate -r role1. In both cases name your project and role to what you see fit.

Let’s create a hosts file. In a future article I will expand on this; however here we just put a name as these “hosts” will all be local.

# inventory/hosts
proxy

I rename playbook.yaml to site.yaml and fill with the following code:

# site.yaml
---
- hosts: localhost
  # run this task in the host
  tags: servers
  connection: local
  tasks:
    - name: create containers
      loop: "{{ groups['all'] }}"
      community.general.lxd_container:
        name: "{{ item }}"
        state: started
        source:
          type: image
          mode: pull
          server: https://images.linuxcontainers.org
          alias: ubuntu/focal/amd64
        profiles: ["default"]
        wait_for_ipv4_addresses: true
        timeout: 600
        devices:
          # configure network interface
          eth0:
            type: nic
            nictype: bridged
            parent: lxdbr0
            # get ip address from inventory
            # ipv4.address: "{{ hostvars[item].ip_address }}"
        # uncomment if you installed lxd using snap
        url: unix:/var/snap/lxd/common/lxd/unix.socket

    - name: add port maps
      community.general.lxd_container:
        name: proxy
        devices:
          map_port_2095:
            type: proxy
            listen: tcp:0.0.0.0:2095
            connect: tcp:127.0.0.1:80
          map_port_2096:
            type: proxy
            listen: tcp:0.0.0.0:2096
            connect: tcp:127.0.0.1:443
          map_port_8080:
            type: proxy
            listen: tcp:0.0.0.0:8080
            connect: tcp:127.0.0.1:8080

# NOT NEEDED
# WILL EXPAND ON THIS IN FUTURE ARTICLE
# EXAMPLE FOR INTERACTING WITH THE CONTAINER
#- hosts: proxy
#  tags: proxy
#  roles:
#    - consul_client
#    - proxy

The idea in this site.yaml is to pull Ubuntu Focal from https://us.images.linuxcontainers.org/. You may also change this to another image if you want. I am also using the default profile I created when initializing LXD. As a side note, I also suggest using LVM and create your own thin pool. Managing environments with LVM is much easier and super simple to expand drives. Some good articles on the subject can be found HERE and HERE.

Several ports have also been forwarded. This is useful if you want to utilize proxies like Traefik, Nginx, etc. In the example above I utilize Cloudflare’s DNS proxying on ports 2095 and 2096. I also make port 8080 available for the Traefik API. Again, in a future article I will create a role for Traefik.

We need to install the community collection, and then we can run ansible playbook to create the LXD environment:

ansible-galaxy collection install community.general
ansible-playbook -i inventory/hosts site.yml --tags="servers"

Further information can be found at Ansible.

You should be able to see your environment, lxc list, and to enter it lxc exec proxy -- sudo /bin/bash.

Final Words

Ansible is a super simple tool to use. It has a big community and many collections to help interact with many things. LXD/LXC is one of many containerization technologies available, but it is simple to use and offers a full-blown OS.