security/acme-client: missing accounts directory causes DNS-01 validation failure

Open Beginner friendly
#5,770 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

  • #5779 by @sean0407 — closed without merging

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
php, shell
Domain
backend, security

Research direction

Start by locating the os-acme-client code that launches acme.sh with --accountconf, and check how it prepares the account configuration path. Ensure the parent directory exists before that invocation; done means DNS-01 issuance can proceed from a clean runtime directory without manual setup, as in the Services > ACME Client > Certificates flow.

Written by the indexing model from the issue text.

Description

support

Important notices
Before you add a new report, we ask you kindly to acknowledge the following:

Describe the bug
os-acme-client invokes acme.sh with an explicit account configuration path beneath:

/var/etc/acme-client/accounts/_prod/account.conf

However, on my system the accounts directory was not created. This causes DNS-01 validation to fail before the DNS provider API is called.

Tip: to validate your setup was working with the previous version, use opnsense-revert (https://docs.opnsense.org/manual/opnsense_tools.html#opnsense-revert)

Last known working os-acme-client version: Unknown.
This is a new pfSense-to-OPNsense migration, so I do not have an earlier OPNsense plugin version known to work.

To Reproduce
Steps to reproduce the behavior:

GUI pages involved:
Services > ACME Client > Certificates
Services > ACME Client > Challenge Types

Symptoms
Certificate configuration:

CN: ryanhome.us
SAN: *.ryanhome.us

The ACME operation failed with:
Error adding TXT record to domain: _acme-challenge.ryanhome.us domain validation failed (dns01)

Debug 3 showed:

ACCOUNT_CONF_PATH='/var/etc/acme-client/accounts/_prod/account.conf'

But the runtime directory contained only: cert-home certs challenges configs home keys

There was no:
/var/etc/acme-client/accounts

Investigation
The installed DreamHost DNS provider calls validate() before submit().

validate() ends by calling: _saveaccountconf_mutable DH_API_KEY "$DH_API_KEY"
_saveaccountconf_mutable ultimately writes to ACCOUNT_CONF_PATH.

In acme.sh 3.1.4, _setopt() does:
if [ ! -f "$__conf" ]; then touch "$__conf" chmod 600 "$__conf" fi
but it does not create the parent directory.

As a result, account.conf cannot be created when the parent directory does not exist. The DreamHost provider exits before submit() is reached.

Debug logging showed "Using dreamhost" and then the TXT-add failure, but no URL debug output from the provider's submit() function.

Verification that DreamHost is not the cause:
From the same OPNsense shell, using the same DreamHost API key: dns-list_records succeeds.

A manual dns-add_record also succeeds for: _acme-challenge.ryanhome.us TXT

DreamHost returns:
{"result":"success","data":"record_added"}
The record is then visible using DreamHost's dns-list_records API.

I also tested a direct query-string request equivalent to that constructed by dns_dreamhost.sh, which also returns:
{"result":"success","data":"record_added"}

Workaround / reproduction proof
Before the workaround:
ls -ld /var/etc/acme-client/accounts
returned:
No such file or directory

I manually created:
mkdir -p /var/etc/acme-client/accounts/_prod
chmod 750 /var/etc/acme-client/accounts
chmod 750 /var/etc/acme-client/accounts/_prod
I did NOT manually create account.conf and made no other ACME configuration changes.

I then issued the exact same certificate again.
The ACME log immediately progressed to:
response='success record_added' The TXT record has been successfully added. Sleeping for 120 seconds to wait for the TXT records to take effect
The certificate was subsequently issued successfully.

OPNsense now reports:
Last ACME Status: OK and acme.sh automatically created: /var/etc/acme-client/accounts/_prod/account.conf with permissions 0600.

Expected behavior
os-acme-client should ensure the parent directory for the account configuration exists before invoking acme.sh with --accountconf.

For example:
/var/etc/acme-client/accounts/_prod/
should already exist before acme.sh is executed.

Proposed Fix is conceptually like:

$accountConfDir = dirname($accountConf);

if (!is_dir($accountConfDir)) {
mkdir($accountConfDir, 0750, true);
}

immediately before the plugin launches acme.sh with:
--accountconf $accountConf

Before workaround behavior:

ls -ld /var/etc/acme-client/accounts
ls: /var/etc/acme-client/accounts: No such file or directory

Workaround:
mkdir -p /var/etc/acme-client/accounts/_prod
chmod 750 /var/etc/acme-client/accounts
chmod 750 /var/etc/acme-client/accounts/_prod

No other ACME settings were changed.
The next issuance succeeded:

response='success record_added'
The TXT record has been successfully added.
Sleeping for 120 seconds to wait for the TXT records to take effect

Issue/Renewal Date: 10/3/2026 3:57:06 PM
Last ACME Status: OK

Screenshots
If applicable, add screenshots to help explain your problem.
No additional screenshots were taken but could be provided if requested.

Relevant log files
If applicable, information from log files supporting your claim.
No additional log files are attached but could be provided if requested.

Additional context
Additional information
The workaround on my system is currently present under /var/etc and therefore may not survive reboot or runtime-directory recreation.
No modification to acme.sh or dns_dreamhost.sh was required.

Environment
OPNsense 26.7.4_1 (amd64)
os-acme-client 4.17
acme.sh 3.1.4
FreeBSD 15.1-RELEASE-p3
ACME CA: Let's Encrypt
Challenge: DNS-01
DNS provider: DreamHost

Dominant language
PHP
Stars
1.2k
Forks
905
Avg merge
4d 19h
Merged PRs (30d)
16

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from opnsense/plugins

All issues in opnsense/plugins

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.