Setting up LetsEncrypt on a CentOS 7 NginX proxy


  • Service Provider

    So I decided to take a shot at setting up Let's Encrpyt on my NginX proxy that runs on CentOS 7. I am not sure how I want to handle the hand off between the proxy and the servers behind yet. Currently all the certificates are manually setup on both after they are generated. But that is for another day..

    Important: You must turn off CloudFlare CDN functionality (make the cloud Grey instead of Orange) if you have the SSL features of CloudFlare enabled.

    NginX is not fully supported for full automation at this time. That will be rectified soon and these directions will be outdated, but for now.

    I started with the core instructions from here and also this [support thread]( yum install python python-devel python-pip python-setuptools python-tools python-virtualenv).

    The first thing I noticed if that they tell you to just run the gitcommand. Well guess what, git is not part of CentOS 7 minimal.

    The EPEL is also required, but I believe their core script checks for that. As I already had the EPEL enabled, it did nothing else. Additionally, there are Python tools missing in the dependency chain.

    yum -y install git python-tools python-pip

    Now on to the install. I do not want this in my home directory, so i first switched over to /etc.

    cd /etc

    Then I ran their git command to pull down the code.
    git clone https://github.com/letsencrypt/letsencrypt

    Change directories, and run the setup script.
    cd letsencrypt
    ./letsencrypt-auto --help

    With Let's Encrypt now installed, it is time to generate the certs.
    Unfortunately, NginX is not currently (as of Dec 6, 2015) supported for automatic installation, though I am not sure if I will ever use the full automatic install because I rarely have a simple single vHost setup going.

    The prefered method of install for Let's Encrypt seems to be the --standalone plugin over the --webroot plugin. The webroot solution looks like the better method, but I did not test it.

    You have to stop NginX because the --standalone plugin will stand up its own temp webserver to answer the domain verification challenge.
    systemctl stop nginx

    Run Let's Encrypt to get the SSL certificates.

    Note: The first time you execute Let's Encrypt it will interactively ask you for an email address and also to accept the ToS. You can include that information in the request with --email [email protected] and --agree-tos

    ./letsencrypt-auto certonly --standalone --email [email protected] --agree-tos -d jaredbusch.com -d www.jaredbusch.com

    If you ever run this again, even for another domain on the same server, leave the email and ToS acceptance out of the script. Like this.

    ./letsencrypt-auto certonly --standalone -d jaredbusch.com -d www.jaredbusch.com

    Assuming you did everything right, you should see this.

    Updating letsencrypt and virtual environment dependencies.......
    Running with virtualenv: /root/.local/share/letsencrypt/bin/letsencrypt certonly --standalone --email [email protected] --agree-tos -d jaredbusch.com -d www.jaredbusch.com
    
    IMPORTANT NOTES:
     - Congratulations! Your certificate and chain have been saved at
       /etc/letsencrypt/live/jaredbusch.com/fullchain.pem. Your cert will
       expire on 2016-03-06. To obtain a new version of the certificate in
       the future, simply run Let's Encrypt again.
     - If like Let's Encrypt, please consider supporting our work by:
    
       Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
       Donating to EFF:                    https://eff.org/donate-le
    

    Now start NginX back up because you do not need to keep your website down while you update the vHost files.
    systemctl start nginx

    You can see in the success message, that it told you where to find the certificate chain. It always save everything in a directory named after the first passed domain to the command. Check out what it does.
    ls -l /etc/letsencrypt/live/jaredbusch.com

    total 0
    lrwxrwxrwx. 1 root root 34 Dec  7 00:29 cert.pem -> ../../archive/jaredbusch.com/cert1.pem
    lrwxrwxrwx. 1 root root 35 Dec  7 00:29 chain.pem -> ../../archive/jaredbusch.com/chain1.pem
    lrwxrwxrwx. 1 root root 39 Dec  7 00:29 fullchain.pem -> ../../archive/jaredbusch.com/fullchain1.pem
    lrwxrwxrwx. 1 root root 37 Dec  7 00:29 privkey.pem -> ../../archive/jaredbusch.com/privkey1.pem
    

    It symlinks everything so when you rerun this in 2 months to renew the certificates, you never have to edit your config files again. The renew process will create new files leaving the old ones in place.

    Now you edit your NginX server (vHost) conf files. Mine exist in /etc/nginx/conf.d/
    nano /etc/nginx/conf.d/jaredbusch.com.conf

    My existing config just used a self signed cert and these two lines.

    ssl_certificate /etc/ssl/cacert.pem;
    ssl_certificate_key /etc/ssl/privkey.pem;
    

    Those need updated to point to the new Let's Encrypt certificates. Additionally, with real certificates, I followed the other guide's suggestion and enabled a couple other SSL options.

        ssl_certificate /etc/letsencrypt/live/jaredbusch.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/jaredbusch.com/privkey.pem;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    

    Save and close nano, then test the nginx config
    nginx -t

    If it is successful, restart NginX.
    systemctl restart nginx

    Load your page up and check your certificate.
    wDzpfQF.jpg
    m7SS42N.jpg
    UBrkHyr.jpg


  • Service Provider

    I ran into an error almost immediately.
    ./letsencrypt-auto --help resulted in this.

    Complete!
    Creating virtual environment...
    Updating letsencrypt and virtual environment dependencies...../root/.local/share/letsencrypt/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
      InsecurePlatformWarning
    ./root/.local/share/letsencrypt/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
      InsecurePlatformWarning
    .
    

    Searching their website did not turnup anythin specific about this, but I did find a thread about Python 2.7 and Centos 6. Comparing the workaround for that (prior to CentOS 6 being supported again). I noticed that not all the Python pieces that the workaround noted were install on my box, python-tools and python-pip.

    I reverted my VM and then added those to the yum install for git. Now Let's Encrypt build correctly.

    [[email protected] letsencrypt]# ./letsencrypt-auto --help
    Updating letsencrypt and virtual environment dependencies.......
    Running with virtualenv: /root/.local/share/letsencrypt/bin/letsencrypt --help
    
      letsencrypt [SUBCOMMAND] [options] [-d domain] [-d domain] ...
    
    The Let's Encrypt agent can obtain and install HTTPS/TLS/SSL certificates.  By
    default, it will attempt to use a webserver both for obtaining and installing
    the cert. Major SUBCOMMANDS are:
    
      (default) run        Obtain & install a cert in your current webserver
      certonly             Obtain cert, but do not install it (aka "auth")
      install              Install a previously obtained cert in a server
      revoke               Revoke a previously obtained certificate
      rollback             Rollback server configuration changes made during install
      config_changes       Show changes made to server config during installation
      plugins              Display information about installed plugins
    
    Choice of server plugins for obtaining and installing cert:
    
      --apache          Use the Apache plugin for authentication & installation
      --standalone      Run a standalone webserver for authentication
      (nginx support is experimental, buggy, and not installed by default)
      --webroot         Place files in a server's webroot folder for authentication
    
    OR use different plugins to obtain (authenticate) the cert and then install it:
    
      --authenticator standalone --installer apache
    
    More detailed help:
    
      -h, --help [topic]    print this message, or detailed help on a topic;
    						the available topics are:
    
       all, automation, paths, security, testing, or any of the subcommands or
       plugins (certonly, install, nginx, apache, standalone, webroot, etc)
    
    [[email protected] letsencrypt]#

  • Service Provider

    If you use a Free CloudFlare account and have the SSL features enabled, you must disable them prior to starting this because CloudFlare is basically acting as a MITM and breaking that SSL validation chain.

    Prior to Let's Encrypt this was actually a really useful tool. I have almost all sites setup with CloudFlare and the SSL enabled in "Full" mode. This let my visitors get a trusted SSL and CloudFlare did not care what SSL I had on the backend as long as it was an expired certificate. For personal stuff I just used Self Signed.

    Anyway, Let's Encrypt (rightly) does not accept that when validating.

    Updating letsencrypt and virtual environment dependencies.......
    Running with virtualenv: /root/.local/share/letsencrypt/bin/letsencrypt certonly --standalone --email [email protected] --agree-tos -d jaredbusch.com -d www.jaredbusch.com
    Failed authorization procedure. jaredbusch.com (tls-sni-01): urn:acme:error:tls :: The server experienced a TLS error during DV :: Failed to connect to host for DVSNI challenge
    
    IMPORTANT NOTES:
     - The following 'urn:acme:error:tls' errors were reported by the
       server:
    
       Domains: jaredbusch.com
       Error: The server experienced a TLS error during DV
    [[email protected] letsencrypt]#

  • Service Provider

    Here is my /etc/nginx/conf.d/jaredbusch.com.conf in whole for reference.

    server {
    	client_max_body_size 40M;
    	listen 443 ssl;
    	server_name www.jaredbusch.com jaredbusch.com;
    	ssl          on;
    	ssl_certificate /etc/letsencrypt/live/jaredbusch.com/fullchain.pem;
    	ssl_certificate_key /etc/letsencrypt/live/jaredbusch.com/privkey.pem;
    	ssl_stapling on;
    	ssl_stapling_verify on;
    	add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    
    	location / {
    		proxy_set_header X-Real-IP $remote_addr;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header Host $http_host;
    		proxy_set_header X-NginX-Proxy true;
    		proxy_pass https://10.254.0.101:443;
    		proxy_redirect off;
    	}
    }
    server {
    	client_max_body_size 40M;
    	listen 80;
    	server_name www.jaredbusch.com jaredbusch.com;
    
    	location / {
    		proxy_set_header X-Real-IP $remote_addr;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header Host $http_host;
    		proxy_set_header X-NginX-Proxy true;
    		proxy_pass http://10.254.0.101:80;
    		proxy_redirect off;
    	}
    }

  • Service Provider

    Now, I just need to get these certificates shipped off to the server behind. Why? Because while I know I do not have to encrypt after the proxy, I still want it all 100% encrypted.



  • Are you still renewing by hand?



  • Any updates to this?


  • Service Provider

    @aaronstuder said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    Are you still renewing by hand?

    I am at least.



  • I'm using cron with the old letsencrypt script. I haven't migrated over to certbot yet.


  • Service Provider

    @dafyre said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    I'm using cron with the old letsencrypt script. I haven't migrated over to certbot yet.

    Same.


  • Service Provider

    @aaronstuder said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    Any updates to this?

    Use Certbot never this method. keep your life simpler.



  • @JaredBusch said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    @aaronstuder said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    Any updates to this?

    Use Certbot never this method. keep your life simpler.

    Yeah. If the old way is working, that should keep working. However, certbot is easier to use.


  • Service Provider

    @travisdh1 said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    @JaredBusch said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    @aaronstuder said in Setting up LetsEncrypt on a CentOS 7 NginX proxy:

    Any updates to this?

    Use Certbot never this method. keep your life simpler.

    Yeah. If the old way is working, that should keep working. However, certbot is easier to use.

    When my system came up for renew after certbot was out, I installed certbot and renewed that way. everything is in the same pace. nothing had to be changed in the config files.



Looks like your connection to MangoLassi was lost, please wait while we try to reconnect.