Designing a homelab network
Designing and creating a homelab network running Proxmox
Now that I have an automated and simple way to create virtual machine templates as well as virtual machines, it is time to start thinking about what I want to create.
Designing the virtual networks
For now, the only available network on Proxmox is the Linux bridge
vmbr0 which is directly connected to
my local Lan.
In addition to that, I would like to have three other networks:
A development network: This will host many different things including a kubernetes cluster, a jenkins server and whatever technology I happen to be playing around or want to experiment with as well as virtual machines for whatever other personal projects I happen to be working on. It will also serve as a lower environment to test in any experimental features.
A production network: This will host services which I happen to find useful or handy in my daily life/operations. This environment will be handled with a little bit more care than the previous one.
- Hashicorp Vault
- Some Telegram bots
A security network: This will serve as a security lab where I can experiment with different versions of vulnerable software, hone my pentesting or reverse engineering skills.
- A Security sandbox network: This one will be an airtight sealed network where viruses, worms, and different kinds of malware could be studied freely.
One of the main criterias for this network is that it will require strict isolation and monitoring to make sure nothing escapes and nothing I do within it has consequences or affects rest of my network.
I hope this paints a vague picture of how the environment will look like, it is of course not set in stone as many things will change given how many unknown restrictions and issues lie ahead.
Now back to the practical side of things, I mentioned wanting to create three additional networks within our proxmox environment. Creating the kind of network I would like to create is relatively easy, all that is needed is modifying the
/etc/network/interfaces file to include the definition of our networks. We are obviously not going to go ahead and modify these files manually on the system for reasons which should be obvious, so how are we going to do it? the answer is: Ansible.
Why ansible? Well, modifying a file on a remote system and maintaining it in that state seems like the kind of task Ansible was made to handle..
Let’s start by setting up Ansible properly.
How to start an Ansible project
According to Ansible’s best practices section, this is how the a directory layout of a project should look like:
production # inventory file for production servers staging # inventory file for staging environment group_vars/ group1.yml # here we assign variables to particular groups group2.yml host_vars/ hostname1.yml # here we assign variables to particular systems hostname2.yml library/ # if any custom modules, put them here (optional) module_utils/ # if any custom module_utils to support modules, put them here (optional) filter_plugins/ # if any custom filter plugins, put them here (optional) site.yml # master playbook webservers.yml # playbook for webserver tier dbservers.yml # playbook for dbserver tier roles/ common/ # this hierarchy represents a "role" tasks/ # main.yml # <-- tasks file can include smaller files if warranted handlers/ # main.yml # <-- handlers file templates/ # <-- files for use with the template resource ntp.conf.j2 # <------- templates end in .j2 files/ # bar.txt # <-- files for use with the copy resource foo.sh # <-- script files for use with the script resource vars/ # main.yml # <-- variables associated with this role defaults/ # main.yml # <-- default lower priority variables for this role meta/ # main.yml # <-- role dependencies library/ # roles can also include custom modules module_utils/ # roles can also include custom module_utils lookup_plugins/ # or other types of plugins, like lookup in this case webtier/ # same kind of structure as "common" was above, done for the webtier role monitoring/ # "" fooapp/ # ""
Since we are starting off with a mildly small project, we just want to automate the task of modifying a file (
/etc/network/interfaces) on a remote linux machine, and then restart the networking service so that our changes take effect.
Our project layout should look look something like this:
hosts # inventory file for our servers group_vars/ ghima.yml # This is the variable group for our Proxmox, the name ghima means "Cloud" in Algerian site.yml # master playbook ghima.yml # playbook for webserver tier roles/ ghima-networking/ tasks/ # main.yml # <-- Here we will store the part which orchestrates the changes we wish to make handlers/ # <-- No handlers needed for now, but let's include it either way templates/ # <-- Same goes for templates vars/ # <-- Same here
Now that we have a skeleton for our project, let’s look at the individual files we need:
This file contains the inventory of machines we’re using Ansible to manage, for now we only have a proxmox server.
--- dev_network_ip: 192.168.5 dev_network_if: vmbr1 prod_network_ip: 192.168.6 prod_network_if: vmbr2 sec_network_ip: 192.168.7 sec_network_if: vmbr3 sandbox_network_ip: 192.168.8 sandbox_network_if: vmbr4
This file contains the set of variables to expect to need while setting up the networking part of the proxmox server.
--- - name: create development/production and security networks blockinfile: path: /etc/network/interfaces block: | auto iface inet static address .1/24 bridge-ports none bridge-stp off bridge-fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s '.0/24' -o -j MASQUERADE post-down iptables -t nat -D POSTROUTING -s '.0/24' -o -j MASQUERADE auto iface inet static address .1/24 bridge-ports none bridge-stp off bridge-fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s '.0/24' -o -j MASQUERADE post-down iptables -t nat -D POSTROUTING -s '.0/24' -o -j MASQUERADE auto iface inet static address .1/24 bridge-ports none bridge-stp off bridge-fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s '.0/24' -o -j MASQUERADE post-down iptables -t nat -D POSTROUTING -s '.0/24' -o -j MASQUERADE auto iface inet static address .1/24 bridge-ports none bridge-stp off bridge-fd 0 post-up echo 1 > /proc/sys/net/ipv4/ip_forward post-up iptables -t nat -A POSTROUTING -s '.0/24' -o -j MASQUERADE post-down iptables -t nat -D POSTROUTING -s '.0/24' -o -j MASQUERADE - name: Restart service networking ansible.builtin.service: name: networking state: restarted
In this file, we define two actions to execute:
- Making sure the
/etc/network/interfacesfile contains the configuration block defining the addition 4 virtual networks.
- Restarting the networking service to make sure the changes added above are applied.
Now that we have a ready to use Ansible playbook, let’s deploy it:
ansible-playbook site.yml -i hosts -k
For now we are using password based authentication to deploy our changes, this is of course not ideal but I will amend that in the future.
In between all of these networks we will be needing a firewall to control the traffic flow, for that purpose, and at least initially, the Proxmox firewall should suffice. We will delve into that deeper in the future.
We might eventually want to include some DHCP servers in each network, but for now assigning IP addresses manually through cloud-init should be conveninent enough.