Skip to content
Personal / Career Engineering journal● Public portfolio
← All entriesProject dashboard ↗GitHub ↗

AWS · SEPTEMBER 14, 2026

Building a Family IT Help Desk on AWS

A cloud credit exercise became a working application for the people who already treat me as their IT department.

Family IT Help Desk v0.1 is complete. The final acceptance happened on September 13 in Toronto, September 14 UTC: an approved user submitted a ticket, the application returned its ID and priority, the same ticket appeared in DynamoDB, and the notification email arrived.

That final database check mattered. A convincing success screen was not enough. I wanted the ticket stored and the notification delivered before calling the first version done.

The cloud foundation came first

I started with account controls and a monthly AWS budget, then built a small Amazon Linux EC2 instance with encrypted storage, SSH restricted to one trusted source, and IMDSv2 required. I connected from PowerShell, inspected Linux and networking, installed a small package, and tested metadata access both without and with a token. When the lab was finished, I terminated the instance and verified that its root volume was gone.

I also used Nova Micro in Bedrock to review that configuration. The first response included advice that repeated controls already in place and blurred account MFA with SSH access. A corrective prompt improved the answer, but it still needed technical judgment. Two requests were enough to learn something useful; no persistent model deployment was created.

A useful reason to learn serverless

For Lambda, I wanted something I would actually keep. Family members already ask me about computers, Wi-Fi, printers, phones, accounts and suspicious emails. A small ticket app gave the cloud services a concrete job.

The first version takes a problem description, calculates priority in the backend, creates a ticket, stores it, emails me, and displays a confirmation. Its graphite, amber and teal interface has some personality, but the humor comes from ordinary code. There is no AI bill attached to each joke.

The architecture that actually shipped

The browser loads the page from a public Lambda Function URL. Cognito handles sign-in and email verification; membership in ApprovedUsers controls access to the help desk. The browser submits a bearer token to an API Gateway HTTP API. Lambda uses the validated claims, checks approval and input, writes the ticket to DynamoDB, and publishes an SNS email notification. CloudWatch provides the logging path.

The execution role has table-specific write permission and topic-specific publish permission. The frontend has no client secret. Hiding the form is helpful for the user experience, but the backend authorization check is the real boundary.

The mistakes worth keeping

One wrong assumption sent the login flow toward a CloudFront address even though no distribution existed. The fix was to use the actual Lambda Function URL consistently in the frontend, Cognito callbacks and CORS. CloudFront is not part of the completed deployment.

Another issue was protecting the page before the browser could load it and obtain a token. The public page and protected ticket submission needed different treatment. CORS settings also had to be saved as actual console entries, rather than simply typed into the input.

The interface needed its own corrections. Pending users initially saw content outside the approval panel. Later, future ticket stages appeared before a ticket had reached them. The accepted version shows Stage 1 first, adds Stage 2 after creation, and keeps the later stages hidden.

Complete has a boundary

The approved-user submission, matching database record and received email close v0.1. This was a small lab acceptance test, not a claim of production readiness or exhaustive security testing. The app is intentionally retained; exact ongoing billing has not yet been reconciled. My target remains $0 additional out-of-pocket cost.

That was the v0.1 checkpoint. Since then, all five AWS onboarding activities have been completed, including the Lambda web-app activity and a separate Aurora PostgreSQL lab. The final AWS starter-series checkpoint showed $199.97 USD in credits remaining after the small amount of lab usage. DynamoDB remains the Help Desk database; Aurora was a separate disposable engineering exercise.

v0.2: closing the management loop

v0.2 is now complete. The HelpDeskAdmins boundary, protected ticket retrieval, management interface and backend status-update path are working, and the full Submitted → In Progress → Resolved lifecycle has been validated end to end. Returning from ticket management restores the authoritative backend state, and the user-facing workflow advances through all four stages.

The final validation also exercised server-side required-field, category and impact checks, request-size rejection, and the security path. A security-category ticket was assigned Critical priority and displayed the security warning. A fresh-ticket smoke test passed after temporary browser debugging instrumentation was removed.

The debugging was part of the result: one restored-state ordering issue could overwrite the correct workflow stage, and a missing result-status element left presentation state stale even when the backend was correct. Tracing the DOM and separating authoritative backend state from client presentation state fixed the lifecycle without weakening the server-side controls.

The optional Bedrock troubleshooting assistant belongs to v0.3, after ticket management works. It will need bounded usage, and security-sensitive or high-priority issues will bypass AI. The help desk must remain useful without it.

The best result from this session was a working system with a finite first version. I can build on it without pretending that every future idea has to be completed today.

Read the Family IT Help Desk case study ↗

Explore the Cloud Engineering Portfolio ↗

← Back to the engineering journal