How to set up a single EC2 instance running Nginx as a load balancer and SSL terminator using Let’s Encrypt, directing traffic to three EC2 instances running a Laravel application. This guide assumes a standard AWS VPC environment and that you have control over DNS records for your domain.
Overview of the Architecture
- Public-facing EC2 (Load Balancer):
- Runs Nginx.
- Terminates SSL using Let’s Encrypt certificates.
- Proxies requests to the 3 backend Laravel application servers.
- Three Backend EC2 Instances (Laravel App Servers):
- Run Laravel (with PHP-FPM, Nginx, or Apache).
- Accessible only within the same VPC, ideally in private subnets.
- The load balancer communicates with them via private IP addresses.
Prerequisites
AWS Setup:
- A VPC with subnets. Assume:
- One public subnet for the load balancer EC2.
- Private subnets for the Laravel app servers.
- Security groups properly set up so the load balancer can access the app servers on port 80 (or your chosen port).
- A VPC with subnets. Assume:
EC2 Instances:
- Load Balancer EC2:
- Public subnet.
- Has a public IP or an Elastic IP (EIP) so it’s reachable from the internet.
- Laravel App EC2s:
- Typically in private subnets (recommended) or can be public if properly secured.
- Each running a web server (Nginx/Apache) and PHP-FPM, serving the Laravel app on port 80 internally.
- Ensure that DNS (e.g.,
example.com) points to the public IP of the load balancer EC2.
- Load Balancer EC2:
DNS Configuration:
- In your domain registrar or DNS provider, create an A record for
example.compointing to the load balancer EC2’s public IP. - If using a subdomain (e.g.,
app.example.com), point that subdomain to the load balancer.
- In your domain registrar or DNS provider, create an A record for
Step-by-Step Setup
A. Set Up the Backend Laravel Instances
Install and Run Laravel:
- On each Laravel EC2 instance, ensure:
- PHP, Composer, and a web server (Nginx or Apache) are installed.
- The Laravel code is deployed in
/var/www/htmlor a similar directory. - Nginx or Apache is configured to serve the application at
http://localhost:80.
- Test locally on each instance:
You should see the Laravel default page or your application’s output.
- On each Laravel EC2 instance, ensure:
Security Groups (Backend):
- The backend servers’ security group should allow inbound traffic on port 80 only from the load balancer’s private IP or security group, not from the public internet.
- Outbound traffic is usually unrestricted by default.
B. Set Up the Load Balancer EC2 (Nginx + Let’s Encrypt)
Install Nginx: On a Ubuntu-based system:
Confirm Nginx is running:
Open Ports in Security Group (Load Balancer):
- Inbound: allow HTTP (80) and HTTPS (443) from
0.0.0.0/0so the public can access the site. - Outbound: allow traffic to the backend servers on port 80.
- Inbound: allow HTTP (80) and HTTPS (443) from
Configure Nginx Upstream for Load Balancing: Create an upstream configuration file:
Add:
Replace IPs with the actual private IPs of your Laravel servers.
Create Nginx Server Block for HTTP:
Add:
Create the root directory for Let’s Encrypt challenges (if it doesn't exist):
Enable the site:
Now
http://example.comshould route to one of the backend Laravel servers. Test by visitinghttp://example.com.
C. Obtain and Install Let’s Encrypt SSL Certificate
Install Certbot: On Ubuntu:
Run Certbot:
Certbot will:
- Place a challenge file in
/.well-known/acme-challenge/for domain verification. - Request an SSL certificate from Let’s Encrypt.
- Update the Nginx configuration automatically to use HTTPS.
- Place a challenge file in
Check the Nginx Configuration After Certbot: After Certbot finishes, it should create or update the
example.comconfig to:- Redirect
http://tohttps:// - Use
ssl_certificateandssl_certificate_keydirectives pointing to your Let’s Encrypt certificates.
A typical final config might look like:
Test:
Now,
https://example.comshould serve the Laravel app over HTTPS.- Redirect
D. Verify Load Balancing and SSL
- Open
https://example.comin a browser. - Confirm the SSL certificate is valid and secured (lock icon in the browser).
- Refresh multiple times to ensure requests are distributed across the three backend servers (you can check logs on each server to confirm hits).
E. Certificate Renewal
- Certbot sets up a systemd timer or cron job to auto-renew certificates.
- Check:
This ensures your SSL certificate is renewed automatically.
F. Additional Considerations
Sticky Sessions / Session Storage: If your Laravel application uses session data (e.g., user logins), consider using a centralized session store such as Redis or a database. Without this, different requests may land on different app servers and cause issues if each server stores sessions locally. Configure
SESSION_DRIVERin.envaccordingly.Health Checks & Failover: Consider enabling health checks to ensure Nginx only routes requests to healthy backend servers. You can configure
proxy_next_upstreamor a specific health check endpoint.Logging and Monitoring:
- Nginx logs:
- Access logs:
/var/log/nginx/access.log - Error logs:
/var/log/nginx/error.log
- Access logs:
- Laravel logs on backend servers:
Checkstorage/logs/laravel.logto ensure the requests are being served correctly.
- Nginx logs:
Scaling: If you need more backend servers in the future, just add their IPs to the
upstreamblock and reload Nginx. This makes the system scalable.
Summary:
- You set up an EC2 instance as a load balancer with Nginx and obtained an SSL certificate from Let’s Encrypt.
- You pointed your domain name to the load balancer, which then routes traffic to three backend Laravel servers.
- The setup terminates SSL at the load balancer and distributes requests over HTTP to the Laravel servers internally.
- With proper DNS, security groups, and upstream configuration, you have a secure, load-balanced environment for your Laravel application.
Thank you
No comments:
Post a Comment