{"id":16941,"library":"acme-dns-01-cli","title":"ACME DNS-01 Interactive CLI Challenge Handler","description":"acme-dns-01-cli is an interactive command-line interface (CLI) based strategy for handling ACME DNS-01 challenges, primarily designed for integration within the Greenlock and ACME.js ecosystems. As of version 3.0.7, it provides a simple, manual process where it prints the required DNS Host and Key Authorization Digest to the terminal, pauses for user input, and then verifies the challenge. Unlike HTTP-01 challenges, this module fully supports wildcard certificate requests, making it a crucial component for securing domains like `*.example.com`. Its main differentiation is its direct, interactive nature, serving as a reference implementation for those needing manual control over the DNS challenge process or adapting it to custom environments. While it requires manual intervention, it offers flexibility for environments where automated DNS provisioning isn't feasible or desired. It integrates seamlessly as a challenge handler within Greenlock's configuration.","status":"active","version":"3.0.7","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","Let's Encrypt","Greenlock","ACME","dns-01","wildcard","wildcards","manual","cli"],"install":[{"cmd":"npm install acme-dns-01-cli","lang":"bash","label":"npm"},{"cmd":"yarn add acme-dns-01-cli","lang":"bash","label":"yarn"},{"cmd":"pnpm add acme-dns-01-cli","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"acme-dns-01-cli is designed to integrate as a challenge handler with Greenlock instances; specific version compatibility exists.","package":"greenlock","optional":true}],"imports":[{"note":"The 'create' function is the primary way to initialize and configure the challenge handler. For CommonJS, it is accessed as a named property: `const { create } = require('acme-dns-01-cli');`","wrong":"const greenlockChallenge = require('acme-dns-01-cli');","symbol":"create","correct":"import { create } from 'acme-dns-01-cli';"},{"note":"In CommonJS environments, requiring the module directly provides an object containing its exports. This module does not provide a default export for direct ES module default imports.","wrong":"import acmeDns01Cli from 'acme-dns-01-cli';","symbol":"(CommonJS module access)","correct":"const acmeDns01Cli = require('acme-dns-01-cli');"},{"note":"The 'set' and 'remove' methods are properties of the challenge handler object returned by calling `create()`, not direct exports from the main `acme-dns-01-cli` module itself. These methods are typically invoked internally by the ACME client (e.g., Greenlock).","wrong":"import { set } from 'acme-dns-01-cli'; set(opts);","symbol":"set (method)","correct":"const handler = create({ debug: true }); handler.set(opts);"}],"quickstart":{"code":"import Greenlock from 'greenlock';\nimport { create as createDns01CliChallenge } from 'acme-dns-01-cli';\n\n// Configure the acme-dns-01-cli challenge handler\nconst challengeConfig = createDns01CliChallenge({\n  debug: true // Enable debug output for the CLI handler\n});\n\n// Initialize Greenlock with the custom challenge handler\nconst greenlock = Greenlock.create({\n  package: {\n    name: 'my-greenlock-app',\n    version: '1.0.0',\n  },\n  configDir: './greenlock.d/', // Specify a configuration directory\n  maintainerEmail: 'your-email@example.com',\n  cluster: false, // Set to true for multi-process environments\n  challenges: {\n    'dns-01': challengeConfig // Register the interactive DNS-01 challenge\n  },\n  // Define how domains are approved (customize as needed)\n  approveDomains: async (opts) => {\n    console.log(`Greenlock is requesting approval for: ${opts.subject || opts.altnames.join(', ')}`);\n    // For acme-dns-01-cli, the manual interaction will occur via the challengeConfig\n    return opts;\n  },\n});\n\n// Function to request a certificate (this will trigger the CLI prompt)\nasync function obtainCertificate() {\n  const domainsToSecure = ['example.com', '*.example.com']; // Example domains\n  console.log(`Attempting to obtain certificate for: ${domainsToSecure.join(', ')}`);\n  try {\n    const cert = await greenlock.add({\n      subject: domainsToSecure[0], // Primary domain\n      altnames: domainsToSecure,   // All domains including wildcard\n      email: 'your-email@example.com', // Email for renewal notices\n    });\n    console.log('Successfully obtained certificate:', cert);\n  } catch (err) {\n    console.error('Failed to obtain certificate:', err);\n    if (err.challenge && err.challenge.dnsHost && err.challenge.dnsAuthorization) {\n        console.warn(`Please verify the TXT record for ${err.challenge.dnsHost} with value ${err.challenge.dnsAuthorization} is correctly set.`);\n    }\n  }\n}\n\n// Execute the certificate acquisition process\nobtainCertificate();\n\n// In a real application, Greenlock would also manage a server\n// to handle certificate renewals and serve HTTPS traffic.\n// Example (requires 'greenlock-express'):\n/*\nimport greenlockExpress from 'greenlock-express';\n\ngreenlockExpress.create({\n  package: greenlock.defaults.package,\n  configDir: greenlock.defaults.configDir,\n  maintainerEmail: greenlock.defaults.maintainerEmail,\n  cluster: greenlock.defaults.cluster,\n  challenges: greenlock.defaults.challenges,\n  approveDomains: greenlock.defaults.approveDomains,\n  // Add your server options here\n}).listen(80, 443);\n*/","lang":"typescript","description":"This quickstart demonstrates how to integrate `acme-dns-01-cli` into a Greenlock instance as a DNS-01 challenge handler, initiating a certificate request that will prompt the user for manual DNS record updates."},"warnings":[{"fix":"For Greenlock v2.6 or lower, you must use the legacy `le-challenge-dns@2.x` package. For Greenlock v3.x and newer, use `acme-dns-01-cli@3.x`. Ensure your Greenlock version matches the appropriate challenge package.","message":"Version 3.x of `acme-dns-01-cli` introduces breaking changes regarding compatibility with older Greenlock versions.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Not suitable for fully automated certificate provisioning without external scripting to interact with the CLI prompts and DNS provider APIs. Plan for manual updates or develop an automation layer if full automation is required.","message":"This strategy is manual and interactive, requiring user intervention via the CLI to update DNS TXT records.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be prepared to create multiple TXT records sequentially as prompted by the CLI for each domain or wildcard that requires a challenge.","message":"Requesting a certificate for multiple domains (e.g., `example.com` and `www.example.com`) or multiple wildcards (`*.example.com`, `*.sub.example.com`) will trigger an individual DNS-01 challenge for each subject.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure you are using `const { create } = require('acme-dns-01-cli');` for CommonJS or `import { create } from 'acme-dns-01-cli';` for ES Modules. Verify your Greenlock version is compatible with acme-dns-01-cli v3.x (Greenlock v3.x+ is generally required).","cause":"Incorrect module import/access for the 'create' function, or an incompatibility between Greenlock and acme-dns-01-cli versions.","error":"TypeError: require(...).create is not a function"},{"fix":"Double-check the exact DNS Host and DNS Key Authorization Digest provided by the CLI. Ensure the TXT record is published correctly and has propagated across DNS servers (use tools like `dig` or online DNS checkers). Wait a few minutes after setting the record before pressing Enter in the CLI.","cause":"The DNS TXT record was not correctly propagated or not set in time before the ACME server attempted verification.","error":"Error: Challenge verification failed."},{"fix":"Add `const Greenlock = require('greenlock');` for CommonJS or `import Greenlock from 'greenlock';` for ES Modules at the top of your file, ensuring Greenlock is installed (`npm install greenlock`).","cause":"The Greenlock module was not imported or required correctly before use.","error":"ReferenceError: Greenlock is not defined"}],"ecosystem":"npm","meta_description":null}