We hope you find this tutorial helpful. In addition to guides like this one, we provide simple cloud infrastructure for developers. Learn more →

How To Configure SSL Passthrough on DigitalOcean Load Balancers

PostedFebruary 14, 2017 23.5k views High Availability Load Balancing DigitalOcean Ubuntu Ubuntu 16.04


Load balancers distribute traffic among multiple backend servers. If one of those servers goes down, a load balancer will redirect traffic to the others, assuring that your services continue to be available. A load balancer also allows you to add additional resources to handle a temporary traffic spike or more general increase in demand. When balancing encrypted web traffic, there are two main configuration choices, SSL Termination and SSL Passthrough.

With SSL Termination, SSL requests are decrypted at the Load Balancer and sent unencrypted to the backend. This places the slower and more CPU intensive work of decryption on the Load Balancer and simplifies the management of the SSL certificates. However, the traffic between the Load Balancer and the backend is unencrypted, which means it is visible to any neighbors on that network segment.

The other option is SSL Passthrough, which sends SSL connections directly to the backend. Unlike SSL Termination, the requests remain encrypted and the decryption load is distributed across the backend servers. However, the certificate information must be replicated on every server. In addition, you cannot add or modify the HTTP headers, so you may lose the client's IP address, port, and other information contained in the X-forwarded-* headers.

In this guide, we will demonstrate how to configure DigitalOcean Load Balancers with SSL Passthrough, ensuring that data remains encrypted directly to the backend. To learn about SSL Termination, see How To Configure SSL Termination on DigitalOcean Load Balancers.


In this tutorial, we will use:

One Ubuntu 16.04 Droplet with:

  • a sudo user and basic firewall. The guide, Initial Server Setup with Ubuntu 16.04, can help you with this. We've created ours in the SFO1 data center and called it backend-01. In the tutorial, we will create an image of the first Droplet after configuring the SSL certificate, so by the end of the tutorial we will have two backend servers to balance.

In addition, in order to generate an SSL certificate you will need:

  • A domain that you control: You must own or control the registered domain name that you plan to use for the SSL certificate. If you do not already have a registered domain name, you can register one with any domain name registrar (e.g. Namecheap, Omnis, etc.). In this guide, we will use passthrough.example.com as the domain name.

During the tutorial, we'll install Nginx on the Droplet and configure SSL using Let's Encrypt. Since we're setting up SSL Passthrough, all of the web servers we use with our load balancer need the same certificate, so we'll create an image of our first server and use that as to create additional instances.

Step 1 — Setting Up backend-01

We'll begin by installing the web server on our backend server. First, refresh the apt package index, then install nginx with the following commands:

  • sudo apt-get update
  • sudo apt-get install nginx

We'll be using Ubuntu 16.04's Let's Encrypt client later in the tutorial, so we'll install it now as well:

  • sudo apt-get install letsencrypt

Once the installation completes, we'll allow HTTP and HTTPS traffic through the UFW firewall:

  • sudo ufw allow 'Nginx Full'
Rule added Rule added (v6)

To confirm that the rule was added, we'll run:

  • sudo ufw status
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx Full ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx Full (v6) ALLOW Anywhere (v6)

Now that we've allowed traffic through the firewall, we'll create content for testing.

Add a test page

To ensure a consistent visitor experience, the backends should generally be identical, but we'll create a web page to identify this backend in order to test the Load Balancer.

In the web server's document root, we'll add a file called lb.html:

  • sudo nano /var/www/html/lb.html

We'll enter the following content

/var/www/html/lb.html on backend-01
<h1 style="color:blue">Backend-01</h1>

We'll save the file and exit the editor, then visit the page using HTTP in a web browser:


The browser should display the following content:

Screenshot of the backend-01 test page

With the test content in place, we're ready to create the Load Balancer

Step 2 — Creating the Load Balancer

We'll navigate to the Load Balancers page by clicking "Networking", then Load "Balancers":

Screenshot with the Navigation Steps Highighted

Next, we'll click "Create Load Balancer", located in the center of the screen when there are no Load Balancers and in the upper-right when there are.


On the "Create Load Balancer" screen we will:

  • Name our Load Balancer "ssl-passthrough"

  • Add "backend-01", which will automatically select the region where "backend-01" is located.

  • Create the Load Balancer

We won't add our Passthrough rule until after we configure SSL on backend-01. If we were to add the rule before SSL were available, the health check would fail and the Droplet would not be available in the pool.

Screenshot of the Create Load Balancer Screen

This will take us to the Load Balancers index page, and a progress bar will display as the Load Balancer is created, which takes a couple of minutes. When it's done, the page will automatically update and display "New" and display the Load Balancer's IP address.

Screenshot of the Newly-Created Load Balancer

When this is complete, we can check that traffic on port 80 to ensure that it is being properly forwarded to the backend.

Let's visit our test page via the Load Balancer's IP address:


We should receive backend-01's content, this time served via the Load Balancer:

Screenshot of backend-01 Served by the Load Balancer

This verifies that the Load Balancer is successfully directing traffic to our backend. The next step is to configure DNS in order to generate an SSL certificate.

Step 3 — Assigning a Domain Name to the Load Balancer

Now we have the information we need to point a domain name to the Load Balancer's IP address.

You can follow the guide on setting up a domain name with DigitalOcean to create an A record for your domain or consult the documentation of your DNS service.

Important: Be sure to use the Load Balancer's IP address, not the address of a specific Droplet.

When you are finished configuring DNS, you should be able to visit the domain in a web browser using HTTP, and the Load Balancer should pass the request on to the backend.


Screenshot of backend-01 Accessed by Domain Name

When you can reach backend-01 by domain name, you're ready to set up SSL and a certificate.

Step 4 — Configuring Nginx to Use SSL

Since we'll be decrypting HTTPS requests on the backend, we need to configure Nginx to accept HTTPS. We'll do this in the default configuration file:

  • sudo nano /etc/nginx/sites-available/default

First, we'll add our server name to the Default server configuration:

 . . .
# Default server configuration
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name passthrough.example.com;
        # SSL configuration
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;

When we request our certificate, Let's Encrypt will need a location block to respond to the certificate challenge, so we'll add that block now. We'll put it right below our server name:

 . . .
