This documentation attempts to outline my implementation of NGINX and using NGINX as a proxy for docker containers. The main purpose of implementing NGINX in this way is to only keep up with one SSL certificate and also to use one website and TCP ports (80,443) to host multiple web applications. This is helpful when you are self hosting servers and have limited IP address space.
Like other posts this is specific to Ubuntu server specifically 22.04. Other distros implementation should be pretty similar though. To install NGINX issue the command sudo apt install nginx
. Once this is installed you should be able to navigate in a browser to http://127.0.0.1 and see the normal default webpage. If you do not see this webpage issue the sudo service nginx status
command to see if the service is started. If it's not started issue the sudo service nginx start
command to start it up.
Next, I use Let's Encrypt to generate a free 3-month SSL certificate to use on my personal projects. To do this on the server you must first purchase a domain and point the URL you want to use to the public IP that the server is using. You must also confirm that your upstream router/firewall/modem has a port forward for the port you are using, specifically ports 80 and 443.
Once you have your DNS and port forwarding setup, install certbot on the server by issuing the command sudo apt install certbot
. Once it is installed, run it in certonly mode. This will spin up a temporary server on port 80 from Let's Encrypt servers to ensure domain ownership and then will issue the key. The command to run this is sudo certbot certonly
. Follow the prompts and choose the temporary server option. If NGINX is already started, you have to stop it first before running the certbot command. To stop the NGINX server issue the command sudo service nginx stop
.
Keys are normally issued to /etc/letsencrypt/live/-domain name-/fullchain.pem and privkey.pem. You will need these paths when configuring NGINX.
I've given a sample configuration below for NGINX. This ties docker containers are even local services to specific paths on the web server. I've laid out each section below. To update yours you will need to edit the file /etc/nginx/sites-enabled/default (unless you have another configuration file).
#This section configured aliases used further down in the config for the docker IP and the port that the service on docker is running on. Keep in mind this is not docker forwarded port but the actual port the service is running on in Docker.
upstream SpoonWebsite {
server 172.17.0.2:80;
}
upstream SpoonBlog {
server 172.18.0.2:2368;
}
#This entry is an example of a service running on the actual system outside of a Docker container.
upstream SpoonWiki {
server localhost:8000;
}
#This section sets up what happens when port 80 is visited for the website. Below, I have it setup to just forward to HTTPS.
server {
listen 80;
listen [::]:80;
server_name spoonnet.net www.spoonnet.net;
location / {
rewrite ^ https://$host$request_uri? permanent;
}
if ($host = www.spoonnet.net) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = spoonnet.net) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name spoonnet.net www.spoonnet.net;
return 404; # managed by Certbot
}
#This is the most important section. Here you will need to update the ssl_certificate lines
server {
server_name spoonnet.net www.spoonnet.net;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.spoonnet.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.spoonnet.net/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
#This is the default location. Note that for proxy_pass it points to the alias above for the Docker website container.
location / {
proxy_pass http://SpoonWebsite;
proxy_redirect off;
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-Host $server_name;
}
#This is for subdirectory blog and points to a separate alias docker container.
location /blog {
proxy_pass http://SpoonBlog;
proxy_redirect off;
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-Host $server_name;
}
#Same as blog above
location /wiki {
proxy_pass http://SpoonWiki;
proxy_redirect off;
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-Host $server_name;
}
}
Once you have updated your configuration as needed, you will need to restart the NGINX service for the changes to take effect. Do this by issuing sudo service nginx restart
.