This collection contains roles for deploying network and server infrastructure onto bare metal. The scope of a deployment is referred to as a "site" which correlates to a /16 subnet of the class A private IPv4 network (10.site['id']
.0.0/16) as well as a fully qualified domain name (site.example.com). Sites are further divided into subnets defined by a /24 mask and subdomains of the FQDN. So at company "example.com", subnet "sales" with ID 5 in site "office1" and ID 99 would equate to sales.office1.example.com and subnet 10.99.5.0/24. Services are built on top of the network while avoiding circular dependencies so that infrastructure can always be rebuilt from a complete failure. This collection is intended for use by small to mid-size MSPs, IT departments or individuals managing up to 255 physically separate IPv4 networks.
While the roles are designed to be platform-agnostic so they can be reused, different use-cases target specific platforms. As of now, those platforms are (or are planned to be):
- Switch: RouterOS (Mikrotik)
- Gateway/Router/Firewall: OpenBSD
- NAS: ZFS/Gluster (Ubuntu LTS)
- Directory: FreeIPA (Rocky Linux)
- Hypervisor/PaaS: OpenShift (OKD4)
- Plug in ethernet adapter
- Prioritize default gateway on Wifi (this will allow us to provision over the adapter while maintaining an internet connection).
- Plug laptop into Switch PXE port via ethernet adapter
Deploy ssh key to switch and perform minimal initial configuration.
- Write Vagrant config for bootstrap-sw VM (Debian).
- Boot/provision bootstrap-sw VM with Mikrotik netinstall binary, firmware and initial config. VM should use the ethernet adapter as a public interface.
- Run netinstall binary on VM
- Boot switch with network boot option.
- Wait for switch to provision.
- Dump interface names to an inventory template (host_vars).
- Rinse and repeat for each switch.
Deploy ssh key to gateway and perform minimal initial configuration.
- Write Vagrant config for bootrap-gw VM (OpenBSD).
- Boot/provision bootstrap-gw VM with DHCP, PXE, TFTP and HTTP services.
- Boot gateway.
- Wait for gateway to provision.
- Dump MAC addresses and interface names to an inventory template (host_vars).
- Rinse and repeat for each gateway.
- Flesh out the configuration beginning with the inventory templates generated by the bootstrap playbooks. This is essentially the design process where we structure the network.
- Validate inventory and fill in any missing fields (
dev
based onmac_addr
for instance). - Provision switches (I tend to run WAN through the switch instead of directly to the gateway, so the switch needs to be provisioned first).
- Establish a basic Internet connection (note that the OpenBSD gateways will not have Python yet, so this must be done with
raw
andscript
modules only). - Install Ansible dependencies (Python)
- Configure network interfaces
- Configure pf
- Configure sshd (need to run this here because the
restart ssh
handler is a dependency of the next role). - Configure the Ansible user
- Configure routing
- Configure unbound as a forwarder
- Configure nsd as an authoritative name server
- Configure ntpd
- Configure tftpd (for pxe)
- Configure httpd (for pxe)
- Configure dhcpd
- Configure wildcard certificates via Let's Encrypt DNS verification
- Configure relayd as a reverse proxy
- Configure wireguard (will need additional inventory config for this)
Ex: inventory/campus1.example.com.yml
This file defines the structure of the network and the relationship between hosts and subdomains. If you've written an Ansible inventory, it should look familiar. The site role will initialize the file but it will need to be fleshed out manually. FQDNs should be used for each host to avoid naming collisions when dealing with multiple sites.
all:
children:
office_example_com:
hosts:
netinstall_routeros:
pxe_openbsd:
children:
gw:
hosts:
gw1.office.example.com:
gw2.office.example.com:
net:
vars:
subdom: net #use subdomain net for this group
children:
sw:
hosts:
sw1.net.office.example.com:
sw2.net.office.example.com:
sw3.net.office.example.com:
sw4.net.office.example.com:
ap1.net.office.example.com:
ap2.net.office.example.com:
srv:
vars:
subdom: srv #use subdomain srv for this group
children:
srv:
hosts:
www1.srv.office.example.com:
ftp1.srv.office.example.com:
nas1.srv.office.example.com:
nas2.srv.office.example.com: