Let'sEncrypt, ACME.sh and LUCI App Acme support topic

Here you may report issues and ask questions about enabling HTTPS and issuing TLS certificates on OpenWrt.

Questions about config file /etc/config/acme and packages:

  • acme
  • acme-acmesh
  • acme-acmesh-dnsapi
  • acme-common
  • luci-app-acme
  • uacme

Before asking you may check:

Hi,

In the wiki for using acme on OpenWrt, it says 'Enable for uhttpd', however in the most recent luci-app-acme (23.267.29406~2edb201), that option is no longer there.
EDIT: just realised this might be because I have installed nginx?

Can you explain how I use /usr/lib/acme/client/acme.sh and feed it the configuration from /etc/config/acme? (dns_cpanel)

I'm trying to construct a valid command for testing from ash.

So far I have:
/usr/lib/acme/client/acme.sh --home /etc/acme --email email@example.com --renew --staging --server https://acme-staging-v02.api.letsencrypt.org/directory --dns dns_cpanel -d lan.example.com

When I run this, I get 'You haven't specified cPanel username, apitoken and hostname yet' (these details are in /etc/config/acme'

EDIT: I came to the understanding that' ACME certificates' in LuCI must be run once to create the account.conf and then running it from the command line finds the credentials.

No current issues for me.

One thing to note is acme defaults to ZeroSSL. To use Let's encrypt you have to use CLI as the option isn't in LuCI yet.

1 Like

I saw the same problem, I successfully got a letsencrypt certificate but it was not used by uhttpd. It needs to be fixed so that letsencrypt can be used by luci.

1 Like

Last I checked the acme-achmesh was the only package with dependency on acme-common.

Also the naming is inconsistent, either uacme needs to be renamed to acme-uacme or there's no reason to keep both acme-acmesh and acme-common as two separate packages and they should be rolled into a single achmesh package.

PS. Again, last I checked, which has been a while ago, there was no documentation for acmesh, you would have to parse the init script source code to see what options/configuration it supports. Which is a serious drawback to using it OpenWrt-way rather than running the shell script with the necessary options in CLI.

just logged into my router and was suprised it had no valid cert.
The issue was not the cert was old but uhttpd wasn't restarted when the cert was renewed.
Hadn't that issue before.
I have OpenWrt 23.05.3 with acme 4.0, acme-acmes 3.0.7-1
acme-acmesh-dnsapi 3.0.7-1
acme-common 1.0.4
luci-app-acme

in the config it says
option update_uhttpd '1'

1 Like

So far I have used standalone mode which generated one cert for six different domains and three different webroots. Worked fine.

Now I discovered webroot mode. Advantage: no need to stop the lighttpd web server.

Is there a problem with using the same cert for different domains?
The mail server receives mail for all six different domains and can only handle one cert.

How can I generate one cert for different domains in webroot mode?
I can only find examples of certs for multiple (sub)domains with different webroots.

So far I have:

/usr/lib/acme/client/acme.sh -r --home /etc/acme \
	-d domain1 -w /root/web/domain1 -d domain2 -d domain3 -d domain4 \
	-d domain5 -d domain6

And why does acme.sh remove a link (/root/web/domain1/.well-known/acme-challenge to /var/run/acme/challenge/) it needs and then complains that it isn't there?

[Thu May  9 22:35:54 CEST 2024] domain1 is already verified, skip http-01.
[Thu May  9 22:35:54 CEST 2024] domain2 is already verified, skip http-01.
[Thu May  9 22:35:55 CEST 2024] Verifying: domain5
mkdir: can't create directory '/root/web/domain1/.well-known/acme-challenge': No such file or directory
/etc/acme/acme.sh: line 4941: can't create /root/web/domain1/.well-known/acme-challenge/aFJMMzSMkDU1pI4Pb1gRNnn_b-7PpA9UFjnVgCKOp6w: nonexistent directory

I followed the instructions here. Has webroot method been tested on openwrt? Is it better to go back to standalone mode meanwhile?

acme for openwrt is incomplete, I had to manually change settings for uhttpd.

option cert '/etc/acme/router.example.com_ecc/router.example.com.cer'
option key '/etc/acme/router.example.com_ecc/router.example.com.key'

And the renewal hook is also wrong in ACME luci
It should be.
Le_RenewHook='**ACME_BASE64*_START_c2VydmljZSB1aHR0cGQgcmVzdGFydA==_ACME_BASE64*_END'

with --debug the link is not removed:

Debugging, skip removing: /root/web/domain1/.well-known/acme-challenge

but it fails anyway because:

domain5:Can not write token to file : /root/web/domain1/.well-known/acme-challenge/PcGIjo8jX9Zm5HZOL0X-UK1ewTxk_OlbsGhYE5NK0e0

I'm a bit lost.

