Problem
This was an 18-assignment web technologies course where each assignment built on the last, deployed to the same AWS EC2 instance the whole way through rather than reconstructed afterward. The end state is a database-backed CMS with a full authentication system, but the point of the case study is the build-up, not just the final screenshot.
Infrastructure
The instance runs under a dedicated IAM user rather than root, applying least privilege from initial setup. nginx serves the site with HTTPS through a self-signed TLS certificate, and MySQL with phpMyAdmin handles the database layer.
Build progression
| Stage | What it added |
|---|---|
| hw2 | Single static HTML page |
| hw3–hw5 | Multi-page static site (home, contact, hobbies, school, work), styling passes |
| hw6–hw7 | Client-side JavaScript introduced |
| hw8 | Bootstrap refactor and a shopping-cart UI |
| hw9 | First PHP page, rendering a dynamic date |
| hw10–hw11 | GET/POST form handling; the contact page converted to PHP |
| hw12 | Server-side validation helpers extracted into a shared file |
| hw13 | Remaining pages converted to PHP, navigation rendered dynamically |
| hw15 | First real database write, the contact form inserting into MySQL |
| hw16 | Database connection helper extracted; stored contacts read back and displayed |
| hw17 | Full CMS: navigation and page content pulled dynamically from menu and pages tables, with explicit field selection in every query instead of wildcard selects |
| hw18 | Full authentication system: registration with duplicate-username checking, salted SHA-256 password hashing, server-side session IDs, and a protected results page that validates the session against the database |
(hw1 and hw14 were non-code assignments and were never deployed to the instance.)
After launch
The instance sat untouched for about a month after the course ended. Pulling screenshots for this case study surfaced a dead MySQL service, killed by the kernel's OOM killer during a memory spike and stuck in a failed state after exhausting systemd's restart limit. The fix was a swapfile and a capped InnoDB buffer pool size. The full write-up, including the dmesg and journalctl evidence, is on DailyBlog: My EC2 Instance Had Been Dead for a Month and I Didn't Know.