Section 03
Server Deployment Notes
EC2, keys, security groups, SSH, Docker, Nginx, domain.
Private key (.pem)
Your key. Keep on laptop. Never share. Never commit to GitHub.
Public key
Installed on EC2 by AWS. Like a lock on the door. Matches your private key.
Analogy: Public key = lock · Private key = key in your pocket · SSH = opening the door
Security Group — Inbound vs Outbound
| Port | Service | Open? |
|---|---|---|
| 22 | SSH | YES |
| 80 | HTTP / Nginx | YES |
| 443 | HTTPS | OPTIONAL |
| 8080 | Docker direct | NO |
| 3306 | MySQL | NO |
Inbound = traffic INTO server (SSH, website). Outbound = traffic OUT (apt, git clone, docker pull). Workshop: outbound allow-all is fine.
SSH login + first checks
chmod 400 workshop-key.pem ssh -i workshop-key.pem ubuntu@YOUR_PUBLIC_IP whoami hostname pwd uname -a free -h df -h sudo apt update sudo apt upgrade -y
Clone + Docker Compose on EC2
git clone https://github.com/USERNAME/REPO.git cd REPO docker --version docker compose version docker compose up -d --build docker compose ps curl http://127.0.0.1:8080
If curl works, Docker is fine. Fix Docker before configuring Nginx.
Nginx reverse proxy
Public entry on :80 → forwards to Docker on localhost:8080
sudo apt install nginx -y sudo systemctl status nginx
server {
listen 80;
server_name your-domain.duckdns.org;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
sudo nginx -t sudo systemctl reload nginx # Better Docker port binding after Nginx works: # ports: ["127.0.0.1:8080:80"]
Go-live checklist
- Create EC2 Ubuntu + key pair (.pem)
- Inbound: 22 + 80 (+443 optional)
- SSH login
- Install Git + Docker
- Clone repo → compose up → curl localhost:8080
- Install Nginx + reverse proxy
- Point domain / DuckDNS to public IP
- Open domain without :8080
- Restrict Docker to 127.0.0.1:8080