server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name passthrough.example.com;
        location ~ /.well-known {
           allow all;
        # SSL configuration
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
    . . .

This regular expression location block explicitly allows access to requests containing .well-known

Next, we'll enable SSL by uncommenting the 443 listen directives:

 . . .

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name passthrough.example.com;
        location ~ /.well-known {
           allow all;
        # SSL configuration
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
    . . .

Finally, we'll be creating a configuration snippet so that Nginx can load the certificate files. We'll include that file now. In the line below, be sure to substitute your domain name in the file name, ssl-passthrough.example.com.conf:

 . . .
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        include snippets/ssl-passthrough.example.com.conf;        
    . . .

When you are finished, save and close the file.

Before we test the configuration, we need to create the snippet file to fill in later:

  • sudo touch /etc/nginx/snippets/ssl-passthrough.example.com.conf

With the file in place, we can test the configuration for syntax errors with the following command:

sudo nginx -t

If no problems are found, we should receive output like the following:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

To make the new configuration live, we'll need to restart Nginx, but before we do that, we'll generate the SSL certificate and fill in the snippet file.

Step 5 — Generating a Let's Encrypt Certificate

We'll request a certificate for our domain using the following command. Substitute your domain for the argument after the first -d, and any alternative names after additional -d flags:

sudo letsencrypt certonly -a webroot --webroot-path=/var/www/html -d passthrough.example.com

We'll be prompted to enter a recovery email address and then to accept the Let's Encrypt terms and conditions. After we've done that, if everything is successful we should receive a message like:

IMPORTANT NOTES: - If you lose your account credentials, you can recover through e-mails sent to sammy@digitalocean.com. - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/passthrough.example.com/fullchain.pem. Your cert will expire on 2017-05-10. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. - Your account credentials have been saved in your Let's Encrypt configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Let's Encrypt so making regular backups of this folder is ideal. - If you like Let's Encrypt, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

To use our newly-generated certificate, we'll create a new Nginx configuration snippet in the snippets directory. This must match the filename that we added to the default configuration earlier:

sudo nano /etc/nginx/snippets/ssl-passthrough.example.com.conf

Within the file, we'll set the ssl_certificate and ssl_certificate_key directives:

ssl_certificate /etc/letsencrypt/live/passthrough.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/passthrough.example.com/privkey.pem;

We'll double-check the configuration syntax again:

sudo nginx -t

Once we've confirmed the syntax is okay, we'll restart the web server to load our configuration changes:

sudo systemctl restart nginx

For a more detailed discussion the SSL configuration, see How To Secure Nginx with Let's Encrypt on Ubuntu 16.04

Now that we have an SSL certificate in place and have configured the web server to use it, we're ready to add the SSL passthrough rule.

Step 6 — Adding the Load Balancer SSL Passthrough Rule

We've tested that our DNS resolves to our Load Balancer and we've configured SSL on the backend, so now we can add the SSL Passthrough rule.

To do so, we'll return to the Load Balancers index page and open the "More" menu for ssl-passthrough, then select "Edit settings".

Screenshot of the Expanded More Menu

From here, we'll click the "Edit" button to add the Forwarding rule:


From the "New rule" dropdown, we'll select the HTTPS protocol, which will open a new row of options. In the dropdown menu that says "Certificate:, we'll select "Passthrough". When we do, the Droplet protocol will automatically change to HTTPS, the port will be updated to the default SSL port, 443, and the Save button will be available.

Screenshot of the Completed Passthrough Rule

We'll click "Save", and we are ready to test the SSL Passthrough by visiting the test page in a web browser using HTTPS:


We should see the test content, as well as an indication that the request is secure, although the exact symbol will vary depending on the web browser:

Screenshot of the Test Page Served by the Load Balancer by Domain

All that remains now is to add another Droplet to the backend and verify that the balancing works as expected.

Step 7 — Duplicating the Web Server

For SSL Passthrough, all of the web servers behind the Load Balancer will need to use the same SSL certificate. To accomplish this as well as to be sure our backends are configured the same, we'll take a snapshot of backend-01and create an additional Droplet.

Note: If you prefer, you can use scp or rsync to copy the certificate files from one server to the next.

We'll navigate to Images, choose the Dropletbackend-01, and click the "Take Snapshot" button:

Screenshot of the Take a Snapshot Page

When the Snapshot is complete, we'll click the "Create Droplet" button in the upper right, which will take us to the "Create Droplets" screen. Here, we'll select "Snapshots"

We'll choose the image we just created. You can adjust available options like size, additional options, ssh keys if needed. We'll leave the defaults, and name this Droplet backend-02, then click "Create":

Once our Droplet is created, we'll use ssh to connect to it in order to update the test page:

  • sudo nano /var/www/html/lb.html

We'll replace or update the heading to the following:

<h1 style="color: orange">Backend-02</h1>

Finally, we'll save and exit the file, then view the updated content by the Droplet IP address:



Once we've confirmed that the HTTP request by server IP address loads as expected, we're ready to add it to the Load Balancer.

Step 8 — Adding backend-02 to the Load Balancer

Let's add backend-02 so we can watch our Load Balancer in action!

We'll navigate back to the Load Balancers index page (Networking > Load Balancers). If there's just one Load Balancer, you can add Droplets from that page; otherwise, click the name of the Load Balancer, then click "Add Droplets." Add 'backend-02 and click "Add Droplets".


Once the second server has responded to the health checks and is marked heathy, we're ready to test.

Step 9 — Testing the Balancing

Now that we have two Droplets on the backend, we can test our Load Balancer by visiting our test page by domain name using HTTPS:


One of the two backends should load. The connection should be marked secure in the address bar, although the way the security status is displayed will vary depending on the browser.


When we refresh the page, we should see the load switch to the second backend.


This confirms that we're balancing SSL traffic between our two backend servers. By using SSL Passthrough we ensure that HTTPS requests are encrypted end-to-end.

Note: If you are able to see multiple backends when you visit the Load Balancer’s IP address, but not when you visit the domain name, verify that you have set up DNS using the Load Balancer’s IP, and not the IP address of one of the backend Droplets.


In this tutorial, we’ve demonstrated how to configure a DigitalOcean Load Balancer to use SSL Passthrough by setting up Nginx with a Let’s Encrypt SSL certificate on a single Droplet. We created a DigitalOcean image of that first Droplet, then used to create additional servers for the backend.


Creative Commons License