Unable to generating SSL certificate with LetsEncrypt certbot using node js

I have deployed my react app on firebase which comes with a pre-configured SSL certificate, but since I am making API calls to a node js server using HTTP and not HTTPS. Since I am accessing a non-secured content from within a secured site browser is blocking all my API calls.

The best and obvious choice is to load all resources via HTTPS to improve the security of my site which means generating a separate certificate signed by ‘Certificate Authority’ in this case LetsEncrypt for my node server, but I am having trouble achieving this.

Steps To Reproduce

  1. Installed Certbot
  2. Generate an SSL certificate with Certbot with the command $ certbot certonly --manual
  3. Type your domain name
  4. Go through HTTP-01 challenge process

Questions

  1. Why do I need to provide my domain in step 3 if my domain is already secured with an SSL certificate? I mean this is a web server and would receive API requests via public IP why the need for the domain?
  2. For the HTTP-01 challenge process, Certbot will ask you to create a file with an auto-generated key in your web server document root, inside directories .well-known/acme-challenge/ and this file must contain the auth key, when I do this I am getting below error:
    Some challenges have failed. To fix these errors, please make sure that your domain name was entered correctly and the DNS A/AAAA record(s) for that domain contain(s) the right IP address.

I would also be happy to receive other suggestions. Thanks for your time.

It sounds like only your website is using a certificate, not your API server. If the site makes the API queries from the client’s browser (rather than server side) and you switch the API server to HTTPS, the client’s browser must also trust the certificate hosted by that API server.

In order to get a publicly trusted cert from Let’s Encrypt for your API server, it must be accessed using a domain name rather than an IP address. Let’s Encrypt is not currently able to provide certs for IP addresses.

Hi @amo

please answer all of the following questions:


Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. https://crt.sh/?q=example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is:

I ran this command:

It produced this output:

My web server is (include version):

The operating system my web server runs on is (include version):

My hosting provider, if applicable, is:

I can login to a root shell on my machine (yes or no, or I don’t know):

I’m using a control panel to manage my site (no, or provide the name and version of the control panel):

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot):

1 Like

@JuergenAuer

My domain is: sahaypay.com
I ran below commands inside the CLI:

certbot certonly --manual

* Which asked me to type my domain and I did.
* Then I got a question asking for the IP of this machine to be publicly logged which I replied to YES.
* Then I have received my auth challenged keys
* I then created a .well-known and acme-challenge folder inside my webserver.
* I then created a file inside the acme-challenge folder with the name generated by Cerbot for the 
   HTTP-01 challenge that has only the auth key inside it.
* In order to serve that file from Koa, I enabled serving static files with the following piece of code.
    *app.use(serve(__dirname, { hidden: true }))
* Then to verify that everything is fine, I opened up my browser and navigate to To verify that 
 everything is fine, open up your browser and navigate to (http://sahaypay.com/.well-known/acme- 
 challenge/auth-file-name)
  1. The output it produced
    • I got no reponse from the browser when I visit the above url but then we I go back to the CLI and
      click ENTER to continue I get the following error:
      e[ 31mChallenge failed for domain sahaypay.come[0m
      http-01 challenge for sahaypay.com
      Cleaning up challenges
      e[31mSome challenges have failed.e[0m
      e[1m
      IMPORTANT NOTES:
      e[0m - The following errors were reported by the server:

      Domain: sahaypay.com
      Type: unauthorized
      Detail: Invalid response from
      https://sahaypay.com/.well-known/acme-challenge/Id0fBrnK0fTCHC58ZiSIOpiCTfOS7HJbheUXQRkkpPg
      [151.101.1.195]: “<!doctype html><html lang=“en”><meta
      charset=“utf-8”/><link rel=“icon” href=”/favicon.ico"/><meta
      name=“viewport” content="

      To fix these errors, please make sure that your domain name was
      entered correctly and the DNS A/AAAA record(s) for that domain
      contain(s) the right IP address.

  2. My webserver is node js v12.18.1, I am using Koa framework with below version
    • “koa”: “^2.11.0”, for static files I am using “koa-static”: “^5.0.0”
  3. The operating system that my web server runs on is Windows server 2016
  4. I can log in to a root shell on my machine - YES
  5. The version of my client is: certbot 1.7.0

Then you have done something wrong. If you can’t check the validation file with your browser, there is an error in your system you have to find and fix.

Then the validation error is expected.

1 Like

@JuergenAuer let me ask couple questions if you don’t mind.

  1. How does sending the request from browser validate that I own the domain?
  2. when calling validating your self, is it must for the web server to listen from a specific port like 80 or can I use my own custom port?

Thanks

It doesn’t. But if it doesn’t work with your browser, it can’t work that Letsencrypt checks your domain.

Please start with some basics:

Then read something about challenge types:

Short: Port 80 / 443 is possible, nothing else using http validation.

1 Like

@JuergenAuer @rmbolger everything is straight forward but this is the most confusing part that even the documentation does not clear up. Maybe I will write a blog post after I understand. so inside the challenge type documentation up there, it says and I quote

Let’s Encrypt gives a token to your ACME client, and your ACME client puts a file on your web server at http://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN>

  1. How do I make http://<MY_DOMAIN>/.well-known/acme-challenge/<TOKEN> available or reachable?
    • I understand from my webserver side I need to save and serve the static file with the auth key
      generated by Certbot, but I don’t understand how I am calling/serving this file from my domain.
      does the domain validation call come from my Firebase client app or from my domain provider or
      somewhere else?

That’s only a question of your webserver configuration.

So

  • you have to find a solution
  • nobody else knows an answer,
  • that’s not a question Letsencrypt is able to answer, because it’s configuration specific

It may be a static file saved in the real webroot, it may be a virtual file handler.

Own sample:

http://server-daten.de/.well-known/acme-challenge/_auTTDlrpaGVcbpT3zVaNa0w_v2_7YmcqygiHFCO9yw

is the file

e:\sd-web\acme-challenges\server-daten.de.challenge._auTTDlrpaGVcbpT3zVaNa0w_v2_7YmcqygiHFCO9yw.txt

so if there is a request

http://server-daten.de/.well-known/acme-challenge/_auTTDlrpaGVcbpT3zVaNa0w_v2_7YmcqygiHFCO9yw

the code checks the subdirectory, if there is a file hostname + “.” + filename + “.txt”. If no, a http status 404, if yes, the content of that file and http status 200 is sent.

So the own client saves the validation file + content in that subdirectory, adds the host + “.txt” to the filename. Other systems may store the file content in a database.

1 Like

I don’t think you understand my point clearly so here me out for a sec. I already have a domain that is pointing to my React application on firebase, but not my Node.JS server, and I am trying to use certbot to secure that domain (which is already secured anyways). certbot will make a request to my React application for the HTTP-01 challenge, and it will fail, because the challenge isn’t there.

so, I am thinking to give my Node.JS server a sub-domain name, and use that sub-domain to point to my Node.JS server. Then , I could use certbot to secure my Node.JS application.

do you think the above analogy is the correct path or not?

That’s not Certbot (the ACME-client), that’s Letsencrypt (the CA). Your domain + /.well-known/acme-challenge/random-filename is checked.

So you run Certbot on the wrong machine. (PS: Or Certbot creates the file on the wrong place or your application doesn’t handle that file content correct).

I don’t know. That’s only an application problem you have to fix.

If your domain doesn’t answer with the correct content or if you run a client on the wrong machine (so the client can’t create the correct file) or if your application under your domain name doesn’t handle file content correct, that can’t work.

But these are details of your application you know (I don’t know) and you have to fix.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.