npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@small-tech/auto-encrypt

v6.2.0

Published

Automatically provisions and renews Let’s Encrypt TLS certificates on Node.js https servers (including Kitten, Polka, Express.js, etc.)

Downloads

1,542

Readme

Auto Encrypt

Automatically provisions and renews Let’s Encrypt TLS certificates on Node.js https servers. As used in @small-tech/https and Kitten.

Implements the subset of RFC 8555 – Automatic Certificate Management Environment (ACME) – necessary for a client to support TLS certificate provisioning from Let’s Encrypt using HTTP-01 challenges.

One third-party dependency (temporal-polyfill).

How it works

Let’s Encrypt TLS certificates are automatically provisioned for you before your server starts.

Auto Encrypt uses the new Let’s Encrypt shortlived profile exclusively, which means certificates are valid for (and renewed before) 160 hours. This should occur at around the 80 hour mark of the certificate’s lifespan, in accordance with data returned by ACME Renewal Information (ARI).

Auto Encrypt also implements automatic support for obtaining certificates on IPv4 and IPv6 addresses to enable the use of Web Numbers on the Small Web.

When not provisioning certificates, Auto Encrypt also forwards HTTP calls to HTTPS on your server.

Compatibility

Node.js 24.19.0+ on Linux and macOS.

All tests pass on Node.js LTS (version 24).

💡 The module was tested to run on Windows 10 & 11 but it is no longer supported on Windows as Microsoft is complicit in Israel’s genocide of the Palestinian people and Small Technology Foundation stands in solidarity with the Boycott, Divestment, and Sanctions (BDS) movement. Windows is an ad-infested and surveillance-ridden dumpster fire of an operating system and, alongside supporting genocide, you are putting both yourself and others at risk by using it.

🇵🇸 To support families facing genocide in Gaza, consider donating to them via Gaza Verified.

Installation

npm i @small-tech/auto-encrypt

Usage

Instructions

  1. Import the module:

    import AutoEncrypt from '@small-tech/auto-encrypt'
  2. Create your server:

    // const server = https.createServer(…) becomes
    const server = await AutoEncrypt.https.createServer(…)

    💡 Auto Encrypt supports one server per Node process. If you call createServer() again, any arguments you pass will be ignored and your will get the same server back. To create another server in the same process (e.g., when testing), call await server.close() first (see below) and then create the new server.

  3. When done, close your server:

    await server.close()
    console.info ('The server is now closed.')

Example

The following code creates an HTTPS server running on port 443 that automatically provisions and renews TLS certificates from Let’s Encrypt for the domains <hostname>.

import AutoEncrypt from '@small-tech/auto-encrypt'

const server = await AutoEncrypt.https.createServer((_request, response) => {
  response.end('Hello, world')
})

await server.listen()

const domain = os.hostname()
console.info(`Auto-encrypted HTTPS server is running at ${domain}.`)

try {
  const response = await fetch(`https://${domain}/`)
  const responseText = await response.text()
  console.info('Server says:', responseText)
} catch (error) {
  console.error(error)
}

await server.close()
console.info ('The server is now closed.')

Note that on Linux, ports 80 and 443 require special privileges. Please see A note on Linux and the security farce that is “privileged ports”. If you just need a Small Web server that handles all that and more for you (or to see how to implement privilege escalation seamlessly in your own servers, see Kitten).

Configuration

You can customise the default configuration by adding Auto Encrypt-specific options to the options object you pass to the Node https server.

You can specify the domains you want the certificate to support, whether the Let’s Encrypt staging server or a local Pebble server should be used instead of the default production server (useful during development and testing), and to specify a custom settings path for your Let’s Encrypt account and certificate information to be stored in.

