Algonquin College capstone

Hybrid MSP Infrastructure & AWS Kubernetes Service

A 17-VM, two-site managed-service environment for two client tenants, extended with a public HTTPS service on a Terraform-provisioned Kubernetes cluster.

Discipline
Infrastructure · Networking
Sites
Two, VPN-linked
Tenants
Lumora · ClearRoots
Delivered
Apr 2026
Period
Jan – Apr 2026
17
Virtual machinesPublic-cloud site
8
VLAN segmentsMSP · LAN · DMZ · SAN
2
Client tenantsSeparate directory platforms
9
AWS resourcesTerraform-provisioned

Sheet A

Architecture

Site 2 · as built

Fig. 01Site 2 — MSP boundary, tenant segmentation, and storage isolation
Capstone Site 2 network topologyAn OPNsense gateway routes six segments: a shared MSP management segment containing two bastions and a backup server, and LAN plus DMZ segments for each of two tenants. Two isolated storage bridges sit outside the routed path, reached over iSCSI from each tenant's file server. A site-to-site VPN tunnel connects to Site 1. The same information is listed in the table below the diagram.WANrp-msp-gateway — OPNsense edge — routing, firewall policy, NAT publication, VPN terminationrp-msp-gatewayrouting · policy · NAT · VPNMSP 172.30.65.177/29 — Shared management and recovery segment — bastions and backupMSP172.30.65.177/29Jump64 — Windows bastion — AD and Veeam administrationJump64.178MSPUbuntuJump — Linux bastion — tenant and OPNsense inspectionMSPUbuntuJump.179S2Veeam — Backup repository and offsite copy targetS2Veeam.180C1LAN 172.30.65.1/26 — Lumora directory, file and endpoint networkC1LAN172.30.65.1/26C1DC1 — Primary domain controller — AD DS, DNS, DHCP, Group PolicyC1DC1.2C1DC2 — Secondary domain controllerC1DC2.3C1FS — Windows file server, iSCSI initiatorC1FS.4C1WindowsClient — Domain-joined Windows endpointC1WindowsClient.11C1UbuntuClient — Domain-joined Linux endpointC1UbuntuClient.36C1DMZ 172.30.65.161/29 — Lumora web publication zoneC1DMZ172.30.65.161/29C1WebServer — Internal IIS serverC1WebServer.162C2LAN 172.30.65.65/26 — ClearRoots identity, file and endpoint networkC2LAN172.30.65.65/26C2IdM1 — Samba AD — DNS, DHCP failover primary, SMBC2IdM1.66C2IdM2 — Samba AD — DHCP failover secondaryC2IdM2.67C2FS — Linux file server, iSCSI initiator, replicated sharesC2FS.68C2LinuxClient — Domain-joined Linux endpointC2LinuxClient.75C2DMZ 172.30.65.169/29 — ClearRoots web publication zoneC2DMZ172.30.65.169/29C2WebServer — nginx HTTPS serverC2WebServer.170iSCSIC1SAN 172.30.65.186/29 — Isolated block storage bridge — deliberately off the routed pathC1SAN172.30.65.186/29outside routed pathiSCSIC2SAN 172.30.65.194/29 — Isolated block storage bridge — deliberately off the routed pathC2SAN172.30.65.194/29outside routed pathSite 1 — Veeam backup copy target 192.168.64.20 via SITE1_OVPNSITE1_OVPN → Site 1

Select an element

Point at or tab to any node, subnet or the gateway

Key
  • Routed via OPNsense
  • Isolated / tunnelled
Tenants
  • Lumora — Windows-centric
  • ClearRoots — Linux-centric
Published at edge
  • RDP :33464 → 172.30.65.178:3389
  • SSH :33564 → 172.30.65.179:22

Inspect — select a system or subnet

Site 2 network segments, addressing, and member systems. Selecting a segment or system highlights it in the diagram above.
SegmentCIDRGatewayMembers
172.30.65.177/29172.30.65.177
172.30.65.1/26172.30.65.1
172.30.65.161/29172.30.65.161
172.30.65.65/26172.30.65.65
172.30.65.169/29172.30.65.169
172.30.65.186/29none — isolatedIsolated block storage bridge — deliberately off the routed path
172.30.65.194/29none — isolatedIsolated block storage bridge — deliberately off the routed path

Sheet B

Specification

The brief

Emerging Technologies hands a team a blank-slate managed-service contract: design, build, and operate shared infrastructure for two client organisations across two physical sites, to a stated set of availability and security requirements — then extend it with a public-facing cloud service.

