security/acme-client: missing accounts directory causes DNS-01 validation failure
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
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
Important notices
Before you add a new report, we ask you kindly to acknowledge the following:
- I have read the contributing guide lines at https://github.com/opnsense/plugins/blob/master/CONTRIBUTING.md
- I have searched the existing issues, open and closed, and I'm convinced that mine is new.
- The title contains the plugin to which this issue belongs
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
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from opnsense/plugins
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 2 days
-
security/tailscale: add description to restart servicePossibly taken @drpsyko101 claimed this 2 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 85/100
Maintainers usually reply within 2 days
-
security/tor: Advanced mode / help toggles are brokenPossibly taken @txr13 claimed this 44 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
os-opnproxy 1.0.5_5Openincomplete
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
opnsense/plugins#5710 · 1 comment ·
Maintainers usually reply within 2 days
-
net/vnstat: use OPNsense interface names in dashboard widgetPossibly taken @joeroback claimed this 108 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 2 days
All issues in opnsense/plugins
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
PrestaShopCorp/ps_eventbus#505 ·
-
`path` option is dropped from request URLs when it has no trailing slashPossibly taken @RaphaelFakhri claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
pusher/pusher-http-php#411 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
OpenConext/OpenConext-engineblock#2168 ·
Maintainers usually reply within 5 days
-
mobile-app
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Open-Locker/Open-Locker#352 ·
Maintainers usually reply within 1 day