Jenkins with NGINX - Reverse proxy with https

Vijayakumar
7 min readOct 18, 2018

--

Thats how scalable NGINX can get!!!

The above image doesn’t provide justice to the actual scalability of NGINX. There are a lot of products and licensed versions of NGINX such as NGINX-plus but here we are going to deal with the open sourced version— NGINX

A BREIF INTRO

I started exploring NGINX as a possiblity of using it as a reverse proxy mechanism for my angular app but it seems that this powerful software has plenty to offer , like caching, security, scalability and so on …

Most of the demanding websites like Netflix use NGINX as a reverse proxy at its core for scalability and security

WHAT IS REVERSE PROXY

Enough of its eulogy. So what exactly is reverse proxing??. The diagram speaks for itself

A very basic proxying

Everyone is well aware that proxying is a pretty wide known terminology, and. reverse proxying is just the inverse of it. Where proxy, the shorthand version of forward proxy, is used at the client end to mask the outgoing request to access the resources at the server, reverse proxy is used at the server end to handle all the incoming requests and manage all the responses from the server. This empowers the server admins to discard requests from any of the clients that deemed suspicious. It also provides the possibilities of load balancing at the proxy end. More on that later !!!

INSTALL NGINX

You can always visit the site — http://nginx.org/en/download.html to download the latest version of nginx irrespective of the platform you use.

If you are a mac user, using the package manager homebrew has a lot of advantages rather than just downloading the .gz or .dmg versions from the site.

$ brew install nginx...............
$ nginx -v
nginx version: nginx/1.15.5. ## version at the time of writing

To start and stop nginx, you can either use homebrew which ultimately modifies the launctl to start and stop the nginx on system reboot

For manually starting and stopping nginx when required

$ sudo nginx ##starts the nginx$ sudo nginx -s stop ##stops the nginx server

NGINX —The defaults

By default NGINX uses directives to define the configurations needed for a specific module. For example — ssl is not enabled by default, we have to manually enable it and so is the Reverse proxy module. And how do we do that ?? — by instructing the NGINX via directives.

These are the rudimentary files that will be used by nginx —

Config files @ /usr/local/etc/nginx — config.xml

Log files @ /usr/local/var/log/nginx — access.log and error.log ( logs files can be customized in the config.xml using the appropriate directives)

Root folder @ /usr/local/var/www (root folder again can be modified to access the desired location using the directive in config.xml)

There is great documentation of all the configurable directives and embedded params provided in the nginx site — http://nginx.org/en/docs/. I highly recommed to go through it incase of any issues with how to use directives

CERTIFICATES FOR HTTPS

To run jenkins with SSL/TCP enbaled we needed to get the certs signed by CAs and make sure that our instance of jenkins point to the same. Since CAs issue certificate chains with the signed root certificate , the browsers (atleast Chromium looks for the trust of the issuer) trust the certs

But for the purpose of this testing, we are going to make use of self signed certificates and which can be generated using openssl.

OPENSSL — Self signed CERTS

Create the cert and the private key in any specific location

Just incase if you are unaware of generating the certs, here it is

Step 1: Install openssl

$ brew install openssl
$ openssl version

LibreSSL 2.2.7 # the version that I installed

Steps 2: Generate key — RSA — Cert

$  openssl req -newkey rsa:2048 -nodes -keyout nginxkey.pem -x509 -days 365 -out nginxCert.pem
Generating a 2048 bit RSA private key
...................+++
..........................................................................+++
writing new private key to 'nginxkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:XX
State or Province Name (full name) []:XX
Locality Name (eg, city) []:XX
Organization Name (eg, company) []:XX
Organizational Unit Name (eg, section) []:XX
Common Name (eg, fully qualified host name) []:XX
Email Address []:XXX

Keytool utility that ships with the jdk installation can also be used to generate the certs

$ keytool -genkeypair -alias adtechAlias -keyalg RSA -keystore adtechKeyStore.jks -keysize 2048# to view the details in the store$ keytool -list -v -keystore adtechKeyStore.jks
Enter keystore password: #password for keystore

Install JENKINS

Now we use homebrew again to install JENKINS in mac

$brew install jenkins

The default home folder will be @ /Users/<your user_name>/.jenkins which will be you default jenkins home

The war files will be located @ /usr/local/Cellar/jenkins/<version>/libexec

The admin password can be found @ $JENKINS_HOME/secrets/intialAdminpassword

Run JENKINS in HTTPS mode

Go to the location of the jenkins.war file and run the following command

$ java -jar jenkins.war --httpPort=-1 --httpsPort=1443 --httpsCertificate=path/to/cert --httpsPrivateKey=path/to/privatekey

Note: — httpPort =1 tells the kernel to disregard any http requests and the customized port — httpsPort=1443 tells the kernel to accept only https calls at 1443. One caveat is that all ports below 1024 are reserved for access by root user of local. So always specify a port greater than that. And for any reason if you feel that you wanted to run jenkins behind the customized version of tomcat instead of its default winstone server, I leave it to your choice. But let us not get there and make it more complex

If you want jenkins to create it own self signed certificate if not for the above certs you created, then just run the above command without the httpsCertificate and httpsPrivateKey

$ java -jar jenkins.war --httpPort=-1 --httpsPort=1443

This makes jenkins to create its own self signed certifcate. Now you can access jenkins @ https://localhost:1443. Please make sure to note down the jenkins admin password in the logs while running the jenkins for the first time

You can stop the running instance of the jenkins at any time by just typing Command+C. To stop a service registered in the launchctl use the following command

$ sudo launchctl stop /Library/LaunchDaemons/org.jenkins-ci.plist

To start it again, use

$ sudo launchctl start /Library/LaunchDaemons/org.jenkins-ci.plist

DNS Host resolution

Every system tries to map a given DNS to an IP address of a node which servers a client request. When we specify that we are trying to map to a certain ***.com DNS , then our systems looks up the hosts file intially to find the desired IP mapping and if not found searches the node in the internet to map to. Now if we would like to map our running instance of jenkins to our very own DNS- let’s say in this case myjenkins.com then we should have a record in our hosts file. This hosts file is present in /private/etc . Add the following record

127.0.0.1 myjenkins.com

We are basically asking the domain — myjenkins.com to be mapped to the IP— 127.0.0.1 which is the localhost/ host machine

NGINX -Configuration

Now back to the nginx. We have already installed it in our system and we have a running instance of it.

Step 1: Initial Configuration

Modify the configuration file (nginx.conf )

Default configuration with the port changes

Now if you execute http://localhost:9091 you will end up with a welcome page

Welcome page

Note: Make sure to run the reloaded configuration of nginx every time you modify the configuration using the following command

$ sudo nginx -s reload

Step 2: Enable HTTPS in nginx

You can make use of the below configuration to enable HTTPS in nginx. In case of a self signed cert, it requires both a private key and a cert in .PEM format to refer to when initial TCP/SSL handshake happens

Nginx with https

Accessing https://localhost:1003 will serve the welcome page of nginx in a secure link

Step 3: Configure a proxy pass

Now create a proxy for jenkins to route every incoming request and make sure that every response from the jenkins pass through nginx by declaring a proxy pass to the DNS configured ( it can also be done with just the localhost IP)

nginx.conf with reverse proxy

Now access https://myjenkins.com and you would have configured your jenkins instance running behind nginx

Shoot up with any questions regarding the setup and I will try to answer the best way possible. Thank you

--

--