The two clients are deliberately mismatched. Lumora is a mission-driven organisation that wants a professionally supported environment, predictable cost, centralised identity, and Canadian data handling. ClearRoots is a budget-conscious NGO that prefers open-source platforms, wants to avoid vendor lock-in, and still needs fault-tolerant core services. One tenant pulls toward Microsoft; the other pulls away from it. They share hardware regardless.

Deliverables were a working environment, a 122-page technical handover, a client-facing SLA, and a live defence.

Scope of my work

End-to-end ownership of the public-cloud site — the MSP edge, both tenant stacks, the dual-bastion operations layer, the backup target, and the AWS-hosted service extension were designed, built, and operated solo. The on-prem site was delivered collaboratively.

The MSP boundary

A single OPNsense instance, rp-msp-gateway, carries the WAN edge and anchors eight internal segments: a shared management network, a LAN and a DMZ for each tenant, and two isolated storage bridges.

Segmentation here is not only a security control — it is a triage aid. Each network tells a support engineer where to look first. If the problem is on the MSP segment, it starts at the gateway, a bastion, or the backup host. If it is on C1DMZ, it is a Lumora publication issue and not a ClearRoots identity issue. If storage breaks, the routed network can be perfectly healthy while the file service fails — which is why the SAN bridges sit outside the routed path entirely (see note 1).

Firewall policy is written against named aliases rather than one-off addresses, so a tenant’s reachable scope is described once and reused. Each tenant LAN may reach its own scope, the shared web nodes, and the DNS authorities — and is explicitly blocked from the other tenant’s scope.

Tenant services

Lumora runs a Windows-centric stack: two Windows Server 2022 domain controllers holding AD DS, DNS, DHCP, and Group Policy; a Windows file server presenting SMB shares from iSCSI-backed storage; an IIS server in the DMZ; and both Windows and Ubuntu domain-joined endpoints.

ClearRoots runs the Linux equivalent: two Samba AD nodes paired for DHCP failover, providing AD-compatible authentication, DNS, and SMB; a Linux file server with iSCSI-backed and replicated shares; an nginx server in the DMZ; and a domain-joined Linux client.

The interesting work was not either stack individually — it was keeping them cleanly separated on shared hardware without letting DNS or DHCP scope bleed across the tenant boundary (see note 3).

Operations

Site 2 is operated through a dual-bastion model. Jump64 is the Windows inspection platform, best for AD and backup administration. MSPUbuntuJump is the Linux platform, faster for identity, file, and web validation. Splitting them by operating model resists the temptation to overload one host with every tool in the environment.

S2Veeam anchors recovery: it holds the local repository and receives the offsite copy from Site 1 across the VPN tunnel, on an explicitly enumerated set of ports rather than an open path between sites. Only the two bastions are published at the edge (see note 2).

The cloud extension

The public service is a containerised site running on a two-node kubeadm cluster on EC2, published at clearroots.omerdengiz.com.

Every AWS resource is declared in Terraform — the IAM role and instance profile, the security group, both instances, the Elastic IP, the Route 53 record — with remote state in S3 so the environment can be destroyed and rebuilt reproducibly. That mattered concretely: during the defence, the entire cloud site was torn down and rebuilt from scratch in front of the panel.

The worker carries the Elastic IP because it is the traffic-serving node, which keeps the DNS record valid across worker reboots. The control plane needs no stable public address for browser traffic, and publishing both would add exposure without improving delivery. Caddy on the worker terminates TLS and proxies to a NodePort service, so certificate issuance and renewal need no separate subsystem.

The cloud stack shares nothing with the internal environment (see note 4).

Sheet C

Notes

4 items

Sheet D

Revisions

What I would change

  1. 01Move TLS into cert-manager with an ingress controller. Caddy on the worker was the right call for a defence demo — one Caddyfile line and no YAML — but it is not how a production cluster should terminate TLS.
  2. 02Replace the self-managed kubeadm cluster with EKS for anything beyond a teaching environment. Bootstrapping the control plane by hand was the point of the exercise; running it that way in production is not.
  3. 03Split the Terraform root into modules. The team hit merge pain near deadlines exactly where module boundaries would have absorbed it.
  4. 04Extend Prometheus and Grafana across both sites. The on-prem side had Zabbix and the cloud side had nothing; one observability story would have been cleaner than two partial ones.

← All work