Nginx Templates and Examples
Nginx Templates and Examples
This repo is a collection of templates and examples for how to use Nginx as a web server, load-balancer, and reverse proxy. Most of these ideas and concepts were learned from this great tutorial.
Templates
This section contains templates for the following Nginx use cases
- Web Server
- Reverse Proxy
- Load Balancer
- HTTPS Redirect
- Caching
The following templates show the structure of different Nginx configurations but are not actually working files.
Basic Web Server Template
Nginx is a web server technology wher the main config file is named "nginx.conf" and is usually placed in the /etc/nginx/
folder.
The following is a basic template for a web server. The file defines a server listening on port 80 and serves the index.html file for any route.
# nginx.conf
server {
listen 80;
server_name example.com www.example.com;
location / {
root /var/www/example.com;
index index.html index.htm;
}
}
Basic Reverse Proxy Template
Nginx can be used as a reverse proxy to sit in front of your services and route traffic. The advantage of this is it reduces the attack surface of your application and allows you to focus on the security of a single entry point.
In this example we define a server and then define a backend service where we want all traffic to be forwarded to
# nginx.conf
server {
listen 80
server_name api.example.com;
location / {
proxy_pass http://backend_server_address/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwared-Proto $scheme;
}
}
NOTE: it is very important to have the trailing /
on the proxy address!
Load Balancer Template
Extending the idea of using Nginx as a reverse proxy, we can use it as a load balancer. We can run multiple replicas of our services and use Nginx to distribute traffic between them for better reliability. Nginx also allows you to specify different algorithms for balancing the load like choosing the server with the least connections.
# nginx.conf
http {
# 3 instances of the same app running
upstream myapp1 {
# choose the load balancing algo - default: round_robin
# least_conn;
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
# proxy all requests to the myapp1 server group
proxy_pass http://myapp1/;
}
}
}
HTTPS Redirect Template
When it comes to security we want to serve our application on HTTPS. We also want to redirect HTTP requests to HTTPS for a good user experience. This HTTPS redirect template shows how to set this up.
Define one server to listen on port 80 (default HTTP port) and redirect traffic to HTTPS with a 301 code. The next server listens on port 443 (default HTTPS port), loads the SSL certificates and serves the application.
# nginx.conf
server {
listen 80;
server_name: example.com www.example.com;
# Redirect HTTP requests to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name: example.com www.example.com;
# Configure SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem
ssl_certificate_key /etc/letsencrypt/live/example.com/privatekey.pem
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; include_subdomains always;"
location / {
root /var/www/example.com;
index index.html index.htm;
}
}
Caching Template
This template shows how to use the proxy_cache_path
directive to define the path for storing the cache and naming it mycache
and then storing data for 10 minutes.
# nginx.conf
http {
# cache server responses to the zone "mycache"
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m;
server {
proxy_cache: mycache;
location / {
proxy_pass https://localhost:8000/;
}
}
}
Examples
The following examples can be run locally by editing the nginx.conf
on your local machine and then reloading the server with nginx -s reload
. Check out the Go example to see how to run the Nginx proxy and Go server with Docker and Docker Compose.
You can find the location of your Nginx install with nginx -V
and finding the --conf-path
. For me it is /opt/homebrew/etc/nginx/nginx.conf
.
This section contains examples for the following Nginx use cases
- Static Site Server Example
- Reverse Proxy for a Node Server with SSL Example
- Reverse Proxy with Multiple Services Example
- Load Balancer for a Vue Frontend and Node Backend Application
- Reverse Proxy for Go Server with SSL
Self-Signed SSL Certificate
For examples using SSL you will also need to generate your own self-signed SSL certificate for access to the server over HTTPS using openssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx-selfsigned.key -out nginx-selfsigned.crt
x509 certificate type nodes - do not encrypt the private key with a passphrase days 365 - certificate is valid for a year newkey rsa:2048 creates a 2048 bit RSA key pair
Static Site Server
With this example we use the NGINX docker image and docker compose to host a static website. This idea can be used to host an SPA by simply putting the built distribution of your application in the expected directory for static hosting.
The NGINX base image looks something like the first server template above and is configured to serve files from /usr/share/nginx/html
by default. We use docker compose to bind our folder containing an html file to the expected location in the container.
The base image also listens on port 80 by default. We can use docker compose to bind any port we like to send traffic port 80. I chose 8089 here.
# docker-compose.yaml
services:
nginx:
image: nginx:1-alpine
ports:
- 8089:80
volumes:
- ./static/:/usr/share/nginx/html
Test it out by running docker compose up
from the /docker-compose-static
directory and then going to localhost:8089
in your browser. You should see a basic hello world page.
Reverse Proxy for Go Server with SSL
Create a basic Go server
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from Go in Docker!")
})
fs := http.FileServer(http.Dir("static/"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
http.HandleFunc("/headers", func(w http.ResponseWriter, r *http.Request) {
for name, headers := range r.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
}
}
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
})
fmt.Println("Server starting on port 8081")
log.Fatal(http.ListenAndServe(":8081", nil))
}
Create a nginx.conf
file that looks to pass traffic to the go server
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
server {
listen 443 ssl;
ssl_certificate /etc/nginx/nginx-selfsigned.crt;
ssl_certificate_key /etc/nginx/nginx-selfsigned.key;
location / {
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;
proxy_pass http://backend:8181/;
}
}
# Redirect HTTP requests to HTTPS
server {
listen 80;
location / {
return 301 https://$host$request_uri;
}
}
}
Then create a docker compose file that runs the Nginx server in a container and the go server in another container. Make sure to mount the SSL certificates and ensure both containers are on the same network.
Run docker compose up --build
and access the Go server APIs at localhost:80
or localhost:443
. Try out the different routes /hello
, /headers
, /static
Check out the code on GitHub for more examples.