Question

How to setup nginx reverse proxy for sub domain

Hello, I’m trying to setup Nginx so I can have sub domains like

www.MySite.com -> Main website (Works correctly) jenkins.MySite.com -> sub domain for Jenkins gitlab.MySite.com -> sub domain for Gitlab

I’ve tried following various tutorials and I seem to have included everything required to make this work, but still to no avail.

I’ve followed this: https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-with-ssl-as-a-reverse-proxy-for-jenkins and various other sources online.

[Nginx Server Block] I’ve edited my nginx.conf file, I’ve created a new nginx/sites-available conf file for Jenkins and symlinked it to sites-enabled.

This is my default/jenkins JENKINS_ARGS

JENKINS_ARGS="--webroot=/var/cache/jenkins/war --httpListenAddress=127.0.0.1 --httpPort=$HTTP_PORT -ajp13Port=$AJP_PORT"

This is an example of my jenkins server block in nginx

server {
    listen 80;
    return 301 https://$host$request_uri;
}

server {

    listen 443;
    server_name jenkins.MySite.com;

    #ssl_certificate           /etc/nginx/cert.crt;
    #ssl_certificate_key       /etc/nginx/cert.key;

    #ssl on;
    #ssl_session_cache  builtin:1000  shared:SSL:10m;
    #ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    #ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    #ssl_prefer_server_ciphers on;

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

    location / {

      proxy_set_header        Host $host;
      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;

      # Fix the “It appears that your reverse proxy set up is broken" error.
      proxy_pass          http://127.0.0.1:8080;
      proxy_read_timeout  90;

      proxy_redirect      http://127.0.0.1:8080 https://jenkins.MySite.com;
    }
  }

I’ve also created an A record in DigitalOcean - Network and also a CNAME

Much help would be appreciated.

Thanks

Subscribe
Share

Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

@domzyoung

No problem and yes, I would setup SSL since LetsEncrypt is indeed free and valid (i.e you won’t get errors like you would with a self-signed SSL cert).

Setting up valid, working SSL that is actually secure does require a little more work though. The first thing you’d really want to do is create your dhparam file, which can take a while and it is resource intensive.

To start, install LetsEncrypt:

sudo apt-get -y letsencrypt

Once done, shutdown NGINX using service nginx stop. We can now run LetsEncrypt to generate your SSL Certificates.

letsencrypt certonly -d jenkins.dominiczenyoung.com -d www.jenkins.dominiczenyoung.com

LetsEncrypt does not support WildCard SSL Certificates, so you can’t use:

*.dominiczenyoung.com
*.www.jenkins.dominiczenyoung.com
etc...

You’ll have to use the ones above in the command above. Once you’ve entered your e-mail and accepted the TOS, it should output a path to your certificate, key, etc. Make a note of that path, you’ll need it shortly.

Now we need to generate your dhparam file. To do that, we can create an SSL directory in /etc/nginx using:

mkdir -p /etc/nginx/ssl

Then generate the file using the command below. This can take anywhere from 5-10 minutes up to 20-30 depending on the size of your Droplet. Be patient and let it finish; you need this for your SSL configuration.

openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

Once that file has been created, the minimum configuration you really want to run with would be:

add_header                      X-Frame-Options SAMEORIGIN;
add_header                      X-Content-Type-Options nosniff;
add_header                      X-XSS-Protection "1; mode=block";

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

ssl_prefer_server_ciphers       on;
ssl_session_cache               shared:SSL:50m;
ssl_session_timeout             5m;
ssl_dhparam                     /etc/nginx/ssl/dhparam.pem;

ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

In the above, you’d change the paths to ssl_certificate and ssl_certificate_key to match those that were created by LetsEncrypt. You should only need to change yourdomain.com to:

jenkins.dominiczenyoung.com

Thus resulting in:

/etc/letsencrypt/live/jenkins.dominiczenyoung.com/

The fullchain.pem and privkey.pem won’t need to be changed as those are the same for all.

So what you’d end up with is an NGINX configuration file that looks something like this one:

server {
    listen 80;
    server_name                     jenkins.dominiczenyoung.com www.jenkins.dominiczenyoung.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name                     jenkins.dominiczenyoung.com www.jenkins.dominiczenyoung.com;

    add_header                      X-Frame-Options SAMEORIGIN;
    add_header                      X-Content-Type-Options nosniff;
    add_header                      X-XSS-Protection "1; mode=block";

    ssl_certificate                 /etc/letsencrypt/live/jenkins.dominiczenyoung.com/fullchain.pem;
    ssl_certificate_key             /etc/letsencrypt/live/jenkins.dominiczenyoung.com/privkey.pem;

    ssl_prefer_server_ciphers       on;
    ssl_session_cache               shared:SSL:50m;
    ssl_session_timeout             5m;
    ssl_dhparam                     /etc/nginx/ssl/dhparam.pem;

    ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

    access_log                      /var/log/nginx/jenkins/access.log;
    error_log                       /var/log/nginx/jenkins/error.log;

    location / {
        proxy_set_header        Host $host;
        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;
        proxy_pass              http://127.0.0.1:8080;
        proxy_read_timeout      90;
        proxy_redirect          http://127.0.0.1:8080 https://jenkins.dominiczenyoung.com;
    }
}

I’ve already configured the above server block for you, so once LetsEncrypt is ran, it should be copy, paste, restart and it should work without any issues.

@jtittle

A                 jenkins.domain.com directs to          directs to  XXX.XX.XXX.XXX   3600
CNAME      *.jenkins.dominiczenyoung.com   	is an alias of domain.com      4320
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

@domzyoung

What does the output of:

tail -20 /var/log/nginx/error.log

Show?

@jtittle Thanks for your reply.

Do I need the SSL stuff setup for this to work? at the moment I haven’t bothered for now with any of the SSL stuff for my droplet setup, that’s not to say I won’t, but I was just aiming to get it working for now.

I’ve just made the below change, with MySite obviously changed to my domain.

server {
    listen 80;
    server_name jenkins.MySite.com;

    return 301 https://$host$request_uri;
}

However it’s still saying “This site can’t be reached”. Again www.MySite.com actually works fine, but jenkins.MySite.com still doesn’t.

Is there any other logs or conf files I can show you which may help you verify if I’ve done everything correct?

@domzyoung

The issue with the SSL portion of your NGINX server block is that SSL won’t work without at least a self-signed or valid SSL Certificate. When you configure a server block to listen on port 443, a valid SSL certificate is required – without it, the connection will fail.

In Chrome, you’ll see something such as:

This site can’t provide a secure connection ERR_SSL_PROTOCOL_ERROR

If you do have a valid SSL Certificate installed, whether via LetsEncrypt, self-signed, or through a SSL provider, please post the output of:

tail -20 /var/log/nginx/error.log

What you have right now, with the commented our SSL portion of your server block essentially gets read like this (as if the commented portions don’t exist):

server {
    listen 80;
    server_name jenkins.MySite.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443;
    server_name jenkins.MySite.com;

    location / {
        ...
        ...
        ...
    }
}

One note about your first server block (listening on port 80), just a quick fix, it should look like:

server {
    listen 80;
    server_name jenkins.MySite.com;

    return 301 https://$host$request_uri;
}

i.e. it’s missing the server_name.