acme-bot

1.4.2 • Public • Published

ACME Bot (JS)

npm-version npm-licence

Lightning fast, lightweight Bot for Automatic Certificate Management Environment (ACME) written in JavaScript for Node.js with minimal dependencies
Based on node-acme-client.

Features

  • [x] Lightweight: no strict dependencies: easy to audit the codebase
  • [x] Multi-platform (Linux / Windows / Mac OS)
  • [x] Supports all types of challenges: http-01, dns-01, tls-alpn-01
  • [x] Single continuous http2 session when communicating to ACME server (faster comms + lower load on public infrastructure)
  • [x] Automatically updates particular cert(s) when less than 30 days left before expiration (configurable)
  • [x] Supports Systemd timer with related service for auto-update task scheduling (used by default)
  • [x] Supports Cron for auto-update task scheduling (used as fallback if systemd is not present)
  • [x] Having root access is not required, but recommended
  • [x] Supports both ECDSA (default) and RSA types of certificate and account keys
  • [x] Standalone mode that doesn't use file system (challenges saved and served directly from RAM)
  • [x] Excellent performance due to use of modern node:crypto API to access internal openssl functionality

Table of contents

Installation

Dependencies

Node.js openssl json5 (optional)
v16+ v1.1.1+ v2+

Install from package manager

> npm install -g acme-bot --no-optional
  - OR -
> yarn add global acme-bot --ignore-optional

Install using script (into a current directory)

#!/bin/sh
wget https://git.serenity-island.net/sie-foss/acme-bot/archive/master.tar.gz -O acme-bot.tar.gz
tar -xaf acme-bot.tar.gz
chmod u+x acme-bot/acme-bot.js
ln -rs acme-bot/acme-bot.js /usr/local/bin/acme-bot # (optional)

Quick start (standalone mode)

  1. Add your domain and subdomains (if any)
    NOTE: if directory wasn't specified for http-01 challenge, then certain provisions must be performed (details)
> acme-bot configure
{
    bot: {
        issuer: "letsencrypt",
        certs_root_dir: "/etc/letsencrypt",
    },
    commands: {
        stop_on_error: false,
        // Stop reverse proxy (if there is one) while requesting and receiving certs
        pre:  [ "systemctl stop  nginx" ],
        post: [ "systemctl start nginx" ]
    },
    domains: {
        'example.org': {
            sub_domains: "www",
            challenge_cfg: [ { type: 'http-01' } ]
        }
    },
}
  1. Check if everything works as expected by requesting a non-trusted certificate using staging environment
> acme-bot --standalone test
  1. If test passed without errors, request trusted certificate from production environment and allow acme-bot to run automatically on schedule from now on
> acme-bot --standalone --issue enable

Uninstall

before actually removing the package, it is recommended to clear the auto-renewal task schedule manually using disable action, since npm doesn't support uninstall scripts:

> acme-bot disable
> npm uninstall -g acme-bot

Usage

Actions and order of the arguments

When acme-bot is expected to perform certain action (e.g. configure, enable, disable, status, etc), order of arguments matters, since 'action' must be the last argument.

# Order of the arguments matters
> acme-bot --debug --config-file /home/user/.local/acme-bot.json configure

Using internal ACME challenge server

If directory was not specified for the http-01 challenge

  • Either --standalone option must be specified and existing http server or reverse proxy would have to be stopped for the duration of running acme-bot
  • OR reverse proxy would have to be configured to interact with bot's internal ACME challenge server via a tcp port or unix socket

Example of using internal ACME challenge server WITH reverse proxy

/etc/nginx/sites-available/default
upstream acme_bot { server unix:/run/acme-bot-http.sock; server 127.0.0.1:8080 backup; }
server {
    server_name example.org www.example.org;
    listen 80;
    listen [::]:80;
    
    location /.well-known/acme-challenge/ {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://acme_bot;
    }
}
/etc/acme-bot/config.json5
{
    commands: { post: [ "systemctl reload nginx" ] },
    bot: {
        issuer: "letsencrypt",
        certs_root_dir: "/etc/letsencrypt",
        // NOTE: if both 'port' and 'path' are specified, 'path' will be used
        acme_challenge_server: { http_01: { port: 8080, path: "/run/acme-bot-http.sock" } },
    },
    domains: {
        'example.org': {
            sub_domains: "www",
            challenge_cfg: [ { type: 'http-01' } ]
        }
    },
}
Command:
> acme-bot --standalone test

Download certificate(s) manually:

To force issuing, downloading and overwriting existing certificate(s), use --force option.

# normal mode: renew only if necessary
> acme-bot
 - OR -
# forced mode: renew regardless of validity of the current cert(s)
> acme-bot --force

Configuration

Default location of the configuration file is /etc/acme-bot/config.json5, however, it is possible to point acme-bot to use other config file with --config-file option.
On the first run acme-bot needs to be configured. Following command will open configuration file in a text editor.
If configuration file not found, it will be created from template.

> acme-bot configure
 - OR -
> acme-bot --config-file /path/to/custom_config.json configure

Testing

