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

@fitfak/acme

v1.0.5

Published

Advanced ACME (RFC 8555) client — HTTP-01/DNS-01/TLS-ALPN-01, multi-domain/wildcard support, EAB (GTS/ZeroSSL) with automatic GTS OAuth2 provisioning, uncached authoritative DNS pre-verification, and automatic renewal.

Readme

FITFAK ACME Engine — Advanced Edition

A pure Node.js ACME (RFC 8555) client built on @fitfak/ssl. Works with Let's Encrypt, Google Trust Services (GTS), and ZeroSSL.

What changed from the original acme.js?

| Problem (old acme.js) | Fix (new architecture) | |---|---| | Single global certs/account.json; different providers overwrote each other | accounts/<provider-host>/<name>.json — separated per provider + account | | EAB re-sent on every run even when the account already existed → "already used" on GTS | If kid is on disk, newAccount is never called again | | Only one domain, only HTTP-01 | Multi-domain (SAN), wildcard, HTTP-01 / DNS-01 / TLS-ALPN-01 | | No DNS-01 (wildcards were impossible) | DNS-01 + Cloudflare/manual driver | | DNS record could be missing and ACME was still queried (wasted rate limit) | TXT record confirmed directly against authoritative nameservers (uncached) before notifying ACME | | Public-resolver propagation checks were slow, especially for wildcards | Authoritative-server queries bypass recursive-resolver caching entirely — much faster | | GTS EAB required a manual Cloud Console visit every time | EAB minted automatically via Google's Public CA API, using an OAuth2 token or a service account | | No automatic renewal | src/renew.js (cron/daemon capable) |

Install

npm install

Quick Start — All 3 Providers, Practically

Each provider works out of the box with a single command once you have its credentials (or none, for Let's Encrypt). --provider is a shorthand for the correct ACME directory URL — you never need to type it manually.

# 1) Let's Encrypt — no account/EAB setup needed at all
node index.js --domain example.com --provider letsencrypt

# 2) Google Trust Services — EAB minted automatically from a service account
node index.js --domain example.com --provider gts \
  --gts-service-account ./gcp-service-account.json --gts-project my-gcp-project

# 3) ZeroSSL — EAB minted automatically from just an email (no API key needed)
node index.js --domain example.com --provider zerossl --zerossl-email [email protected]

All three write the resulting certificate to certs/example.com/{cert.pem,key.pem} and a renewal.json that src/renew.js uses for automatic renewal later — no extra configuration required per provider.

Usage

# Simple HTTP-01 (Let's Encrypt, requires port 80)
node index.js --domain fitfak.net

# Wildcard + apex together (dns-01 is forced automatically; manual TXT entry)
node index.js --domain fitfak.net --domain "*.fitfak.net"

# Automatic DNS-01 via Cloudflare
node index.js --domain fitfak.net --domain "*.fitfak.net" \
  --challenge dns-01 --dns-driver cloudflare --cf-token $CF_TOKEN

# Google Trust Services with a manually obtained EAB
node index.js --domain fitfak.net \
  --acme-url https://dv.acme-v02.api.pki.goog/directory \
  --eab-kid $GTS_KID --eab-hmac $GTS_HMAC

# Google Trust Services with AUTOMATIC EAB provisioning (no Cloud Console needed)
node index.js --domain fitfak.net \
  --acme-url https://dv.acme-v02.api.pki.goog/directory \
  --gts-service-account ./gcp-service-account.json --gts-project my-gcp-project

# TLS-ALPN-01 (port 443 must be free)
node index.js --domain fitfak.net --challenge tls-alpn-01

Run node index.js --help for the full option list.

Google Trust Services — Automatic EAB

Instead of manually running gcloud publicca external-account-keys create or clicking through Cloud Console every time you register a new account, this client can call Google's official Public Certificate Authority API directly:

  • --gts-oauth-token — pass an already-obtained OAuth2 access token (e.g. $(gcloud auth print-access-token)).
  • --gts-service-account <path> — pass a service-account JSON key file; the client performs the standard JWT-Bearer OAuth2 exchange itself and mints a fresh access token automatically, so nothing needs to be copied by hand.
  • --gts-project <project-id> — required with either option above.

One-time setup on the Google Cloud side (not needed per run):

gcloud services enable publicca.googleapis.com
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member=serviceAccount:YOUR_SA_EMAIL \
  --role=roles/publicca.externalAccountKeyCreator

ZeroSSL — Automatic EAB

ZeroSSL's own REST API can mint EAB credentials directly, avoiding a visit to the dashboard's "Developer" tab for every account:

  • --zerossl-access-key <key> — an API access key generated once in the ZeroSSL dashboard (Developer -> API Access Key). Since March 2022, ZeroSSL EAB credentials are reusable, so one key comfortably backs many issuances/renewals.
  • --zerossl-email <email> — simplest option, no API key at all: ties EAB directly to an email address. ZeroSSL automatically creates a free account for that address if one doesn't already exist.

Automatic Renewal

Every certificate issuance automatically creates certs/<domain>/renewal.json (contains NO secrets — DNS API tokens etc. are read from environment variables).

# Environment variables needed for certificates using Cloudflare:
export FITFAK_DNS_DRIVER=cloudflare
export FITFAK_DNS_CF_API_TOKEN=xxxx

# One-off check (renews anything with fewer than 30 days left)
node src/renew.js --once

# Long-running daemon (checks once a day)
node src/renew.js --daemon

Example crontab entry:

0 3 * * * cd /path/to/fitfak-acme && FITFAK_DNS_DRIVER=cloudflare FITFAK_DNS_CF_API_TOKEN=xxxx node src/renew.js --once >> renew.log 2>&1

Directory Layout

src/
  acme-client.js       Low-level JWS/HTTP ACME protocol layer
  acme-issue.js         Main orchestrator (account + order + challenge + finalize)
  account.js            Provider+domain scoped account persistence
  providers.js           Let's Encrypt/GTS/ZeroSSL profile detection, EAB pre-check
  gts-eab.js              Automatic GTS EAB provisioning via OAuth2/service account
  dns-verify.js           Uncached authoritative-nameserver DNS pre-verification
  dns-driver-env.js       Environment-variable driver selection for cron/daemon
  renew.js                Expiry check + automatic renewal
  challenges/
    http01.js             HTTP-01 (port 80)
    dns01.js               DNS-01 (forced for wildcards, pre-verified)
    tlsalpn01.js            TLS-ALPN-01 (port 443, RFC 8737)
  dns-drivers/
    cloudflare.js           Cloudflare API driver
    manual.js                 Manual (interactive) driver
index.js                 CLI entry point

Known Limitations

  • TLS-ALPN-01 requires port 443 to be directly reachable (not behind a reverse proxy). If a web server is already bound to 443, use DNS-01 instead.
  • Only Cloudflare has a ready-made DNS driver. For other providers (Route53, DigitalOcean, etc.), implement the same interface (setTxtRecord/removeTxtRecord) under src/dns-drivers/.
  • The authoritative-nameserver DNS pre-verification requires outbound UDP/TCP port 53 access from wherever this client runs (to reach nameservers directly) — it will not work behind a network that only permits DNS through a fixed internal resolver.