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.
Examples:
- Kubernetes
- Jenkins
- Hashicorp Vault
- NextCloud
- Gitlab
- Grafana
- Prometheus
- Portainer
- OpenVPN
- Some Telegram bots
-
NFS server
-
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:
- hosts:
[ghima] 192.168.4.2
This file contains the inventory of machines we’re using Ansible to manage, for now we only have a proxmox server.
- group_vars/ghima.yml
---
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.
- roles/ghima-networking/tasks/main.yml:
---
- 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/interfaces
file 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.