Selected work · Learning Management System
Hosting an internal Learning Management System on AWS
We host an open-source LMS — Totara — for internal company learning, on EC2 behind a subnet-segmented network built to contain blast radius. Here's how the current infrastructure is built, and the landing-zone roadmap I'd take it through next.
Totara — an open-source, Moodle-based learning management system — hosted on AWS to deliver internal company training. I support this infrastructure and maintain the platform and its dependencies.
01Current network design
Test and production are fully separated at the subnet level, not just by tagging or naming convention — each tier gets its own EC2 and its own subnet:
- Test EC2 in its own test subnet
- Test database in its own subnet
- Reachable only over internal VPN
- Production EC2 in its own production subnet
- Production database in its own subnet
- Reachable by consumers over the public internet
- A Fortinet firewall sits in front of all traffic before it reaches EC2 — handling networking security and firewalling in one place.
- All instances are Linux.
- The subnet split is deliberate defense-in-depth: if one subnet is compromised, the blast radius stays contained — the separated subnets are harder and slower to reach from there.
02Roadmap — where I'd take this next
Split into a proper multi-account landing zone
Move this out of a single account and into an AWS Organization — Management, Security, Log Archive, and Audit accounts, with Dev and Production as their own accounts rather than subnets within one. See how I approach that structure in general.
Automated patching — with a human in the loop
SSM-driven automated patching sounds like a clean win, but blind automation is risky here: an open-source LMS like Totara is version-locked to specific dependency ranges (PHP, HTTP server, and others) per release. An unattended kernel or package update can silently jump the stack out of what that Totara version supports and break the platform. The fix isn't skipping automation — it's automating the patch proposal and requiring human approval before it applies, so someone checks compatibility against the current Totara version first.
- WAF in front of both Dev and Production.
- A Transit Gateway back to the corporate network, so developers reach the test environment through normal internal routing instead of a separate VPN hop.
- A proper load balancer + Auto Scaling group in front of the app tier, instead of scaling by hand on a single EC2 instance.
- Amazon Inspector for continuous vulnerability scanning across all instances.
- AWS Config and Secrets Manager for configuration compliance and credential management.
- Centralized CloudWatch logs, VPC Flow Logs enabled, and alerting wired through CloudWatch + SNS + EventBridge.
- Infrastructure defined in CloudFormation or Terraform, with IAM policies tightened to least privilege throughout.
The current design already gets the network segmentation right — test and prod fully isolated by subnet, firewalled, VPN-gated. The next step is turning that into a real multi-account landing zone, adding the observability and scaling layer it's missing, and making patching safe by keeping a human in the approval loop.
One of the pieces of work I want to talk through is our Learning Management System. We use AWS to host it — it's Totara, an open-source platform, and we use it to give internal company folks a learning management system. To host it, install it, and maintain it and all its dependencies, we run a dev and a production environment on EC2.
The way we built it, those environments are fully separated out into their own subnets. There's a test subnet and a production subnet, and we host the EC2 for each environment inside its own subnet — test EC2 in the test subnet, production EC2 in the production subnet. Same for the database: test database in its own subnet, production database in its own separate subnet.
In front of all of that, we have a Fortinet firewall in one place before traffic ever reaches the EC2 instances — that's what handles the networking security and firewalling for us. These are all Linux instances. And for the network, we set up VPN so that the test instance is only reachable by internal folks over internal VPN, while production consumers reach it over the public internet.
I've supported this infrastructure, and I have a clear list of what I'd improve next.
Where I'd take it
The biggest structural change is expanding this out of a single account into a full AWS Organization — a Security account, a Log Archive account, an Audit account, a Management account — and turning Dev and Production into genuinely separate accounts instead of subnets sharing one account.
I'd also add automated patching through SSM — but carefully. Automated patching sometimes really doesn't work the way you'd want it to, because you don't always know what's going to change underneath you and how that affects your LMS version. If you're running a certain version of an open-source LMS — say Totara 18, 19, or 20 — each of those supports a specific range of dependency versions: certain PHP versions, certain HTTP server versions, and so on. So when you patch, you have to be careful not to update the kernel or the packages past the point where Totara still supports them, or you'll run straight into breakage.
Past that, I'd lean more heavily into internal AWS services. I'd bring in a Web Application Firewall for both Dev and Production, and set up a Transit Gateway back to our corporate environment so developers can still reach the test environment internally without a separate VPN step. I'd build out a proper logging system so all the metrics and logs are actually captured, and use a load balancer to scale with user demand instead of relying on a single EC2 instance.
I'd bring in Amazon Inspector to do vulnerability scanning across all the instances, set up Auto Scaling, and use AWS Config and Secrets Manager. I'd centralize CloudWatch logs, enable VPC flow logs, and wire up alerting through a combination of CloudWatch, SNS, and EventBridge. For deployment, I'd move the infrastructure to CloudFormation or Terraform, and make sure every IAM policy involved is least-privilege.