You can also set the ipv4 flag to true to make Auto Encrypt auto-detect your external IPv4 address (using https://ip.small-web.org/) and provision a certificate for it.

Similarly, you can set the ipv6 flag to true to make Auto Encrypt auto-detect stable IPv6 addresses on your machine (this is done locally) and provision certificates for them.

If you pass ipOnly: true, then certificates will only be provisioned for IP addresses. This turns off the automatic provisioning of certificates for the machine’s hostname and overrides any domains you may have passed in the domains array.

(Auto Encrypt uses Node Pebble to enable testing with a local Pebble server from Node.js.)

Example

import AutoEncrypt from '@small-tech/auto-encrypt'

const options = {
  // Regular HTTPS server and TLS server options, if any, go here.

  // Optional Auto Encrypt options:
  ipv4: true,
  ipOnly: true,
  server: AutoEncrypt.server.STAGING,
  settingsPath: '/custom/settings/path'
}

// Pass the options object to https.createServer()
const server = await AutoEncrypt.https.createServer(options, listener)

// …

Default options

Here is the full list of Auto Encrypt options (all optional) and their defaults:

  • domains: the hostname of the current computer and the www subdomain at that hostname.
  • server: it will use the production server (which has rate limits). Valid values are AutoEncrypt.server.(PEBBLE|STAGING|PRODUCTION).
  • settingsPath: ~/.small-tech.org/auto-encrypt/
  • ipv4: true/false – whether or not to automatically detect external IPv4 address and add it to the TLS certificate being provisioned.
  • ipv6: true/false – whether or not to automatically detect stable IPv6 addresses and add them to the TLS certificate being provisioned.
  • ipOnly: When true, the machines hostname is not added to the TLS certificate and neither are the domains passed in the domains array, if any.

Making a graceful exit

When you’re ready to exit your app, call await server.close(). Auto Encrypt then does its housekeeping: it shuts down the HTTP server that answers Let’s Encrypt challenges and performs HTTP to HTTPS redirections, and it stops checking for certificate renewal.

Auto Encrypt does not hold your app open. Its renewal check runs on an unreferenced timer, so it never keeps the process alive on its own. If renewal is the only thing your app has left to do, and you want it to keep running, hold the event loop open yourself.

Developer documentation

If you want to help improve Auto Encrypt or better understand how it is structured and operates, please see the developer documentation.

Express.js example

const express = require('express')
import AutoEncrypt from '@small-tech/auto-encrypt'

const app = express()
app.get('/', (request, response) => {
  response.end('Hello, world!')
})

const myDomain = 'dev.ar.al'
const server = await AutoEncrypt.https.createServer(
  { domains: [myDomain] },
  app
)

await server.listen()
console.log(`Auto-encrypted Express server is running at https://${myDomain}`)

// Later…
await server.close()
console.info ('The server is now closed.')

Like this? Fund us!

Small Technology Foundation is a tiny, independent not-for-profit.

We exist in part thanks to patronage by people like you. If you share our vision and want to support our work, please become a patron or donate to us today and help us continue to exist.

Audience

This is small technology.

If you’re evaluating this for a “startup” or an enterprise, let us save you some time: this is not the right tool for you. This tool is for individual developers to build personal web sites and apps for themselves and for others in a non-colonial manner that respects the human rights of the people who use them.

Client details

Auto Encrypt does one thing and one thing well: it automatically provisions a Let’s Encrypt TLS certificate for your Node.js https servers using the HTTP-01 challenge method when your server is first hit from its hostname, and automatically renews your certificate thereafter. When not provisioning certificates, it forwards any HTTP requests that your machine gets to HTTPS.

Auto Encrypt does not and will not:

  • Implement wildcard certificates. For most small tech needs (personal web sites and web apps), you will likely need no more than two domains (the root domain and, due to historic and conventional reasons, the www subdomain). You will definitely not need more than the 100 domains that are supported per certificate. If you do, chances are you are looking to use Auto Encrypt in a startup or corporate setting, which is not what its for.

  • Implement DNS-01 or any other methods that cannot be fully automated.

Terms of service

Using Auto Encrypt agrees to the Let’s Encrypt Subscriber Agreement on your behalf, as every unattended ACME client must. There is nobody to ask at the moment an account is created, so Auto Encrypt answers for you.

The agreement that applies is the one the ACME server names in its directory. Directory exposes it as termsOfServiceUrl.

Staging and production server behaviour and rate limits

By default, Auto Encrypt uses Let’s Encrypt’s production environment. This is most likely what you want as it means your HTTPS server will Just Work™, i.e., provision its TLS certificate automatically before it starts and from thereon automatically renew the certificate at the time ARI tells it to (around the 80 hour mark of the certificate’s 160 hour lifespan).

However, be aware that the production server has rate limits.

Auto Encrypt makes one provisioning attempt and does not retry a failed one. Every alternative to trying again – a different address, a different machine, telling someone – is yours and not a library’s. createServer() rejects, and AutoEncrypt.provisioningFailure(error) tells you which of four kinds of failure you have.

let server

try {
  server = await AutoEncrypt.https.createServer(…)
} catch (error) {
  const { kind, retryAfter } = AutoEncrypt.provisioningFailure(error)
  console.error(`Could not provision a certificate (${kind}).`)
  if (retryAfter !== null) { console.info(`Let's Encrypt asked us to wait ${retryAfter}ms.`) }
  process.exit(1)
}

await server.listen()

| Kind | What happened | What to do | | --- | --- | --- | | transient | Let’s Encrypt failed, was unreachable or had not decided yet, or the lookup of your IPv4 address did not give one | Try the same name or address again. New orders refill at one every 36 seconds | | unreachable | Let’s Encrypt tried to validate your name or address and did not find your server at it | Check DNS and reachability first. Trying again inside 12 minutes spends the five-an-hour authorisation failure budget for that name or address | | rateLimited | Let’s Encrypt refused you under a limit | Read retryAfter where it is set. A wait measured in hours means a different name or address is the only fix | | permanent | A configuration, account or programming error | Trying again never helps. Tell someone |

The result also has retryAfter, the wait Let’s Encrypt asked for in milliseconds or null where it asked for none, and problemType and detail, taken from the ACME problem document where there was one.

If you have no orchestrator above you – you’re running Kitten on your own machine, say – let a process supervisor restart the process when it fails. That covers every other startup failure too.

For testing, Auto Encrypt provides seamless support for using the included local Pebble server or the Let’s Encrypt staging server.

If you do use the staging environment, be aware that browsers will reject the staging certificates unless you trust the Fake LE Root X1 certificate. If testing with an external https client written in Node, you can add the fake root certificate to your trust store temporarily, using the NODE_EXTRA_CA_CERTS environment variable or setting the ca options property when creating your https server. (Note that if you’re testing with the staging or Pebble server from the same process that Auto Encrypt is running in, Auto Encrypt automatically does this for you by adding the necessary CA certificates to Node’s trust store for the current process.)

Needless to say, do not add the fake certificate root to the same trust store you use for your everyday browsing.

Related projects

From lower-level to higher-level:

Auto Encrypt Localhost

Automatically provisions and installs locally-trusted TLS certificates for Node.js https servers in 100% JavaScript (without any native dependencies like mkcert and certutil).

HTTPS

Drop-in replace for the standard Node.js HTTPS module replacement that automatically handles TLS certificate provisioning and renewal both at localhost (via Auto Encrypt Localhost) and at hostname (via Auto Encrypt).

Kitten

  • Site: https://kitten.small-web.org
  • Source: https://codeberg.org/kitten/app

A 💕 Small Web development kit.

Tests and coverage

This project has 100% test coverage of lines, branches and functions, and the coverage script fails below that.

To see the current state of code coverage, run npm run coverage.

For more details, please see the developer documentation.

A note on Linux and the security farce that is “privileged ports”

Linux has an outdated feature dating from the mainframe days that requires a process that wants to bind to ports < 1024 to have elevated privileges. While this was a security feature in the days of dumb terminals, today it is a security anti-feature. (macOS has dropped this requirement as of macOS Mojave.)

On modern Linux systems, you can disable privileged ports like this:

sudo sysctl -w net.ipv4.ip_unprivileged_port_start=0

Or, if you want to cling to ancient historic relics like a conservative to a racist statue, ensure your Node process has the right to bind to so-called “privileged” ports by issuing the following command before use:

sudo setcap cap_net_bind_service=+ep $(which node)

If you are wrapping your Node app into an executable binary using a module like Nexe, you will have to ensure that every build of your app has that capability set. For an example of how we do this in Site.js, see this listing.

Technical definition

Implements the subset of RFC 8555 – Automatic Certificate Management Environment (ACME) – necessary for a Node.js https server to provision TLS certificates from Let’s Encrypt using the HTTP-01 challenge before the server starts, and to renew them thereafter using ACME Renewal Information (ARI).

A note on coding conventions

The code uses TC39 class fields with the following naming conventions for private fields:

#property     // safe property access (either via accessor or where property is both safe to get and set)
#_property    // unsafe  property access (should only be used in accessors)

(Documenting these here as private class fields – ‘hashnames’ – are relatively new as of this writing and may not be familiar to some. The use of the underscore to differentiate direct property access from mediated access via an accessor is a project convention.)

Like this? Fund us!

Small Technology Foundation is a tiny, independent not-for-profit.

We exist in part thanks to patronage by people like you. If you share our vision and want to support our work, please become a patron or donate to us today and help us continue to exist.

Copyright

© 2020-present Aral Balkan, Small Technology Foundation.

Let’s Encrypt is a trademark of the Internet Security Research Group (ISRG). All rights reserved. Node.js is a trademark of Joyent, Inc. and is used with its permission. We are not endorsed by or affiliated with Joyent or ISRG.

License

AGPL version 3.0 or later.