How To: Let's Encrypt and NodeBB



  • Let's Encrypt and NodeBB

    Summary

    NodeBB is a special beast. One that takes careful grooming and maintenance. Ah, gone are the golden days of LAMP. That glorious "P", so easy to use but oh so poor on performance. With Node.js and socket.io living behind your webserver you no longer have the easy liberty of throwing down files and opening directory access any where you would like. What's that? You have to shutdown your NodeBB just to renew your Let's Encrypt SSL certificates? You are using SSL right? Shame, shame if you are not.

    Take notice! You no longer need to shutdown your webserver and NodeBB just to renew those Let's Encrypt certificates if you make a simple change to your webserver configuration.

    Back story

    Let's Encrypt is a free SSL certificate authority. You run their software on your server that authenticates with their master control. The key is proving that you have rights to the domain you are requesting a certificate for. Their software is a webserver so you can't already be running one on port 80. Theirs needs to bind to that port. To run their software, to renew my certificate, I have had to shutdown my webserver (which makes my NodeBB forum unavailable). It doesn't take long but I was annoyed that my NodeBB forum would have to be offline during that time. I knew there must be a solution to this problem and there is in their "webroot" option.

    The webroot flag keeps their software from needing to run as a webserver and just places special authentication files in your already existing webserver's html path. That is all fine-and-dandy for a typical LAMP setup but doesn't behave as well with Node.js, socket.io and NodeBB. It can behave though if you tell your webserver to exclude the super secret Let's Encrypt webroot path from going to NodeBB and point off somewhere else.

    Webserver

    We must tell the webserver that the .well-known/acme-challenge directory is not to be proxied off to socket.io like it needs to be for NodeBB.

    Nginx

    These configurations need to be in the unencrypted (port 80) section of your webserver configuration.

    Change yourdomainhere.com with your actual domain name.

    server {
        listen       80;
        server_name  yourdomainhere.com;
    
        root   /var/www/yourdomainhere.com/html;
    ...
    

    Add a location block for the Let's Encrypt directory

    location /.well-known/acme-challenge/  {
        try_files $uri =404;
    }
    

    Bonus: If you want to only serve https traffic for your NodeBB forum make your root location block something like this

    location / {
        rewrite ^(.*) https://yourdomainhere.com$1 permanent;
    }
    

    Reload Nginx for the changes to take affect.

    sudo systemctl reload nginx
    

    Apache (and others)

    You will need to research how to setup the proper exclusion of the .well-known/acme-challenge directory from being proxied to socket.io.

    Let's Encrypt

    Linux

    When it is time to renew your certificate (or create your certificate) you would run the following command.

    Change yourdomainhere.com with your actual domain name.

    sudo ./letsencrypt-auto certonly --webroot -w /var/www/yourdomainhere.com/html -d yourdomainhere.com -d www.yourdomainhere.com
    
    • certonly means to only have the certificates generated and do not try to modify any webserver (Nginx) configuration files. That task is left to the student (you).
    • --webroot tells Let's Encrypt to not run as a webserver and not to bind to port 80
    • -w points to the actual path on disk that Nginx can serve files from. This is the place that the .well-known/acme-challenge directory will be created in and inside of that directory Let's Encrypt will place temporary authorization files
    • -d the domain name that this certificate will authenticate for. Add additional -d flags for each of the names you may have.

    Windows (and others)

    You will need to research the syntax to execute the letsencrypt-auto command but the flags should be very similar to the Linux ones shown above.

    Caveats

    Symbolic Links

    It has been reported that symbolic links do not work well with the Let's Encrypt software. Therefore please avoid attempting to sym link the .well-known/acme-challenge directory to another location on your file system.

    Conclusion

    What I have left out is the initial configuration of your webserver to accept SSL connections. There are numerous documents online to help with that portion. If it is done correctly for Let's Encrypt the certificate path will point to a live directory. Renewing the certificates only updates the files in the live directory and your webserver configuration is not touched.

    With this configuration I am able to run the command to update my certificates without having to shutdown my webserver thus making NodeBB unreachable from my webserver proxy.

    Contact me https://community.nodebb.org/user/rod#


  • @rod Details like this is helpful for someone like me. Will have to give this a try. Thanks!



  • I already covered this in my "High performance stack" tutorial. Still a nice tutorial.



  • @AOKP I just looked at your high performance tutorial. Definitely a lot of information. Possibly too much all at once. I think people may find this succinct post just related to Let's Encrypt easier to digest.



  • Edited to include a warning about using a sym link to the .well-known/acme-challenge directory.


  • Community Rep

    @rod, is the root you specify in the nginx config arbitrary, an empty directory path that actually exists, or does it need to be the actual root of the public folder? I have a non-standard configuration where I have a dedicated user for running NodeBB, and the actual root location is in the home folder of that user (which is also non-standard, in the /usr/share/nginx dir)

    EDIT: nvm, I forgot to specify the folder to save the file in with the -w flag

    Thanks!


  • Admin

    @Bri root /var/www/yourdomainhere.com/html; this one?

    It's not used by NodeBB, only by Let's Encrypt.

    It will try to access the file located in /.well-known/acme-challenge/, and that is relative to the root as defined.

    For my Let's Encrypt setup, I instead use:

      location "/.well-known/acme-challenge" {
          root /usr/share/nginx/html;
      }
    

    ... as that folder is served by nginx already, so less configuration 😄 (I modify my ./letsencrypt-auto command according as well, of course)


  • Community Rep

    Cool, didn't know that you could put the "root" inside the location block, thanks!



  • @rod hi rod, im doing exactly what u r saying but i have a problem is where should i put the verification files? another saying is where to put these two files below to upload into
    .well-known/acme-challenge/ directory?

    nOmtkseci4NqOwrx9OYnmtQaoNsPrqq7_JG3Kf4iVd8
    NJpedX-UNHPAVRaur_ZNyiSjwpqrudSPuX2eL8PY010

    thanks.



  • I'm using a Lets Encrypt based service at https://www.sslforfree.com which allows DNS authentication instead of the two file uploads. Too much hassle to get that directory working .. 🐇


  • Community Rep

    @01 You tell nginx where to look for the files.

    server {
        listen       80;
        server_name  yourdomainhere.com;
        ...
    
        location "/.well-known/acme-challenge" {
            root /usr/share/nginx/html;
        }
    }
    

    This would mean the files you create are:

    /usr/share/nginx/html/nOmtkseci4NqOwrx9OYnmtQaoNsPrqq7_JG3Kf4iVd8
    /usr/share/nginx/html/NJpedX-UNHPAVRaur_ZNyiSjwpqrudSPuX2eL8PY010



  • @yariplus said in How To: Let's Encrypt and NodeBB:

    @01 You tell nginx where to look for the files.

    server {
        listen       80;
        server_name  yourdomainhere.com;
        ...
    
        location "/.well-known/acme-challenge" {
            root /usr/share/nginx/html;
        }
    }
    

    This would mean the files you create are:

    /usr/share/nginx/html/nOmtkseci4NqOwrx9OYnmtQaoNsPrqq7_JG3Kf4iVd8
    /usr/share/nginx/html/NJpedX-UNHPAVRaur_ZNyiSjwpqrudSPuX2eL8PY010

    Thank you @yariplus, I have tried to reverse proxy these files over but didn't work. So I found a very easy way to do it.
    I downloaded Caddy which is a tiny open source server, and verified the files use the caddy server. Everyone use LE ssl on nodebb should do it this way, much easier.

    Now I'm encountering a new problem, I tried to setup the certificates for my nodebb but it doesn't work.

    This is my nginx config

    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        #gzip  on;
    
    server {
        listen 80;
    
        server_name mydomain.com;
    
        location / {
            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_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
    
            proxy_pass http://127.0.0.1:4567;
            proxy_redirect off;
    
            # Socket.IO Support
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    		
    		
        }	
    }
    
    
    
    
    server {
        # listen on ssl, deliver with speedy if possible
        listen 443 ssl http2;
    
        server_name mydomain.com;
    
        # change these paths!
    
        ssl_certificate /cert/bundle.crt;
        ssl_certificate_key /cert/mydomain.key;
    
        # enables all versions of TLS, but not SSLv2 or 3 which are weak and now deprecated.
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    
        # disables all weak ciphers
        ssl_ciphers 'AES128+EECDH:AES128+EDH';
    
        ssl_prefer_server_ciphers on;
    
        location / {
            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_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
    
            proxy_pass http://127.0.0.1:4567/; 
            proxy_redirect off;
    
            # Socket.IO Support
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    
    }
    

    nodebb config

    {
        "url": "https://mydomain.com",
        "secret": "************************",
        "database": "mongo",
        "mongo": {
            "host": "127.0.0.1",
            "port": "*****",
            "username": "****",
            "password": "*****",
            "database": "****",
            "uri": ""
        },
        "port": "4567"
    }
    

    Any idea why it doesn't work?


  • Global Moderator

    @01 it's not "much easier", it's just wrong. If you don't use nginx to do it, you'll not be able to do automatic renewal correctly.

    Is nginx running? It doesn't look like you actually modified your nginx config to include the static serving for acme challenge. Have you verified that the nginx config is valid?



  • @PitaJ said in How To: Let's Encrypt and NodeBB:

    @01 it's not "much easier", it's just wrong. If you don't use nginx to do it, you'll not be able to do automatic renewal correctly.

    Is nginx running? It doesn't look like you actually modified your nginx config to include the static serving for acme challenge. Have you verified that the nginx config is valid?

    @PitaJ Sorry for the confusion, these two configs are for trying to setup ssl certificates on my nodebb, I have already verified with the acme challenge with the static server. I have got the ssl certificates already with the static server, with nginx I just don't know how to get it to work. So I gave up.

    Im trying to get ssl work on my nodebb and I've been search everywhere but still can't get it to work, any suggestions? I think this nginx config should be valid, because nginx runs with this cinfg file. if there are errors in the config normally nginx wont run at all.

    I got my certificates issued from this website https://zerossl.com/, to renew the certificates they said only require the csr file, so I have to manually renew it anyway. I hosted my nodebb on windows 10 so it's different to many of the docs and so hard to get everything to work.


  • Community Rep

    @01 What is the error you are receiving when you visit your site?

    If you can access your site, but it says the connection is insecure, then part of your certificate chain is missing or invalid.


 

| |