Introduction
Nginx is a powerful web server that can also act as a reverse proxy, load balancer, and caching server. One of its common use cases is to serve as a reverse proxy in front of multiple backend services while handling authentication at the proxy level.
In this post, we’ll cover how to:
- Set up an Nginx reverse proxy for a NestJS backend.
- Implement an authentication system to control access to backend services.
- Secure and optimize the configuration.
Why Use an Nginx Reverse Proxy?
A reverse proxy helps by:
- Enhancing security: Hiding internal services from direct exposure.
- Load balancing: Distributing traffic across multiple instances.
- Centralized authentication: Enforcing authentication before requests reach backend services.
- SSL termination: Handling HTTPS at the proxy level to offload encryption work.
Setting Up a NestJS Backend
First, let’s create a simple NestJS backend that will be proxied by Nginx.
1. Install NestJS CLI and Create a Project
npm i -g @nestjs/cli
nest new my-backend
cd my-backend
2. Create an Authentication Module
nest generate module auth
nest generate controller auth
nest generate service auth
Modify auth.service.ts
to return a mock authentication response:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AuthService {
validateToken(token: string): boolean {
return token === 'valid-token';
}
}
Modify auth.controller.ts
to verify JWTs:
import { Controller, Get, Headers, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Get('validate')
validateToken(@Headers('authorization') authHeader: string) {
if (!authHeader || !this.authService.validateToken(authHeader.split(' ')[1])) {
throw new UnauthorizedException();
}
return { status: 'valid' };
}
}
Run the backend:
npm run start
By default, it will run on http://localhost:3000
.
Configuring Nginx as a Reverse Proxy for NestJS
1. Install Nginx
sudo apt update && sudo apt install nginx -y
2. Configure the Reverse Proxy
Edit the Nginx configuration file:
sudo nano /etc/nginx/sites-available/reverse-proxy.conf
Add the following configuration:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000; # Forward requests to NestJS
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Save and create a symbolic link:
sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/
sudo systemctl restart nginx
This configuration forwards requests to the NestJS backend.
Adding an Authentication Layer
To restrict access, we can introduce an authentication mechanism.
1. JWT Authentication with Nginx and NestJS
We’ll modify our Nginx configuration to validate JWTs by forwarding authentication requests to the NestJS auth service.
Edit the Nginx configuration:
location / {
auth_request /auth/validate;
error_page 401 = @error401;
proxy_pass http://localhost:3000;
}
location /auth/validate {
proxy_pass http://localhost:3000/auth/validate;
internal;
}
location @error401 {
return 401 "Unauthorized";
}
Here, before forwarding any request to the backend, Nginx calls /auth/validate
. If it returns 401
, the request is blocked.
Securing Nginx
- Enable HTTPS with Let’s Encrypt:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
- Limit Request Rates to prevent brute-force attacks:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
location / {
limit_req zone=mylimit burst=20 nodelay;
}
Conclusion
Using Nginx as a reverse proxy with authentication for a NestJS backend provides a secure and scalable way to manage access to backend services. By leveraging JWT authentication, we ensure requests are validated before reaching our backend services.
Top comments (0)