Yes, the options was removed. The idea was that all services (uhttpd, nginx, emailrelay etc.) should create a hotplug hook that will be triggered on event of the new certificates and they should themselves reload or restart the deamon and pick up the new certificate. I don't know if the hooks were actually added. Will try to check this once get a time

You must configure the /etc/config/acme and the /etc/init.d/acme service will read the onfigs and trigger the acme.sh itself. So please don't run it manually to avoid unexpected conflicting problems.
I also highly recomend you to use the Luci Application for ACME, you can install it with opkg update; opkg install luci-app-acme. It provides UI with helping notes about options.

Yes, the uacme integration with the acme-common wasn't yet merged

I'll try to create a separate wiki page with a list of all options. Still, the prefered way is to use the luci-app-acme because it contains a description for all options

1 Like

See, everybody complain, nobody wan't to fix it. I myself was diverted to fix the luci-app-acme and DNS validation. Hope I will enough time to shift the gears, but honestly I would rather be happy if maintainer of the acme-common will do this. For now he even not joined the topic and seems very busy :frowning:

@fortuna Just to be clear, the standalone mode is intended to be used if you don't have a webserver or it's not available from internet. It will start a netcat that will imitate a web server to return a the file with a random value of ACME chalenge to the LetsEncrypt/ZeroSSL so that they can be sure that you really own the server and domain.

The webroot instead will save the challenge file to a folder and the folder must be served by your HTTP server (i.e. lighttpd) from the URL http://yoursite/.well-known/acme-challenge/.
But anyway once the new certificate is signed you have to reload or restart the HTTP server so that it will re-read a certificate file and start using the new cert. When the acme issues a new cert it calling a hotplug hooks and your http server should create its own hook to make the reload/restart itself. But this part is not implemented yet, as you may see from my previous comments.

If you have to shutdown the HTTP server before running the standalone validation then you are probably didn't configured it to serve the /.well-known/acme-challenge/ URL from the /var/run/acme/. Another possible reason could be that your sever is configured to be accessible only from local network (e.g. Luci admin panel) but outside world can't access it including the LE/ZeroSSl validators.

Technically speaking a certificate can have mutiple domains but usualy this is used for subdomains e.g.:

As far I know, you still can have many domains in certificate, but in practice this may be rare because from a cert you may see all of them while you may want to hide their relation.

Please check again, your mail server must support many certificates. All programs that I saw are working totally fine if there are many certs in one file just written one after another. But they have a requirement to have a strict order when you have private key then its public cert. This is needed because a public cert doesn't have an ID of a corresponding private key and you can't map them to which belongs to which.

You better to use /etc/ssl/acme/*.example.com.key instead, see the "Use the generated certificates" section
https://openwrt.org/docs/guide-user/services/tls/acmesh#use_the_generated_certificates

Interesting, so you used the ACME.sh option to pass the renewal hook as a text but not the file path. As temporarly solution this should work, thank you

That's true. So you recommend webroot mode and a cert for every domain. I am a bit reluctant as acme.sh removes the link from /.well-known/acme-challenge/ to /var/run/acme/challenge/ it needs itself and nobody can explain why.

And apart from the mail server, I just realized that the very lighttpd web server now has only one location for its key and its pemfile:

    ssl.privkey = "/etc/path/key.pem"
    ssl.pemfile = "/etc/path/fullchain.pem"

It is possible to specify different pemfiles for different domains, it's just more complicated than using only one cert.

Let's say I want to give it a try, how do I migrate from 1 cert in standalone mode to 6 certs in webroot mode? I need to --issue first and then --install-cert, right? Do I need to issue for 5 domains or all six?

Well, in your case it should be easier to make a single cert for all domains, Otherwise you need to configure a path to certs for each domain in the lighttpd.conf:

$HTTP["host"] == "www.domain1.com" {
     server.document-root = "/home/www/domain1.com/public"
     ssl.pemfile = "/etc/lighttpd/certs/www.domain1.com.pem"
}

No, you should not call the acme.sh directly. The openwrt acme-common does this for you.

I prefer to call acme.sh directly every two months in a cron job.

But is it broken?

root@router:/etc/acme# /usr/lib/acme/client/acme.sh --standalone -f -r --home /etc/acme -d domain1
[Sat May 18 20:13:03 CEST 2024] Renew: 'domain1'
[Sat May 18 20:13:03 CEST 2024] Renew to Le_API=https://acme-v02.api.letsencrypt.org/directory
Please specify at least one validation method: '--webroot', '--standalone', '--apache', '--nginx' or '--dns' etc.
root@router:/etc/acme# /usr/lib/acme/client/acme.sh --version
https://github.com/acmesh-official/acme.sh
v3.0.7

You have a path /usr/lib/acme/client/acme.sh but the acme package installs the command to /usr/lib/acme/acme.sh.

See the acme.sh wiki about how to trigger the issue cert command: