Step-by-Step Guide to Building a Static Website Using AWS, Nginx, and Cloudflare

MindDevMindDev
4 min read

Why This Stack?

  • AWS EC2: Flexible virtual servers with full control over configuration.

  • Nginx: High-performance web server optimized for static content.

  • Cloudflare: Free CDN, DDoS protection, and SSL/TLS encryption.


Prerequisites

  1. An AWS account with EC2 access.

  2. A domain name (e.g., example.com).

  3. A Cloudflare account.

  4. Basic terminal/SSH skills.


Step 1: Launch an EC2 Instance

Start by launching an Ubuntu 22.04 LTS instance on AWS EC2.

1.1 Create a Security Group

Allow HTTP, HTTPS, and SSH traffic:

# Create security group  
aws ec2 create-security-group \
  --group-name StaticWebsiteSG \
  --description "Security group for static website"

# Allow SSH (port 22), HTTP (80), and HTTPS (443)  
aws ec2 authorize-security-group-ingress \
  --group-name StaticWebsiteSG \
  --protocol tcp --port 22 --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-name StaticWebsiteSG \
  --protocol tcp --port 80 --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-name StaticWebsiteSG \
  --protocol tcp --port 443 --cidr 0.0.0.0/0

1.2 Launch the Instance

aws ec2 run-instances \
  --image-id ami-0c55b159cbfafe1f0 \  # Ubuntu 22.04 LTS in us-east-1  
  --instance-type t2.micro \
  --key-name YourKeyPair \
  --security-groups StaticWebsiteSG \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=StaticWebServer}]'

Note: Replace YourKeyPair with your EC2 key pair name.


Step 2: Install and Configure Nginx

SSH into your EC2 instance and set up Nginx.

2.1 Connect to the Instance

ssh -i "your-key.pem" ubuntu@<EC2_PUBLIC_IP>

2.2 Install Nginx

sudo apt update && sudo apt upgrade -y  
sudo apt install nginx -y  
sudo systemctl start nginx  
sudo systemctl enable nginx

2.3 Deploy Static Files

Create a directory for your site and upload your HTML/CSS/JS files:

sudo mkdir -p /var/www/example.com/html  
sudo chown -R ubuntu:ubuntu /var/www/example.com  
nano /var/www/example.com/html/index.html  # Add your static content

2.4 Configure Nginx Server Block

Create a config file for your domain:

sudo nano /etc/nginx/sites-available/example.com

Paste this configuration:

server {
    listen 80;
    listen [::]:80;

    root /var/www/example.com/html;
    index index.html;

    server_name example.com www.example.com;

    location / {
        try_files $uri $uri/ =404;
    }
}

Enable the site and test the config:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/  
sudo nginx -t              # Validate syntax  
sudo systemctl reload nginx

Step 3: Secure the Server

3.1 Configure Firewall (UFW)

sudo ufw allow 'Nginx Full'  
sudo ufw enable

3.2 Enable HTTPS with Let’s Encrypt

Install Certbot and request a certificate:

sudo apt install certbot python3-certbot-nginx -y  
sudo certbot --nginx -d example.com -d www.example.com

Certbot automatically updates your Nginx config to use HTTPS.


Step 4: Set Up Cloudflare

4.1 Add Your Domain to Cloudflare

  1. Log in to Cloudflare and add your domain.

  2. Note the Cloudflare nameservers (e.g., lara.ns.cloudflare.com).

  3. Update your domain’s DNS nameservers via your registrar.

4.2 Create DNS Records

Add an A record pointing to your EC2 instance’s public IP:

# Use Cloudflare API (optional)  
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/dns_records" \
  -H "Authorization: Bearer <API_TOKEN>" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "A",
    "name": "example.com",
    "content": "<EC2_PUBLIC_IP>",
    "proxied": true
  }'

4.3 Configure SSL/TLS

  1. In Cloudflare Dashboard:

    • Go to SSL/TLS > Overview and set mode to Full (strict).

    • Enable Always Use HTTPS.

4.4 Enable Caching

Create a Page Rule to cache static assets:

URL Pattern: example.com/*  
Settings: Cache Level = Cache Everything

Step 5: Optimize Performance

5.1 Enable Gzip Compression in Nginx

Edit /etc/nginx/nginx.conf and add:

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

Reload Nginx:

sudo systemctl reload nginx

5.2 Configure Cloudflare Caching

Set browser cache TTL to 1 month:

# Use Cloudflare API  
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/settings/browser_cache_ttl" \
  -H "Authorization: Bearer <API_TOKEN>" \
  -H "Content-Type: application/json" \
  --data '{"value": 2592000}'

Step 6: Monitor and Maintain

  • Nginx Logs: Check access/error logs at /var/log/nginx.

  • Cloudflare Analytics: Monitor traffic and threats in the dashboard.

  • Renew SSL Certificates: Certbot auto-renews certificates, but test manually:

      sudo certbot renew --dry-run
    

Architecture

Your site is now served via Nginx on EC2, protected by Cloudflare’s CDN and security features.


Cost Breakdown

  • EC2: ~$3.50/month (t2.micro, non-free tier).

  • Cloudflare: Free plan includes CDN, SSL, and DDoS protection.

  • Domain: ~$10/year (varies by registrar).


Conclusion

You’ve built a production-ready static website with AWS EC2, Nginx, and Cloudflare. This setup guarantees speed, security, and scalability. To automate further, explore Terraform for infrastructure-as-code or GitHub Actions for CI/CD.

Got questions? Drop them in the comments below! For more guides, subscribe to our newsletter. 🚀


Further Reading:

0
Subscribe to my newsletter

Read articles from MindDev directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

MindDev
MindDev

Passionate AWS DevOps Engineer | Expert in EC2, Lambda & Cloud Computing | Building efficient Jenkins pipelines | Docker & Kubernetes enthusiast | #DevOpsCommunity"