Jenkins with NGINX - Reverse proxy with https
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
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 onlyhttps
calls at1443.
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 )
Now if you execute http://localhost:9091 you will end up with a 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
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)
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