Generate Let's Encrypt certificates in Node!
I wanted to see how difficult it is to generate Let's Encrypt certificates in Node without using an external package like greenlock or exec-ing certbot in child processes.
Essentially this boils down to creating keypairs, signing and sending HTTPS requests to Let's Encrypt's API endpoints. Not a huge lift; however, certnode is pretty limited right now. Extending functionality might be a larger effort.
This was primarily a learning exercise but also an effort to create a package that hopefully makes it easy for others to generate certificates for their domains :)
npm i certnode
The example code can be found here.
Note: you must control the domain + email address you pass to client.generateCertificate(). Also, be sure to allow inbound HTTP traffic (TCP, port 80) in your firewall rules.
constcertnode=require('certnode')constfs=require('fs')consthttps=require('https')constclient=newcertnode.Client()// Generate fresh account keys for Let's Encryptawaitclient.generateAccountKeyPair()const{ certificate, privateKeyData }=awaitclient.generateCertificate('<domain>','<email>')constserver=https.createServer({cert: certificate,key: privateKeyData})/* register event listeners */server.listen(443,'0.0.0.0',()=>{})// Account private key is encrypted with passphrase, if provided.awaitclient.exportAccountKeyPair('<directory>','[passphrase]')// Certificate private key is encrypted with passphrase, if provided.awaitPromise.all([fs.promises.writeFile('/path/to/certificate',certificate),certnode.writeKeyToFile('/path/to/privateKey',privateKeyData,'[passphrase]')])constanotherClient=newcertnode.Client()// If you previously exported with passphrase, provide the same passphrase.awaitanotherClient.importAccountKeyPair('<directory>','[passphrase]')/* generate certificate with `anotherClient` */const[certificate,privateKeyData]=awaitPromise.all([fs.promises.readFile('/path/to/certificate','utf8'),fs.promises.readFile('/path/to/privateKey','utf8')])// If you previously exported with passphrase, provide the same passphrase.constserver=https.createServer({cert: certificate,key: privateKeyData,passphrase: '[passphrase]'})/* register event listeners */server.listen(443,'0.0.0.0',()=>{})To generate the API docs:
npm run docs
Then open ./out/index.html in your browser.
sudo domain=<domain> npm test
The test suite sends HTTPS requests to Let's Encrypt (staging environment) and generates certificates.
Therefore, tests must run from a domain you control, presumably on a VPS. Since certnode attains certificates through HTTP validation, it must run as root so it can listen on port 80. Make sure firewall rules allow inbound HTTP traffic.
Note: if you run tests several times in quick succession, you may be rate-limited by Let's Encrypt.
npm run lint