Introduction
I have a lot of services running in my homelab, and it becomes a bit of a hassle to remember all the ports and IPs of each service. I also want to expose some of these services to the internet, but I don’t want to expose them directly. This is where Nginx comes in. Nginx is a powerful reverse proxy that I use in my homelab to expose services to the internet. In this post, I’ll show you how I use it and how you can use it too.
What is a reverse proxy?
Let’s first take a step back and understand what a reverse proxy is. A reverse proxy is a server that sits between the internet and your web servers. It receives requests from clients and forwards them to the appropriate backend servers. It can also perform additional tasks such as load balancing, caching, and SSL termination.
You can read more about it here: Reverse Proxies: A Beginner’s Guide to Unlocking Their Power
Setting up Nginx
I run Nginx directly on my host machine, but you can also run it in a container. Here is the installation steps for setting up Nginx bare metal:
Once installed, you can start the Nginx service:
You should also enable the Nginx service to start on boot:
Use the following command to check the status of the Nginx service:
Nginx Configurations
Let’s now understand some of the basic configurations that you need to do to get Nginx up and running.
Server Blocks
Nginx uses server
blocks to host multiple websites on a single server. Each server block has its own configuration and can host multiple websites. The server block configuration is stored in the /etc/nginx/sites-available
directory. You can create a new server block configuration file for your website using the following command:
Here is an example of a basic server block configuration:
In this example, we are creating a server block for service.example.com
. We are listening on port 80 and forwarding the requests to the backend server running on http://192.168.0.101:3100
. You can create multiple server block configuration files for different websites and services.
Snippets
Nginx snippets are reusable configuration blocks that can be included in multiple server blocks. You can create a new snippet configuration file using the following command:
Here is an example of a basic snippet configuration:
In this example, we are creating a snippet configuration file that sets the necessary headers for proxying requests. You can include this snippet in your server block configuration files using the include
directive.
Considering the above server block example, you can include the snippet like this:
Custom Configs
You can also create custom configurations for Nginx. You can create a new custom configuration file using the following command:
Here is an example of a basic custom configuration:
This will disable the Nginx version in the headers and error pages.
Any configs which are added in the conf.d
directory are automatically included in the Nginx configuration. You can find this in the nginx.conf
file:
Enabling the Server
Once you have created the server block configuration file, you need to enable it by creating a symbolic link to the sites-enabled
directory. Let’s enable the example.com
server block configuration file:
You can also check the Nginx configuration for any syntax errors using the following command:
If there are no syntax errors, you can reload the Nginx service to apply the new configuration:
Now if you visit service.example.com
in your browser, you should see the website hosted on the backend server.
My Nginx Configurations
I have a lot of services running across multiple servers in my homelab. I use Nginx to reverse proxy everything. Considering three servers that I have named sukuna.lan
, satoru.lan
and sukuna.lan
and let’s say I am running immich on sukuna server on port 2283
, the FQDN for the service would be immich.sukuna.lan
. Here is how I would configure Nginx for this:
Now this works for HTTP, but I also want to enable HTTPS for some my services like Vaultwarden. For such service I have generated a self signed certificate.
To use the self signed certificates, I have few other snippets like ssl-params.conf
and self-signed.conf
which I include in the server block configuration file.
Here are the snippets:
And another one for the self signed certificate:
And here is how I include these snippets in the server block configuration file:
Here we are listening on port 443 and enabling SSL. We are also including the self-signed.conf
and ssl-params.conf
snippets. Additionally all requests to the HTTP port are redirected to the HTTPS port.
This is essentially how I am using Nginx for all my services whether it is HTTP or HTTPS. I also automate creation of these configs via Ansible to make my life a bit easier and make these configs better maintainable but I will cover about that in a separate post so keep an eye out for that.
Conclusion
Nginx is a powerful reverse proxy that I use in my homelab to expose services to the internet. In this post, I showed you how I use it and how you can use it too.
If you have any questions or suggestions, feel free to reach out to me on Twitter ↗️ / Reddit ↗️.
See you in another one! 👋