How Do I Deploy My Website

This website is hosted using a combination of AWS services such as S3, CloudFront, API Gateway, Lambda, DynamoDB, ACM, Cloudwatch, SNS, and Cloudflare DNS. Terraform is used to automate the infrastructure provisioning, and GitLab CI/CD automates the deployment process. I do use Route53 Health Check with Cloudwatch alert for making sure my URL is UP. Below is an overview of the deployment process:
1. GitLab CI/CD for Automated Deployments

The deployment process is managed through a GitLab CI/CD pipeline that handles both development and production environments:
Development Pipeline (dev branch):
- Build Stage:
- Uses Docker-Compose service for container builds
- Builds a development Docker image using a custom Dockerfile
- Runs only on the 'dev' branch
- Deploy Stage:
- Deploys the application using Docker-Compose
- Provides containerized development environment
- Automatically rebuilds and updates service
Production Pipeline (main branch):
- Deploy Stage:
- Authenticates with AWS using secure credentials
- Synchronizes content with S3 bucket (
sahibgasimov.com) - Automatically invalidates CloudFront cache makes sure content updates immediately
- Runs only on the 'main' branch for production deployments
2. Terraform for Infrastructure as Code
In this setup Terraform I use to provision and manage AWS resources only. I keep IaC consistent which allows version control for the entire environment configuration.
3. S3 as an Origin for CloudFront
The website's static files (HTML, CSS, JavaScript) are stored in an S3 bucket configured as a private origin for CloudFront. Public access to the S3 bucket is disabled, and an Origin Access Control (OAC) is used to securely grant CloudFront permission to access the bucket. All content delivery is managed through CloudFront for enhanced caching, compression, and global delivery.
4. API Gateway and Lambda (Python) for Dynamic Functionality
API Gateway is used to expose endpoints (e.g., getCount and updateCount) that
trigger Lambda functions written in Python. These Lambda functions interact with DynamoDB to perform
operations such as retrieving and updating data. To ensure accuracy, the Lambda function implements
visit deduplication:
- IP Hashing: The visitor's IP address is extracted from the API Gateway event and hashed using SHA-256. This ensures visitor privacy (GDPR compliant) while allowing us to identify unique sessions.
- Visit Window: The system checks a tracking table to see if the visitor has already been counted in the last 24 hours.

5. CloudFront CDN for Fast and Secure Content Delivery
CloudFront is configured as the primary CDN for the website, ensuring fast, secure, and content delivery. Below are the key technical enhancements made to the CloudFront setup:
- Caching Optimization:
- The
CachingOptimizedpolicy has been applied to enable caching of frequently accessed files. - TTL (Time-to-Live) values for content have been fine-tuned to balance performance and content
freshness:
DefaultTTL:86400 seconds (1 day)MaxTTL:31536000 seconds (1 year)MinTTL:0 seconds (allows dynamic adjustments)
- Object cache control is managed using metadata on the S3 origin (e.g.,
Cache-Controlheaders).
- The
- Compression: Brotli and Gzip compression are enabled, ensuring reduced payload sizes for faster delivery of assets such as HTML, CSS, and JavaScript.
- Security Enhancements:
- HTTP-to-HTTPS redirection is enforced using the
ViewerProtocolPolicyset toredirect-to-https. - Key HTTP security headers are added using a custom response headers policy:
Strict-Transport-Security:Forces HTTPS connections with a max-age of 1 year.X-Content-Type-Options:Prevents MIME type sniffing.X-Frame-Options:Set toSAMEORIGIN, mitigating clickjacking attacks.Referrer-Policy:Set tono-referrer, enhancing privacy.
- HTTP-to-HTTPS redirection is enforced using the
- Origin Access Control (OAC):
- The S3 bucket used as the CloudFront origin is configured with an OAC to block all public access and only allow CloudFront to fetch content securely.
- This ensures the bucket cannot be accessed directly, improving security and centralizing content delivery through CloudFront.
- Clean URL Management: A custom CloudFront Function is implemented to handle URL path
rewriting:
- URLs ending with
.html(e.g.,/about.html) are redirected to paths without the extension (e.g.,/about). - Paths without extensions automatically append
.html(e.g.,/aboutbecomes/about.html).
- URLs ending with
Additionally, I'm using a CloudFront Function for HTML path redirection. All it does is cut ".html" from the
file endings. For example, if I have about.html, I can now route the path to /about,
and .html won't appear even if the user specifies .html explicitly. I've provided
detailed step-by-step instructions for this setup in my Medium blog.
CloudFront Function Code:
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check if the URI ends with .html
if (uri.endsWith('.html')) {
// Redirect to the version without .html (e.g., /about.html -> /about)
var newUri = uri.slice(0, -5); // Remove ".html" from the end of the URI
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { 'value': newUri }
}
};
}
// Append .html if the URI does not have an extension or does not end with a slash
if (!uri.includes('.') && !uri.endsWith('/')) {
request.uri += '.html'; // Append .html to paths without extensions
}
// Return the modified request
return request;
}
6. DynamoDB for Data Storage
DynamoDB is used as the backbone for the visitor counter data. It utilizes two main tables:
- Global Counter: Stores the total aggregate views for the website.
- Recent Visitors: A tracking table that stores hashed IP addresses. This table uses **AWS TTL (Time To Live)** to automatically expire and delete records after 24 hours, ensuring the "visit window" resets automatically without manual cleanup.
7. CloudWatch and Route53 for Monitoring and Alerts
CloudWatch is configured to monitor the health of Route53 Health Check URL path, and trigger alarms via SNS notifications.
8. SNS for Notifications
In the event of operational issues or threshold breaches, CloudWatch triggers alarms that notify the admin via an SNS topic, ensuring timely responses to any issues.
9. Cloudflare for DNS
My DNS is stored in Cloudflare. I manage a couple of websites, and being able to control DNS from a single dashboard without needing their password for their domain registrar is nice when I move or change the server I am hosting them on I also have a homelab, so instead of exposing ports on my router to various hosted services, I create subdomains for a domain I own and then follow this policy: If access to the service is public (like a website) I use a Cloudflare Tunnel. I can set access rules to block or allow certain countries, etc. If access to the service is restricted to me and a few other users, I use a Cloudflare Tunnel and a Cloudflare Application to provide authentication.
10. Frontend Development with HTML, CSS, and JavaScript
The front-end of the website is built using classic HTML for structure, CSS for styling, and JavaScript for interactivity. This ensures a responsive and dynamic user experience across different devices and browsers.