To ensure the bot is ready to receive and store actual trusted certificates after (re-)configuring the bot, it is highly recommended to run a test to reduce the chance of running up against rate limits of the certificate issuer.
During the test, acme-bot will use issuer's staging environment (if available), and a separate directory to store account data, runtime data, and received certificates.

> acme-bot test

If test completes without issues, you can allow acme-bot to run automatically .

Automatic Task Scheduling

Following command will attempt to schedule execution of acme-bot once every 2 weeks at randomized time for automatic certificate renewal (when necessary):
Depending on the target system and environment, this command will either create a pair of service and timer for systemd OR a cron job. If neither found, it will just print error.

> acme-bot enable

To request certificate(s) immediately after successfully scheduling automatic renewal task execution add --issue option.

> acme-bot --issue enable

Check status

> acme-bot status

Expected output (if systemd is used)

● acme-bot.timer - Automatic Certificate Management Environment (ACME) - Timer
     Loaded: loaded (/etc/systemd/system/acme-bot.timer; enabled; preset: enabled)
     Active: active (waiting) since XXX XXXX-XX-XX XX:XX:XX XXX;
     Trigger: XXX XXXX-XX-XX XX:XX:XX XXX; 1 week 5 days left
     Triggers: ● acme-bot.service

NEXT                        LEFT               LAST PASSED UNIT           ACTIVATES
Mon XXXX-XX-XX XX:XX:XX EDT 1 week 5 days left -    -      acme-bot.timer acme-bot.service

1 timers listed.
Pass --all to see loaded but inactive timers, too.

Free ACME Servers

acme-bot comes with several built-in issuers' directory URLs.
[source]

{
    letsencrypt:      "https://acme-v02.api.letsencrypt.org/directory",
    letsencrypt_test: "https://acme-staging-v02.api.letsencrypt.org/directory",
    buypass:          "https://api.buypass.com/acme/directory",
    buypass_test:     "https://api.test4.buypass.no/acme/directory",
    zerossl:          "https://acme.zerossl.com/v2/DV90",
    sslcom:           "https://acme.ssl.com/sslcom-dv-ecc"
}

Challenge priority

When ordering certificate for a particular domain, acme-bot uses priorities when selecting challenges.
E.g. if supported challenges received from issuer are http-01, dns-01, tls-alpn-01 and configured challenges for particular domain are: [ 'dns-01':{ ... }, 'http-01':{...} ], then dns-01 will be selected.
E.g. if supported challenge received from issuer is only http-01 then http-01 will be selected as a fallback option.
Please note that wildcard certificates can only be validated through dns-01 challenge, which is not fully implemented on the acme-bot at the moment.
More information about challenge types can be found here.

Local challenge verification

To minimize load on public infrastructure, acme-bot will attempt to validate that it is possible to satisfy challenges locally, before telling ACME server to finalize validation the challenge. In some cases (firewalls, etc) this internal challenge verification might not be possible to complete. In this case, it is possible to disable this mechanism by setting skip_local_challenge_check option to true inside bot config. E.g.:

{
    // ....
    bot: {
        issuer: "letsencrypt",
        certs_root_dir: "/etc/letsencrypt",
        skip_local_challenge_check: true,
    },
    // ....
}

Help and usage:

(currently, under construction)

> acme-bot help

Debugging

To suppress most of the details use --silent option (only warnings and errors will be logged)

> acme-bot --silent

To see more details of what acme-bot is doing, use --debug option

> acme-bot --debug

To see even more details, set environment variable NODE_DEBUG=* along with the --debug option

> NODE_DEBUG=* acme-bot --debug

TODO

Active

  • [x] Parse existing certs to determine and check actual expiration date, match altnames, etc
  • [x] Finish transition from jsrsasign to system-wide ssl libraries.
    • [x] openssl supported v1.1.1+ (incl. v3.0+)
    • [ ] automatic availability detection and dynamic API selection
    • [ ] mbedTLS
    • [ ] GnuTLS
    • [ ] LibreSSL
    • [ ] wolfSSL
  • [x] Implement acme http challenge server for standalone mode
  • [x] Finish implementation of infrastructure for dns-01 challenge
  • [x] Implement tls-alpn-01 challenge
  • [ ] Write detailed man pages for the program and config file
  • [ ] (?) Implement manual procedure for dns-01 challenge (when no add and del scripts specified) (defeats 'A' in ACME, but okay for tests)
  • [ ] (?) Implement 'interview' on clean install to simplify initial configuration
  • [ ] (?) Test automated task execution and scheduling as a non-priviledged user, document limitations
  • [ ] (?) Implement local verification mechanism for tls-alpn-01 challenge
  • [ ] (?) Implement running acme-bot in certbot style, i.e. using only command line arguments
  • [ ] (?) Implement keeping defined amount of most recent certs in the archive
  • [ ] (?) Test running on Mac OS

Suspended

Package Sidebar

Install

npm i acme-bot

Weekly Downloads

0

Version

1.4.2

License

MIT

Unpacked Size

189 kB

Total Files

20

Last publish

Collaborators

  • nik-sie