Who doesn’t need a reverse proxy from time to time? This is a component that I often find very useful in various situations. A reverse proxy can allow you to expose services running on private networks, not having a public IP address. Or also to perform SSL-offloading by dealing with the certificates in a single place. And often to redirect and rename things, having a nice and friendly URL which exposes services with a lot less friendly domain names or also dynamic addresses (which is often the case in Cloud).
Not only Apache HTTP Server
Most of the time I do hear people thinking directly at Apache HTTP Server and that’s what they set up with mod_proxy or mod_rewrite to handle the required tasks. I have nothing against Apache HTTP Server: it does the job and it does it for many many years now and supports a bunch of extra features with various modules.
But, I do find it more annoying to set up and configure to be used only as a reverse proxy. I also do find it heavier and, historically on a heavy workload, it wasn’t performing great at all. Historically, by design, Apache HTTP Server struggled with scaling. Things improved with the newer versions (mainly with v2 vs v1 I believe), but still, it isn’t my first choice.
Let me introduce you to nginx
If you don’t already know about nginx, you really should consider investing few minutes to discover it. This tool is powerful and simple!
nginx (pronounced “engine x”) is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server.https://nginx.org/en/
I do find nginx to be lightweight, simple to set up, and very good at doing its job.
nginx works well on ARM cpus
As you probably know Oracle Cloud introduced ARM compute instances end of May in its offer. They come with the promise of good performance at a lower price for various workloads when compared to x86 processors.
Oracle released a benchmark with nginx stating it is up to 32% more powerful (handling more requests) running on ARM cpus than x86.
While you shouldn’t be after that 32% increase, the point is that nginx works well on ARM and because of that you could run it on a smaller and cheaper instance while still getting the performance and functionality you need.
Keep in mind that even with a Free Tier Oracle Cloud account you receive, for free, 4 ARM OCPU and 24Gb of memory to split between 1 and 4 compute instances as freely as you want.
How to install nginx on Oracle Linux?
How to install nginx on an Oracle Linux instance? The Oracle YUM repositories can provide older versions of nginx. But if you are after the latest “stable” version (which means no new features and only errors and security fixes) or the latest “mainline” version (the one which can receive new features and therefore could potentially break something you are using), you should look somewhere else.
The installation of nginx is still extremely simple. For example on Oracle Linux 7.9 (but the same works on 8) it is achievable with only a few commands.
# INSTALL NGINX
# setup YUM nginx repository
# why a repo? Because the OL software collection (rh-*) only has old versions (1.12, 1.14 and 1.16 which is the 2019 stable release apparently)
# (backslash in front of $ is very important !)
sudo bash -c "cat > /etc/yum.repos.d/nginx.repo" << EOL
name=nginx stable repo
name=nginx mainline repo
# install nginx
sudo yum install -y nginx
# start nginx (and enable the service)
sudo systemctl enable --now nginx
# open port 80 (HTTP) in the firewall
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reload
Congrats! You now have a webserver up and running.
The configuration files are located in /etc/nginx and owned by root, therefore you will need ‘sudo‘ when editing them. The default way of doing things is by adding a configuration file for every site you need in the /etc/nginx/conf.d/ folder. nginx will automatically load any *.conf file from that folder. If you want to test your configuration before asking nginx to use it, you can use:
sudo nginx -t
Once you have your configuration in place you have to tell nginx to reload the configuration to apply the new changes, you can do it with:
sudo nginx -s reload
After having defined your domain name and the proxy rules, you maybe want to use HTTPS to connect to it.
Free SSL/TLS certificates for your domain names sites
Nowadays HTTPS websites are the standard. You can still generate a self-signed certificate, but your browser will complain about it as not being trusted by default (except if you also import and trust the certificate authority you used to generate the certificate).
A nonprofit Certificate Authority is providing TLS certificates for free helps whit this: Let’s Encrypt.https://letsencrypt.org/
The simplest way to use the Let’s Encrypt services is by using Certbot. Certbot is a free, open-source software tool for automatically using Let’s Encrypt certificates manually-administrated websites to enable HTTPS.
The way to install Certbot in Oracle Linux changed over the years, and currently, the easiest way in my opinion is by using Python 3.6 or newer (an alternative is by using Snap, which require a different kind of setup).
# INSTALL CERTBOT
# Certbot (Python)
sudo yum install -y python36 augeas-libs
# set up Python virtual environment
sudo python3 -m venv /opt/certbot/
# upgrade pip in venv
sudo /opt/certbot/bin/pip install --upgrade pip
# install Certbot
sudo /opt/certbot/bin/pip install certbot certbot-nginx
# prepare Certbot command
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
# test Certbot command
sudo certbot --help
And now Certbot is ready to be used.
You can request the certificates for your domain and manually configure it with:
sudo certbot certonly --nginx
You can also let Certbot changing your nginx configuration to use the certificates it does get directly (please keep in mind it’s safer to take a backup of /etc/nginx/conf.d/ before using this option, just in case…) by using:
sudo certbot --nginx
Renew your SSL/TLS certificates before they expire
Let’s Encrypt certificates are free but valid for only 90 days, this is why you have to remember to set up a cron task renewing your certificates. You, therefore, need to set up a scheduled tasks renewing them before they do expire.
The Certbot site provides a command for that:
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
Last but not least, Certbot also should need to be updated from time to time. Certbot suggest to run
sudo /opt/certbot/bin/pip install --upgrade certbot certbot-nginx on a monthly base, you can also setup a cron job for this one as well so you don’t have to care anymore about it.
Remember that if you setup HTTPS websites, you also need to open port 443 in the firewall because so far only port 80 (HTTP) has been opened if you used the code above.
nginx is up and running, you have free SSL/TLS certificates for your domains. Your next step depends on your real need. You can set up the proxy functionality to forward the requests to a backend server or a pool of servers, with the benefit of load balancing. Online there are example configurations for many many different needs and they are fairly simple to understand also by keeping an eye on the documentation to understand how nginx configuration works.
My typical usage of nginx as reverse proxy in Oracle Cloud is when I want a friendly URL for Autonomous Database services (SQL Developer Web, Graph Studio or the ML notebooks), as public access to Jupyter Lab or Jupyter Hub running on a compute instance without a public IP address. I do also use it as proxy to a websockets router (for example Crossbar.io) running in a Docker container, as a way to easily change domain and have a valid SSL/TLS certificate for it. There aren’t really many limits, if something has a web interface and is accessible from the compute instance running nginx, a reverse proxy can be setup.