Skip to content
/ certnode Public

๐Ÿ” Generate Let's Encrypt certificates in Node!

License

Notifications You must be signed in to change notification settings

zbo14/certnode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

47 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

certnode

Generate Let's Encrypt certificates in Node!

Why?

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 :)

Install

npm i certnode

Usage

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.

Generate account keys

const certnode = require('certnode')
const fs = require('fs')
const https = require('https')

const client = new certnode.Client()

// Generate fresh account keys for Let's Encrypt
await client.generateAccountKeyPair()

Generate certificate for HTTPS server

const { certificate, privateKeyData } = await client.generateCertificate('<domain>', '<email>')
const server = https.createServer({ cert: certificate, key: privateKeyData })

/* register event listeners */

server.listen(443, '0.0.0.0', () => {})

Write account keys to filesytem

// Account private key is encrypted with passphrase, if provided.
await client.exportAccountKeyPair('<directory>', '[passphrase]')

Write certificate + private key to filesystem

// Certificate private key is encrypted with passphrase, if provided.
await Promise.all([
  fs.promises.writeFile('/path/to/certificate', certificate),
  certnode.writeKeyToFile('/path/to/privateKey', privateKeyData, '[passphrase]')
])

Import account keys

const anotherClient = new certnode.Client()

// If you previously exported with passphrase, provide the same passphrase.
await anotherClient.importAccountKeyPair('<directory>', '[passphrase]')

/* generate certificate with `anotherClient` */

Import certificate + private key for HTTPS server

const [certificate, privateKeyData] = await Promise.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.
const server = https.createServer({
  cert: certificate,
  key: privateKeyData,
  passphrase: '[passphrase]'
})

/* register event listeners */

server.listen(443, '0.0.0.0', () => {})

Documentation

To generate the API docs:

npm run docs

Then open ./out/index.html in your browser.

Test

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.

Linting

npm run lint

Resources

About

๐Ÿ” Generate Let's Encrypt certificates in Node!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published