Basic EC2 Web Server
AWS EC2, SSH, security groups, Linux and deployment.
Overview
Launch an AWS EC2 instance, connect over SSH, configure security groups, install a web server and deploy a simple site.
The problem
Launch and deploy to a basic AWS EC2 web server with SSH and security groups.
Why it matters
Launching and securing cloud VMs is a core cloud skill.
What you'll build
- A cloud web server
- Secure SSH access
- A deployed site
What you'll learn
- EC2
- AWS
- SSH
- Deployment
Business problem
Teams deploy web servers on cloud VMs safely.
Technical problem
Provision an EC2 instance, secure it, and deploy a site.
When you're done: A secure EC2 web server serving a site.
Requirements
User requirements
- Launch an instance
- SSH in
- Serve a site
- Restrict access
System requirements
- AWS account
- EC2
- Security groups
Functional requirements
- Launch instance
- Key pair
- Security group
- Web server deploy
Non-functional requirements
- Secure access
- Minimal cost
Technical requirements
- EC2
- SSH
- SG rules
Security requirements
- Restrict SSH
- Least-privilege SG
Operational requirements
- Documented launch steps
Constraints
- AWS free tier preferred
Success criteria
- Instance reachable over SSH
- Web server serves content
- SSH only from your IP
Flows
Request Flow
- 1
Browser
User requests the application over HTTPS.
- 2
CDN / DNS
Edge routes the request to the origin.
- 3
Load Balancer
Distributes traffic across healthy app instances.
- 4
Application
Handles the request, applies business logic.
- 5
Cache
Serves fast reads for hot data.
- 6
Database
Persists data and returns results.
Project Structure
Root of the client application source.
Setup
- 1
Prerequisites
You need the tools required by AWS, EC2, SSH installed and available on your PATH.
- 2
Clone project
Clone the repository locally.
1. Clone the repositorygit clone <your-repo-url> <project-folder> - 3
Install dependencies
Install the project dependencies.
1. Connect over SSHLinux / Windowsssh -i <your-key>.pem ubuntu@<public-ip>Expected
Opens a remote shell.
If it fails
Permission denied / timeout
Fix
Check the key permissions and security group.
- 4
Configure environment
Set the environment variables documented for this project. Never commit secrets.
1. Create the environment filecp .env.example .env # then edit values - 5
Start project
Run the development command and confirm it starts.
1. Update the systemLinuxsudo apt update && sudo apt upgrade -y - 6
Verify
Open the printed local URL and confirm the primary flow works.
Build Phases
0 of 6 phases complete
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Run
1. Connect over SSHLinux / Windowsssh -i <your-key>.pem ubuntu@<public-ip>Expected
Opens a remote shell.
If it fails
Permission denied / timeout
Fix
Check the key permissions and security group.
Tasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Run
1. Update the systemLinuxsudo apt update && sudo apt upgrade -yTasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Tasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Tasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Tasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Objective: Establish the next milestone of the operational environment.
What changes: The project advances to the next coherent state, keeping the previous milestones working.
Files touched
Relevant source and configuration files for this milestone.Tasks
- Implement the specific behaviour required for this milestone.
- Verify the previous milestone still works.
Validate: The milestone behaves as expected and does not break existing functionality.
Common mistakes
- • Skipping validation and moving on before confirming the milestone works.
Commands
ssh -i <your-key>.pem ubuntu@<public-ip>Expected
Opens a remote shell.
If it fails
Permission denied / timeout
Fix
Check the key permissions and security group.
sudo apt update && sudo apt upgrade -yTesting
Unit tests
Core logic and pure functions behave correctly.
ssh -i <your-key>.pem ubuntu@<public-ip>Success: All unit tests pass without errors.
Integration tests
Components integrate correctly with data sources and services.
npm testSuccess: Integration tests pass for the primary flows.
API tests
Endpoints respond to valid and invalid input correctly.
npm testSuccess: API tests cover happy and failure paths.
End-to-end tests
A user can complete the primary journey end to end.
npm run test:e2eSuccess: The main user journey completes successfully.
Security tests
No obvious security regressions are introduced.
npm auditSuccess: No high or critical vulnerabilities.
Debugging & Troubleshooting
Port already in use at startup
Why: Another process is binding the same port your app wants.
Check: List what is using the port.
lsof -i :3000 # Linux/macOS | netstat -ano | findstr :3000 # Windows
Fix: Free the port or start your app on a different port.
Prevent: Choose uncommon ports and document them in the README.
Environment variable missing or undefined
Why: A required value was not loaded into the runtime.
Check: Print the variable or inspect the config loader.
echo $MY_VAR # Linux/macOS | echo %MY_VAR% # Windows
Fix: Add the variable to your .env file and restart the process.
Prevent: Fail fast at startup when required env vars are absent.
API request times out
Why: An upstream call is slow or the network is blocked.
Check: Time a direct request against the upstream.
curl -w 'time_total: %{time_total}\n' http://upstream/healthFix: Add timeouts and retries to the client; verify the upstream is up.
Prevent: Set explicit timeouts and circuit breakers on outbound calls.
Dependency fails to install or run
Why: Version conflicts or an incompatible runtime.
Check: Inspect the error and the installed versions.
npm ls <pkg>
Fix: Align versions or clear the lockfile and reinstall.
Prevent: Commit a lockfile and use the same Node version everywhere.
Security
Security is treated as a core requirement: input is validated, secrets are protected, and dependencies are kept up to date.
Input validation
Validate and sanitize all user input before use.
Secrets management
Store secrets in environment variables, never in source.
Dependency hygiene
Regularly audit dependencies for known vulnerabilities.
Deployment
- 1
Prepare for deployment
Build the production artifact.
1. Build for productionnpm run build - 2
Deploy
Deploy to the project target platform following its documented steps.
1. Deploynpm run deploy # or the platform-specific command - 3
Verify
Confirm the deployed application responds and its health check passes.
1. Check healthcurl -I https://<your-deployed-url>
Documentation
Project Overview
Launch an AWS EC2 instance, connect over SSH, configure security groups, install a web server and deploy a simple site. This is a beginner cloud project in the operational environment space, built to demonstrate real engineering, not just copied code.
What You Will Build
- A cloud web server - Secure SSH access - A deployed site
Problem Statement
Teams deploy web servers on cloud VMs safely. Provision an EC2 instance, secure it, and deploy a site.
Technology Stack
AWS, EC2, SSH, Linux
Installation
Clone the repository and install dependencies with the documented commands.
Local Development
Run the development command and open the printed local URL.
Testing
Run the test commands documented in the Testing section and confirm they pass.
Deployment
Follow the documented deployment steps for this project's target platform.
Interview Explanation
Use the Interview section to explain the architecture, technology choices and trade-offs.
Build Process
Phases guide the build in 6 checkpoints. Complete each and validate before moving on.
Interview Prep
30-second pitch
I built Basic EC2 Web Server — launch and deploy to a basic aws ec2 web server with ssh and security groups. It uses AWS, EC2, SSH and solves teams deploy web servers on cloud vms safely.
2-minute walkthrough
Launch an AWS EC2 instance, connect over SSH, configure security groups, install a web server and deploy a simple site. The core requirements were Launch instance, Key pair, Security group. I structured the work around Launch an EC2 instance, Secure it with security groups, Deploy a site and validated the result with the documented tests.
Architecture
Because this is a devops-foundations project, the architecture is concentrated in operational environment rather than a distributed system.
Why these technologies
I chose AWS, EC2, SSH, Linux because they are the pragmatic, well-supported tools best suited to building a cloud of this kind.
Why this architecture
The structure exists to keep concerns separated, make each piece testable, and scale the project cleanly as requirements grow.
At scale
At scale I would introduce caching, move to a service boundary structure, add proper observability, and enforce stricter contracts between components.
What can fail
The data source becomes unavailable, A dependency introduces a breaking change, Performance degrades under load, Configuration drift between environments
Monitoring
Monitoring is covered in the Observability section, focusing on basic health and error signals.
Security
Security was handled by validating input, protecting secrets, and following the practices listed in the Security section.
Deployment strategy
Deployment follows the steps in the Deployment section for the target platform, with a health check to confirm success.
What I'd do differently
With more time I would add deeper test coverage, stronger observability, and automated deployment.
Practice Q&A
Why did you build Basic EC2 Web Server?
To demonstrate Launch an EC2 instance and Secure it with security groups on a real, portfolio-worthy project.
What was the hardest part?
Coordinating the pieces so each stays correct as the project grows, and validating end to end.
How do you handle failure and scale?
By designing for correctness first and adding resilience once the core works.
Extensions
- Add deeper test coverage
- Add observability and alerting
- Harden security
- Automate deployment