Posted on Leave a comment

Simple Nginx Reverse Proxy in LXD

Launching the container

This how-to guide will take you through the steps to setup an Nginx reverse proxy on your system by using an LXD container to run Nginx and configure it to run as a reverse proxy, forwarding traffic to internal containers. This guide will assume that your system is already configured as an LXD server.

Before setting up the reverse proxy, run the following command to get a list of IP addresses for your containers, noting the address of the instances to forward traffic to:

$ lxc list

Start by launching a new instance using the Ubuntu 20.04 image. To launch the new instance and name it nginx-proxy use the following command:

$ lxc launch ubuntu:20.04 nginx-proxy

This will create a base container where we will install Nginx. Once the command finishes the container should be running. We will need to setup port forwarding (proxy port) for the TCP/UDP ports we want Nginx to handle. The plan is to have port 80 and 443 forwarded to the nginx-proxy container and from there it will redirect traffic to the appropriate instances. To forward ports, we can either edit the nginx-proxy container directly or create a profile for the port forwarding and attached it to the container. In this tutorial I will edit the container’s configuration directly. See https://lxdware.com/forwarding-host-ports-to-lxd-instances/(opens in a new tab) for instructions on creating profiles as an option.

Use the following commands to edit the configuration of the nginx-proxy container and forward both ports 80 and 443 from the host LXD server to the container:

$ lxc config device add nginx-proxy hostport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
$ lxc config device add nginx-proxy hostport443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443

Now it is time to connect into the container and setup the software. Use the following command to obtain a bash shell connection to the instance, use the exit command at anytime to leave the shell:

$ lxc exec nginx-proxy /bin/bash

Installing Nginx

The following commands will now be run inside the nginx-proxy container. Debian-based operating systems have the ssl-cert package which is an easy wrapper for openssl certs and creates the default self-signed certs that will allow us to get started with reverse proxying SSL traffic. Use the following command to install the Nginx and ssl-cert packages:

$ apt update && apt install nginx ssl-cert -y 

Setting up the proxy config

With Nginx installed, we will need to configure the server blocks in the default configuration file of Nginx. We will create a server block that listens on port 80 for any traffic with the destination URL srv1.test.internal, and forward that traffic to our internal instance at http://10.187.151.36:80. To edit the default configuration file use the following command:

$ nano /etc/nginx/sites-enabled/default

The default file will already contain server blocks for forwarding traffic to a default location. We will be appending additional server blocks to the file. Paste in the following server block, changing the text in red to your own DNS name, port and internal instance IP address as needed:

server {
    server_name srv1.test.internal;
    listen 80;

    location / {
        proxy_pass_header Authorization;
        proxy_pass http://10.187.151.36:80;
        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;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

When it comes to handling SSL/TLS traffic the reverse proxy will handle the SSL certificate. The configuration below listens for SSL traffic on port 443 destined for srv1.test.internal , and forwards that traffic to the internal instance. In the example the destination port is also changed to port 80, we is common among web apps that don’t handle SSL encryption directly. The port can be changed to what the instance listens on. The included snakeoil.conf adds in the self-signed certificates for encrypting the SSL traffic, this can be changed to point to your own certificates if you have them.

server {
    server_name srv1.test.internal;
    listen 443 ssl;

    location / {
        proxy_pass_header Authorization;
        proxy_pass http://10.187.151.36:80;
        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;
        proxy_set_header X-Forwarded-Proto https;
    }

    include snippets/snakeoil.conf;

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

Starting and Enabling Nginx

Now that the configuration has been added it is time to restart nginx to apply the changes. In addition to restarting Nginx it is a good idea to enable the service as well, as not all distributions enable it automatically. Run the following commands to restart and enable Nginx:

$ systemctl restart nginx
$ systemctl enable nginx

Congratulations! The container is now setup. Exit from the shell terminal and return to your LXD host server by using the command:

$ exit
Leave a Reply

Your email address will not be published. Required fields are marked *