acmetool

repository·master·Indexed 24 days ago

https://github.com/hlandau/acmetool

A lightweight, dependency-free command-line tool for automatically acquiring and renewing SSL/TLS certificates from ACME servers like Let's Encrypt. It features an idempotent design that manages certificates without directly modifying webserver configuration files, supporting validation methods such as Webroot, Proxy, Stateless, Redirector, Listen, and Hook. It includes a quickstart wizard for initial setup and supports ECC and RSA keys.

Tokens
10.5K
Snippets
16
Records
57
Agent score
84%

What's inside acmetool

  1. How target set disjunction works

    master

    To prevent redundant certificate requests, ACME clients use a 'disjunction procedure' to ensure that any given hostname appears in at most one target's list of names to be satisfied.

    1. Sorting: Targets are sorted by priority (descending), then by the number of hostnames (descending).
    2. Mapping: The client iterates through sorted targets, building a Hostname-Target Mapping.
    3. Reduction: For each target, the client calculates a 'reduced set' of hostnames by removing any hostnames that have already been assigned to a higher-priority target.

    This process ensures deterministic behavior and minimizes the number of certificates issued when multiple targets overlap in their requested hostnames.

  2. How ACME identifiers (Account, Key, Certificate) are calculated

    master

    ACME uses specific deterministic identifiers for directories to ensure consistency.

    Key ID

    • A lowercase base32 encoding (with padding stripped) of the SHA256 hash of the subjectPublicKeyInfo from the private key.

    Account ID

    • Formed by taking the ACME Directory URL, stripping the scheme (e.g., example.com/directory), and URL-encoding it (using lowercase hex).
    • This string is then appended with / and the Key ID of the account's private key.
    • Example: example.com%2fdirectory/irq7564p5siu3zngnc2caqygp3v53dfmh6idwtpyfkxojssqglta
    • For testing with HTTP, the scheme is prefixed with http: (e.g., http:example.com%2fdirectory/...).

    Certificate ID

    • A lowercase base32 encoding (with padding stripped) of the SHA256 hash of the order URL (or the certificate URL for legacy certificates). This allows an ID to be assigned before the certificate is even issued.
  3. Compare acmetool with other ACME clients

    master

    acmetool is designed as a lightweight, single-file binary that focuses on satisfying certificate requirements without mutating your webserver configuration. Unlike Certbot, it does not attempt to automatically modify your webserver files; instead, it places certificates in standard locations and uses hook shell scripts to reload the webserver.

    Key differentiators include:

    • Automatic Renewal: Supported natively.
    • ECC Support: Supported.
    • Webserver Support: Native support for Apache, nginx (experimental), HAProxy, and Hitch. It can support any webserver via webroot, proxy, or port 80 redirector methods.
    • State Management: Uses a comprehensible, magic-free state directory designed for idempotency.
  4. Automate webserver reloads using notification hooks

    master

    Acmetool can automatically reload your webserver when certificates are renewed by executing scripts in /usr/lib/acme/hooks (or /usr/libexec/acme/hooks).

    The reload hook

    By default, acmetool quickstart installs a reload hook that detects your distro and reloads common services (e.g., via systemctl reload or service reload).

    To add a custom service to the reload list, edit the configuration file at /etc/conf.d/acme-reload or /etc/default/acme-reload:

    # Add a service to the existing list
    SERVICES="$SERVICES cherokee"

    Custom Hooks

    You can drop your own executable files into the hooks directory. To prevent acmetool from overwriting your custom scripts during updates, ensure they do not contain the string #!acmetool-managed!# near the start of the file.

  5. The ACME State Directory structure

    master

    The State Directory is organized into several key subdirectories:

    • desired/: Contains target expression files (YAML) that express the hostnames for which certificates are required.
    • live/: Contains symbolic links to the appropriate certificate directories for each hostname.
    • certs/: Stores actual certificate data, organized by certificate/order ID. Includes cert, chain, fullchain, privkey (symlink), account (symlink), url, and revocation status files (revoke, revoked).
    • keys/: Stores PEM-encoded private keys, organized by key ID.
    • accounts/: Stores PEM-encoded account private keys, organized by account ID.
    • conf/: Contains configuration data (e.g., target for default provider URLs).
    • tmp/: Used by the implementation for temporary file operations.
  6. Understand the acmetool state storage schema

    master

    Acmetool stores all state in a single directory (default /var/lib/acme).

    live/ directory

    Contains symlinks for hostnames pointing to their respective certificate directories. Use these stable paths in your webserver config: /var/lib/acme/live/example.com/{cert,chain,fullchain,privkey}

    desired/ directory

    Contains YAML target files. Each file defines what certificates should be obtained.

    Target File Structure Example:

    satisfy:
      names:
        - example.com
        - www.example.com
    
    request:
      provider:               # ACME Directory URL
      ocsp-must-staple: true
      challenge:
        webroot-paths:
          - /var/www
        http-ports:
          - 123
        env:
          FOO: BAR
      key:
        type: rsa|ecdsa
        rsa-size: 2048
        ecdsa-curve: nistp256
    
    priority: 0

    Important Constraints

    • Filesystem Boundaries: All files under the state directory must reside on the same filesystem.
    • Target Files: An empty target file in desired/ defaults to the filename as the target hostname.
    satisfy:
      names:
        - example.com       # The names you want on the certificate.
        - www.example.com
    
    request:
      provider:               # ACME Directory URL. Normally set in conf/target only.
      ocsp-must-staple: true  # Request OCSP Must Staple. Use with care.
      challenge:
        webroot-paths:        # You can specify custom webroot paths.
          - /var/www
        http-ports:           # You can specify different ports for proxying.
          - 123               # Defaults to listening on localhost.
          - 456
          - 0.0.0.0:789       # Global listen.
        http-self-test: false # Defaults to true. If false, will not perform self-test
                              # but will assume challenge can be completed. Rarely needed.
        env:                  # Optionally set environment variables to be passed to hooks.
          FOO: BAR
      key:                    # What sort of key will be used for this certificate?
        type: rsa|ecdsa
        rsa-size: 2048
        ecdsa-curve: nistp256
        id: krzh2akn...       # If specified, the key ID to use to generate new certificates.
                              # If not specified, a new private key will always be generated.
                              # Useful for key pinning.
    
    priority: 0
  7. Understand the ACME State Storage Specification (ACME-SSS)

    master

    The ACME State Storage Specification (ACME-SSS) defines how an ACME client stores state information on a local POSIX-like system. This structure allows the client to manage its own state and expose certificates and keys to other system services.

    On UNIX-like systems, the preferred State Directory is /var/lib/acme.

  8. How ACME state reconciliation works

    master

    The reconciliation process is the core operation that builds the State Directory to ensure all targets are satisfied with the best possible certificates.

    The Reconciliation Lifecycle:

    1. Conform: Validates the directory for consistency, fixes permissions, and ensures symlinks are unbroken and relative.
    2. Cache: Ensures all uncached certificates are available.
    3. Revoke: If a revoke file exists in a certificate directory, the implementation requests revocation and creates a revoked file upon confirmation.
    4. Satisfy Targets: For each target, the system checks if a satisfying certificate exists. If not, it initiates a certificate request process:
      • Create an order and satisfy authorizations.
      • Once the order is ready, create a CSR with the required SANs and finalize the order.
      • Write the order URL to the State Directory.
    5. Update Live Symlinks: Updates the live directory so hostnames point to the Most Preferred Certificate.
    6. Cleanup: Optionally deletes cullable certificates and keys.

    Key Concepts:

    • Satisfying a Target: A certificate satisfies a target if its private key is available, it is not revoked, it is not self-signed, it is within its validity period, and it is not 'near expiry'.
    • Near Expiry: A certificate is considered near expiry if the time remaining is less than the implementation's threshold (recommended: 30 days or 33% of validity).
    • Most Preferred Certificate: The system selects the best certificate for a target based on:
      1. Whether it satisfies the target.
      2. If multiple don't satisfy, it uses a fallback hierarchy (e.g., a certificate with an available private key is better than one without; a self-signed cert is better than a revoked one).
      3. Certificates with later Not After times are preferred.
  9. Configure ACME validation methods

    master

    acmetool supports several ways to perform domain validation:

    • Webroot: Places challenge files in a directory that your webserver serves from /.well-known/acme-challenge/.
    • Proxy: acmetool listens on port 402. You configure your webserver to proxy requests for /.well-known/acme-challenge/ to http://127.0.0.1:402/.well-known/acme-challenge/.
    • Stateless: A method where the webserver responds to challenges without consulting acmetool, requiring a one-time configuration change.
    • Redirector: Starts an HTTP server on port 80 that redirects all requests to HTTPS and handles validation responses. This is useful if your webserver is not listening on port 80. Run it as a service: acmetool redirector --service.uid=USERNAME --service.daemon=1
    • Listen: If ports 80 or 443 are not in use, acmetool can use them directly (primarily for development).
    • Hook: Allows you to write custom shell scripts or binaries to provision challenge files (e.g., rsyncing them to a remote server).
  10. Understand the self-signed certificate fallback mechanism

    master

    When an ACME client cannot immediately procure a valid certificate, it may provision an interim self-signed certificate to prevent daemons from failing due to missing files. This allows the daemon to continue operating with reduced functionality.

    To implement this fallback, the following directory state must be maintained:

    • An empty selfsigned file must be created in the certificate directory.
    • The url file must not exist.
    • The cert and fullchain files must be identical.
    • The chain file must exist and must be an empty file.

    Certificate ID for self-signed certificates: The ID is constructed as the string selfsigned- followed by the lowercase base32 encoding (with padding stripped) of the SHA256 hash of the DER encoded certificate.

  11. Understand the ACME State Directory structure

    master

    The ACME State Directory is the central storage for all ACME-related data. It follows a specific directory tree to manage accounts, keys, certificates, and symlinks for easy access by applications.

    Directory Tree Overview

    • accounts/: Contains account-specific information. Each subdirectory is named after an Account ID and contains a privkey file (PEM format).
    • keys/: Contains private keys used for certificates. Each subdirectory is named after a Key ID and contains a privkey file (PEM format).
    • certs/: Contains information about issued or requested certificates. Each subdirectory is named after a Certificate ID and contains:
      • url: The URL for the finalized order (UTF-8).
      • account: A relative symlink to the account directory used for the request.
      • cert: The PEM-encoded certificate.
      • chain: The PEM-encoded certificate chain (intermediate certificates).
      • fullchain: The concatenation of cert and chain.
      • privkey: A relative symlink to the corresponding key in the keys/ directory.
    • live/: Contains relative symlinks to subdirectories in certs/. Symlink names follow the pattern hostname:label (e.g., example.com or example.com:web). This allows applications to point to a stable path like /var/lib/acme/live/example.com/cert regardless of certificate rotations.
    • tmp/: Used for atomic file operations and temporary storage.
  12. Automate certificate renewal with `reconcile --batch`

    master

    acmetool is designed to be idempotent and works like make. The reconcile subcommand ensures that all desired hostnames are satisfied by valid certificates. Certificates are automatically renewed when they are within 30 days of expiry or 66% through their validity period.

    To run acmetool as a cron job for automatic renewal, use the --batch flag to prevent the tool from attempting to interact with a terminal:

    acmetool --batch reconcile

    Note: want calls reconcile automatically.