Nginx Reverse Proxy with Let's Encrypt

This guide describes how to secure an existing Elasticsearch server using an Nginx reverse proxy via a native HTTPS connection on port 443 with a Let's Encrypt certificate.

Prerequisites

  • Active Elasticsearch server
  • No services installed on ports 80 or 443
  • SSH root access to the Elasticsearch server



Preparation

First, log in to the Elasticsearch server via SSH to perform the remaining configuration steps. If you did not provide a public SSH key for the server when ordering it, you can retrieve the login credentials from the Customer Center under the menu item Server → Password Vault in the Customer Center.


This guide sets up the reverse proxy for the Elasticsearch server XXXXX.creolineserver.com with Kibana. Please adjust the hostname accordingly in all of the following configuration files. Our servers with pre-installed Elasticsearch are all provided with Kibana and an Nginx reverse proxy.



Log in to the server via SSH using the root user:

ssh root@XXXXX.creolineserver.com



Nginx Installation

By using Nginx, you can configure a Let’s Encrypt certificate alongside the HTTPS connection on port 443, which is automatically renewed before it expires.


apt update && apt install curl gnupg2 ca-certificates lsb-release

# Install the official Nginx repository
wget -qO - http://nginx.org/packages/keys/nginx_signing.key | apt-key add -
echo "deb http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list

# Install the Nginx web server
apt update && apt install nginx



After installation, you can use systemctl to check whether the Nginx server was successfully installed and started.

systemctl status nginx

● nginx.service - nginx - high-performance web server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2021-09-22 16:01:18 CEST; 6s ago



Nginx Configuration

Disable the default vhost configuration with the following command:

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled


Then add a new configuration file using the following command:

nano /etc/nginx/conf.d/elasticsearch-proxy.conf



server {
    listen 80;
    server_name localhost XXXXX.creolineserver.com;

 location / {
 proxy_pass http://127.0.0.1:9200;
 proxy_read_timeout 60;
 proxy_connect_timeout 60;
        proxy_buffering off;
 client_max_body_size 100M;

        proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Real-IP $remote_addr;
    }
    location /kibana {
 proxy_pass http://127.0.0.1:5601/kibana;
 proxy_read_timeout 60;
 proxy_connect_timeout 60;
 proxy_buffering off;
        client_max_body_size 100M;

 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Real-IP $remote_addr;
    }
}


If you have changed the Elasticsearch HTTP API port, you must update the NGINX configuration accordingly. The same applies to the Kibana port and the corresponding /kibana location directive. The Kibanasettings are only required if you have installed Kibana for Elasticsearch.


Next, check the configuration for syntax errors and reload the NGINX configuration so that your changes take effect.

nginx -t

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

systemctl reload nginx



Let’s Encrypt Installation

Install the Certbot package to issue Let’s Encrypt certificates:


apt update && apt install certbot python3-certbot-nginx



Let’s Encrypt Configuration

After successfully installing the Certbot package, you can issue the necessary SSL certificate using the certbot command.


If this is your first time using the certbot command, you’ll need to enter an email address to receive expiration notifications and important security alerts.


certbot --nginx -d XXXXX.creolineserver.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): <Your email address>

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the nonprofit
organization that develops Certbot? We'd like to send you emails about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the web server configuration.
2: Redirect - Redirect all requests to secure HTTPS access. Choose this for
new sites, or if you're confident your site works over HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [Enter] (press 'c' to cancel): 2

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for XXXXX.creolineserver.com
Using default port 80 for authentication.
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://XXXXX.creolineserver.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=XXXXX.creolineserver.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Enable HTTPS redirection if you want to automatically redirect incoming traffic on port 80 (HTTP) to port 443 (HTTPS).



Automatic Renewal of SSL Certificates

For automatic renewal, the certbot.service and certbot.timer are already included with the certbot package, so a manual cron job is no longer needed.


If you do not wish to use the two systemd services provided by certbot, you can also trigger the certbot package twice daily via a cron job using crontab -e:


52 0,12 * * * certbot renew --post-hook "nginx -t && systemctl reload nginx" 


The cron job is only necessary if the systemd services certbot.service and certbot.timer have been disabled.



Firewall Configuration

You can then block direct access to Elasticsearch via the Cloud Firewall, so that all future HTTP requests must be sent exclusively through the Nginx proxy.

To do this, create a new firewall rule that allows incoming TCP traffic on ports 80 and 443, and use another rule to block all other incoming traffic.



Please note that additional rules are required to access Kibana. If your application server has a static IP address, it is recommended that you allow HTTP and HTTPS communication exclusively from the application server’s source address.



Testing HTTP(S) Requests

You can use curl to verify that the configuration was successful and that the Nginx proxy is functioning as intended.


curl https://XXXXX.creolineserver.com
{
  "name" : "XXXXX.creolineserver.com",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "Mi_bhUolSw2UTHTnVNoKZA",
  "version" : {
    "number" : "7.14.2",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "6bc13727ce758c0e943c3c21653b3da82f627f75",
    "build_date" : "2021-09-15T10:18:09.722761972Z",
    "build_snapshot" : false,
    "lucene_version" : "8.9.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}


If you enabled HTTPS redirection during the Let's Encrypt configuration, you can also test the redirection:


curl -I http://XXXXX.creolineserver.com

HTTP/1.1 301 Moved Permanently
Server: nginx/1.21.3
Date: Wed, 22 Sep 2021 15:12:31 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://XXXXX.creolineserver.com


The HTTP status code 301 and the Location header in the response indicate that the HTTPS redirection is working correctly.


The Elasticsearch server can now be accessed from your application via https:// without specifying a port.\nYou can test accessing Kibana using a browser of your choice by entering the following URL (the server name must be adjusted beforehand):

https://XXXXX.creolineserver.com/kibana



Disable Nginx Version in HTTP Responses

In the default Nginx configuration, the Nginx version is included in the Server header of every HTTP response. This behavior can be disabled via the nginx.conf file.


To do this, edit the file /etc/nginx/nginx.conf and add the parameter server_tokens off; to the http block.


user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

 log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
 '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

 access_log  /var/log/nginx/access.log  main;

 sendfile on;
    keepalive_timeout 65;
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
}


To apply the changes, the Nginx server configuration must be reloaded:


nginx -t && systemctl reload nginx


The Nginx version being used is then hidden in the HTTP responses:


curl -I https://XXXXX.creolineserver.com

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 23 Sep 2021 06:11:34 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 554
Connection: keep-alive
X-elastic-product: Elasticsearch