The post Using NGINX as an Atlassian JIRA Reverse Proxy appeared first on Justin Silver.
]]>I use JIRA in a cloud infrastructure where it’s obviously desirable to serve the contents over SSL, therefore I set up an NGINX as a JIRA reverse proxy for unencrypted requests to the JIRA backend service and handle the SSL on the front end with Let’s Encrypt. We need to let JIRA know that we are proxying it over HTTPS however by setting some values in server.xml first.
Notice that my Let’s Encrypt SSL certificates are in the /etc/letsencrypt/live/jira.doublesharp.com directory, but yours will be specific to the hostname you create them for. The certs are created via the letsencrypt command and use Nginx to process the validation request. Once created the generated PEM files can be used in your Nginx config. Note that you will need to comment out this line in the SSL config if they don’t yet exist, start Nginx to create the certs, uncomment the lines to enable SSL, and then restart Nginx once again (whew!).
Configure JIRA to add proxyName
, proxyPort
, scheme
, and secure
parameters to the Tomcat Connector in server.xml
.
<Connector port="8081" maxThreads="150" minSpareThreads="25" connectionTimeout="20000" enableLookups="false" maxHttpHeaderSize="8192" protocol="HTTP/1.1" useBodyEncodingForURI="true" redirectPort="8443" acceptCount="100" disableUploadTimeout="true" bindOnInit="false" proxyName="jira.doublesharp.com" proxyPort="443" scheme="https" secure="true" />
Don’t forget to copy the database driver to $JIRA_INSTALL/lib
.
Note use of “jira.doublesharp.com” in config and change as needed. This configuration uses a subdomain specific certificate from Let’s Encrypt, but you could also use a Wildcard Certificate for your JIRA reverse proxy setup as well which can help to consolidate your key generation.
# Upstream JIRA server on port 8081. Use 127.0.0.1 and not localhost to force IPv4. upstream jira { server 127.0.0.1:8081 fail_timeout=0; } # listen on HTTP2/SSL server { listen 443 ssl http2; server_name jira.doublesharp.com; # ssl certs from letsencrypt ssl_certificate /etc/letsencrypt/live/jira.doublesharp.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/jira.doublesharp.com/privkey.pem; location / { # allow uploads up to 10MB client_max_body_size 10m; # set proxy headers for cloudflare/jira proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # hand the request off to jira on non-ssl proxy_pass http://jira; } } # redirect HTTP and handle let's encrypt requests server { listen 80; server_name jira.doublesharp.com; root /var/lib/jira; # handle letsencrypt domain validation location ~ /.well-known { allow all; } # send everything else to HTTPS location / { return 302 https://jira.doublesharp.com; } }
The post Using NGINX as an Atlassian JIRA Reverse Proxy appeared first on Justin Silver.
]]>The post Letsencrypt: Free SSL Certificates for NGINX appeared first on Justin Silver.
]]>I always wanted all of my sites to run over SSL, but it also didn’t seem worth the expense of buying certificates for all the domains I own. Enter Let’s Encrypt which offers free 90 day SSL certificates. This guide shows how to install and use letsencrypt to generate SSL certificates for NGINX running on CentOS 7, however it should be similar on other supported systems. A bit about Let’s Encrypt from their site:
Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. Let’s Encrypt is a service provided by the Internet Security Research Group (ISRG).
The key principles behind Let’s Encrypt are:
- Free: Anyone who owns a domain name can use Let’s Encrypt to obtain a trusted certificate at zero cost.
- Automatic: Software running on a web server can interact with Let’s Encrypt to painlessly obtain a certificate, securely configure it for use, and automatically take care of renewal.
- Secure: Let’s Encrypt will serve as a platform for advancing TLS security best practices, both on the CA side and by helping site operators properly secure their servers.
- Transparent: All certificates issued or revoked will be publicly recorded and available for anyone to inspect.
- Open: The automatic issuance and renewal protocol will be published as an open standard that others can adopt.
- Cooperative: Much like the underlying Internet protocols themselves, Let’s Encrypt is a joint effort to benefit the community, beyond the control of any one organization.
Install letsencrypt
with yum
. Next generate a strong Diffie-Hellman key – you can specify a different path but you need to change it in the Nginx server
block.
yum -y install letsencrypt openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Edit your Nginx configuration to listen on HTTP and HTTPS, and respond to Let’s Encrypt domain validation requests to /.well-known
. Go ahead and add the SSL configuration, but no keys (since they don’t exist yet).
server { # Domain validation is on port 80, SSL is served on 443. If available include "http2", otherwise remove it. listen 80 443 ssl http2; # Hostnames to listen on, you will pass each of these to letsencrypt with "-w www.example.com" server_name www.example.com; # Your document root, you will pass this path to letsencrypt with "-w /var/www/www.example.com/html/" root /var/www/www.example.com/html/; # Add SSL Keys here once they are generated # Use TLS (so don't use old version of SSL) ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_stapling on; ssl_stapling_verify on; # handle letsencrypt domain validation location ~ /.well-known { allow all; } # handle all requests... location / { } }
Validate the configuration, and when it passes reload Nginx. You can then generate an SSL key with letencrypt
using the --webroot
method. With this method you need to pass your web root with “-w /path/to/your/webroot
” and each domain you want an SSL for with “-d www.example.com -d example.com -d images.example.com
“, and so on. The first time you run Let’s Encrypt you will need to accept some terms, enter your email, etc, but subsequent runs won’t ask for this.
# validate nginx configuration nginx -t # reload nginx configuration service nginx reload # generate SSL keys letsencrypt certonly --webroot -w /var/www/www.example.com/html/ -d www.example.com
Once the keys have generated, you will need to add the certificate and key to your Nginx configuration. Edit the server
block and add the following – you may need to change the path for the letsencrypt
location on your system. Don’t move them since you will need to be able to renew them every 90 days.
# ssl certs from letsencrypt ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
Validate the Nginx configuration again, then reload the service. Once it is up, you can use curl
to validate that it is serving requests over SSL.
# validate nginx configuration nginx -t # reload nginx configuration service nginx reload # see if you can load your site over SSL curl -s https://www.example.com
If you have trouble validating your domain and get 403 errors and use SELinux, it’s possible that you will need to run the following command to give nginx permission to read the .well-known directory.
chcon -Rt httpd_sys_content_t /var/www/yoursite/.well-known
Your certificate will expire every 90 days so it’s easiest to set up a cron job to automatically check for soon to expire certificates once per day so they can be renewed – this is why we don’t want to move the certs out of the /etc/letsencrypt/live/...
directory. You may need to reload nginx as well if the certificate is updated but this should generally be transparent to clients. Edit your crontab by running crontab -e
and adding the following to check for updates at 1AM.
# LetsEncrypt Renewals 0 1 * * * letsencrypt renew >/dev/null 2>&1 && service nginx reload
Note that your certificates will only be renewed if they are close to expiration, otherwise the system will skip it and continue using the currently installed cert. You want to update at least weekly although daily is prefered to make sure you everything is up to date.
[root@www ~]# letsencrypt renew ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/justinsilver.com.conf ------------------------------------------------------------------------------- Cert not yet due for renewal The following certs are not due for renewal yet: /etc/letsencrypt/live/justinsilver.com/fullchain.pem (skipped)
The post Letsencrypt: Free SSL Certificates for NGINX appeared first on Justin Silver.
]]>The post NGINX Reverse Proxy to Legacy Website appeared first on Justin Silver.
]]>NGINX reverse proxies can be a very powerful tool for many reasons and recently came to the rescue as I was at a loss as to how to provide access to a legacy website when launching the new one. The caveat in this case was that the legacy server is, well, old. It has many hard coded values throughout including URLs and only likes to listen on particular hostnames from time to time. Since I did not write this site and do not have access to the source code (it’s a DLL on a Windows box somewhere) I had to come up up with a solution to didn’t involve modifying the code.
The first option I thought of was to just update the /etc/hosts
file (or Windows equivalent) to point the domain name to the old server IP address when needed, but this is a bit cumbersome. Comparing data between the new and old systems – presumably the main reason you would want to see the old server – is pretty much out. Faking the DNS is a no go.
An NGINX reverse proxy takes a request from a front-end NGINX server and passes it on to a back-end server in more traditional setup. In this situation the request is being made to the legacy server IP address and some special parameters are used to rewrite the domain information for redirects, cookies, and page content. We are also checking the port to determine if the request to the legacy server should be made via HTTP or HTTPS.
server { # listen on 80 and 443, ssl if the latter listen 80; listen 443 ssl; # this is the "new" url for the legacy site server_name gamma.example.com; # ssl config ssl on; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; # legacy server IP address set $legacy_ip 123.123.123.123; # proxy over which protocol? set $protocol http; if ( $server_port = 443 ){ set $protocol https; } # pass everything through the proxy location / { # proxy all requests to the legacy server proxy_pass $protocol://$legacy_ip; # set the Host header on the request proxy_set_header Host "www.example.com"; # replace redirect strings proxy_redirect http://www.example.com/ /; proxy_redirect https://www.example.com/ https://gamma.example.com/; # replace cookie domains proxy_cookie_domain 'www.example.com' 'gamma.example.com'; # replace page content sub_filter_once off; sub_filter 'www.example.com' 'gamma.example.com'; } }
The post NGINX Reverse Proxy to Legacy Website appeared first on Justin Silver.
]]>The post GoDaddy SSL Certificates on NGINX appeared first on Justin Silver.
]]>To properly install a GoDaddy SSL certificate on an NGINX install, you will need to include the gd_intermediate.crt
and gd_bundle.crt
the SSL certificate file for your server. The location of this file can be found in the *.conf
, usually in /etc/nginx/conf.d
. In my case, the SSL certificate is located at /etc/nginx/ssl/server.crt
but you should set it appropriately to CRT_FILE
for your site.
The files to include can be found on https://certs.godaddy.com/anonymous/repository.pki, or use the following script.
[www.example.com]# curl -v -I https://www.example.com * About to connect() to www.example.com port 443 (#0) * Trying 127.0.0.1... connected * Connected to www.example.com (127.0.0.1) port 443 (#0) * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS alert, Server hello (2): * SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed * Closing connection #0 curl: (60) SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed More details here: http://curl.haxx.se/docs/sslcerts.html
Append your site’s SSL certificate with the GoDaddy gd_intermediate.crt
& gd_bundle.crt
intermediate certificates. Use the following to backup/update this file based on the value set to CRT_FILE
.
cp /etc/nginx/ssl/server.crt /etc/nginx/ssl/server.crt.bak CRT_FILE=/etc/nginx/ssl/server.crt GD_HOST="https://certs.godaddy.com" GD_PATH="/anonymous/repository.pki?" GD_ACTION="actionMethod=anonymous%2Frepository.xhtml%3Arepository.streamFile%28%27%27%29" GD_CID="cid=88430" GD_REPO="$GD_HOST$GD_PATH$GD_ACTION&$GD_CID" curl "$GD_REPO&streamfilename=gd_intermediate.crt" >> $CRT_FILE curl "$GD_REPO&streamfilename=gd_bundle.crt" >> $CRT_FILE service nginx restart
After the update you should be able to fetch your site over SSL with no warnings.
[www.example.com]# curl -v -I https://www.example.com * About to connect() to www.example.com port 443 (#0) * Trying 127.0.0.1... connected * Connected to www.example.com (127.0.0.1) port 443 (#0) * successfully set certificate verify locations: * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server key exchange (12): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using DHE-RSA-AES256-SHA * Server certificate: * subject: OU=Domain Control Validated; CN=*.example.com * start date: 2014-02-03 16:44:03 GMT * expire date: 2015-03-04 22:23:49 GMT * subjectAltName: www.example.com matched * issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certificates.godaddy.com/repository; CN=Go Daddy Secure Certification Authority; serialNumber=12345678 * SSL certificate verify ok. > HEAD / HTTP/1.1 > User-Agent: curl/7.21.7 (x86_64-redhat-linux-gnu) libcurl/7.21.7 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 libssh2/1.2.7 > Host: www.example.com > Accept: */* > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Server: nginx/1.4.7 Server: nginx/1.4.7
The post GoDaddy SSL Certificates on NGINX appeared first on Justin Silver.
]]>