Short version
sudo apt install nginx -y
Create a .conf file in /etc/nginx/conf.d/
See full config section for template
sudo nginx -t
sudo systemctl reload nginx
The example in this post uses test.acceptdefaults.com running nginx 1.18.0 on Ubuntu 22.04.
You may need to change commands/paths based on your distro.
Install
Update system
sudo apt update && sudo apt upgrade -y
install nginx
sudo apt install nginx -y
start nginx service
sudo systemctl start nginx
enable (run on startup) nginx service
sudo systemctl enable nginx
conf file
You’ll most likely want to disable the default config file.
sudo rm /etc/nginx/sites-enabled/default
Open a new conf file. You can name it anything. It’s a good idea to name to use the domain name.
See the config location note below if you want to use sites-enabled instead.
sudo nano /etc/nginx/conf.d/test.acceptdefaults.com.conf
Paste the config in the .conf file. Press ctrl+x then Y to save and enter to confirm the filename.
See the config notes below for more details.
server { listen 80; listen [::]:80; server_name test.acceptdefaults.com test2.acceptdefaults.com; location / { proxy_pass http://<IP>:<port>; } }
You may need additional proxy options depending on the target application. Most applications will list reverse proxy settings if they need it.
Test the config with sudo nginx -t
sudo nginx -t
Reload nginx to load the new config
sudo systemctl reload nginx
SSL
Obtaining a cert
If you don’t have an SSL cert you can get one from Let’s Encrypt using certbot. Here’s a link to the certbot setup steps.
You can also use a self-signed cert for staging.
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
Add SSL Config
If you used certbot this part was already done for you.
Add the lines below to your server directive.
The ssl_protocols and ssl_ciphers can be adjusted as needed. I used the defaults from certbot.
# SSL listen 443 ssl; listen [::]:443 ssl ipv6only=on; ssl_certificate /path/to/cert.pem ssl_certificate_key /path/to/private_key.pem ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
Move the listen 80 (and listen [::]:80; if using ipv6) to another server directive. Copy the server_name line from the 443 block.
server { listen 80; listen [::]:80; server_name test.acceptdefaults.com test2.acceptdefaults.com; }
HTTPS redirect
If you want to redirect HTTP traffic to HTTPS add the line below to your server directive listening on port 80.
return 301 https://$host/;
Test your config with sudo nginx -t
sudo nginx -t
Reload the config with sudo systemctl reload nginx
sudo systemctl reload nginx
Full config example with SSL
server { server_name example.com; location / { proxy_pass http://<ip>:<port>; } # SSL listen 443 ssl; listen [::]:443 ssl ipv6only=on; ssl_certificate /path/to/cert; ssl_certificate_key /path/to/private.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; } server { listen 80; listen [::]:80; server_name example.com; # HTTPS redirect return 301 https://$host/; }
Notes
Engine-X not N-Jinx
conf file location
Depending on your OS the default /etc/nginx/nginx.conf file may look in multiple locations for configuration files. You can find this in the http directive (surrounded in {}).
Here’s the default includes from a Ubuntu 22.04 install.
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
The internet likes to fight about this but they both work.
Debian based systems also include the sites-enabled directory. You can use /etc/nginx/conf.d/*.conf on Debian based systems.
One benefit of the sites-available and sites-enabled method is having disabled configs in the sites-available directory without having the config active. You can also accomplish this in /etc/nginx/conf.d/ by renaming .conf files to .conf.disabled.
/etc/nginx/conf.d
/etc/nginx/conf.d is pretty straight forward. Any .conf files in this directory will be loaded.
sites-available and sites-enabled
Any files in /etc/nginx/sites-enabled/ will be loaded. Files are typically symlinks (ln -s) from /etc/nginx/sites-available/.
Files are not required to be in the sites-available directory to be loaded and do not need to be a link. This is just a method to keep things organized.
You need to use the full path when creating the symlink or nginx will give an error when loading the config.
sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf
config notes
listen: This listens on the IP and port. If no IP is given it will listen on all ports. You can comment out [::]:<port> lines if you do not want IPv6.
server_name: You can use a space separated list if you need multiple domains. The ; is at the end of the list, not each domain.
location /: This uses the “/” location (ex:https://test.acceptdefaults.com/). You can use a different location (/app, /web, etc.) if you do not want to use the root location.
Nginx can also do load balancing but that’s a topic for another post. You could setup the reverse proxy using an upstream with only one server if you plan on load balancing it in the future.