How can you use it?
First, download the source.
If you're on
OpenBSD 5.9 and newer, use the standard acme-client.tgz.
Otherwise (FreeBSD, NetBSD, Linux, Mac OS X, old OpenBSD), use acme-client-portable.tgz.
You can also use the bleeding-edge from GitHub
( acme-client |
Unpack, SHA512 verify ( acme-client.sha512 | acme-client-portable.sha512), then run
It should have all you need.
(This project used to be named letskencrypt, but was renamed to acme-client in version 0.1.11.)
The dependencies of
acme-client-portable are LibreSSL, libbsd (Linux), and
libseccomp (Linux, and optional but strongly suggested).
The standard acme-client has no dependencies.
How does it work?
acme-client consists of isolated independent components.
Each of these is responsible for part of the sequence of manipulating a Let's Encrypt certificate for one or more domains:
read and parse an account and domain private key
authenticate with the Let's Encrypt server
authorise each domain listed for the certificate
submit the X509 request
receive and serialise the signed X509 certificate
request, receive, and serialise the certificate chain from the issuer
Why so complicated?
Key integrity and trust.
You don't want the private key processes interacting with anybody else (
You don't want network-touching processes interacting with the file-system ( dnsproc.c and netproc.c). You
don't want the process parsing ( revokeproc.c) your
certificate — which comes down the pipe and might be rigged to blow — to touch your file-system
or the network.
Same goes with the process converting the downloaded certificates to the format usable by your web
server ( certproc.c).
Moreover, you don't want the process scribbling in your webroot to scribble elsewhere ( chngproc.c).
Same goes with the process scribbling in your public certificate directory ( fileproc.c).
In the diagramme, processes with file-system write access are in
and are isolated in a chroot(2) file-system jail.
Those with network access are in blue and
are pledge(2)ed only for networking and DNS
Orange nodes are off-site.
All other processes are locked down with full pledge(2)s.
Each process uses the fork+exec model:
Use of fork+exec in privilege separated programs. The strategy is to give each process a fresh &
unique address space for ASLR, stack protector — as protection against address space
discovery attacks. (From OpenBSD's innovations.)
In the portable version without
all processes but the red are privilege-dropped and chroot(2)ed.
The red file-system processes do not drop privileges.
Add OCSP stapling if specified with
Also merge code by xdgc ( pull/13) to allow consumers of
non-http-01 -t challenges have more information — thanks!
See acme-client(1) for more details of both.
I've also disabled the Linux
seccomp sandbox by default.
I've provided a full explanation in
why I've disabled seccomp in acme-client
Fix some fall-out from the fork+exec migration noted in
issue/12, where creating new
keys with -n or -N caused a race condition.
Thanks for the report!
Also, put in the initial
libseccomp(3) sandbox for
conformant versions of Linux.
This has only been tested on Alpine Linux, so it will probably fail at
first for other systems: it is experimental.
(If you don't have libseccomp(3) installed, or if you comment out
the appropriate lines in the GNUmakefile, it
will not be enabled.)
If it does fail, please notify me by e-mail or on GitHub with the error code it produces.
Lastly, import some OpenBSD downstream fixes relating to error-catching when closing TLS connections.
Bug-fix release working around old versions of
certificates were attempted to load inside of the file-system jail.
This has been fixed in newer versions of libressl (specifically the TLS
library), but while those these make their way into the ecosystem, I've implemented a workaround.
You have this problem if the client fails to connect to the ACME server entirely.
Also add a bit of documentation on how to configure the system, if it doesn't work (and it should work) out of the box.
Bug-fix release for systems not having the
__dead attribute (Linux, FreeBSD, etc.).
Warning: the default paths have changed!
In moving letskencrypt to acme-client,
the default directories are moving to /etc/ssl/acme, /var/www/acme, and /etc/acme.
Before, these all had letsencrypt in place of acme.
-m flag try to build the domain directory if it does not exist.
This makes adding new -m hosts much easier.
-e flag, which allows for extending certificates with new SAN domains.
fork+exec model for subprocesses.
In the words of OpenBSD,
The strategy is to give each process a fresh & unique address space for ASLR, stack protector—as
protection against address space discovery attacks.
Lastly, add support for ECSDA domain keys. (Not account keys, yet.)
-t, which allows the caller to provide its own challenge implementation.
These challenges, such as dns-01, are too system-specific to provide in a safe manner.
After being merged into OpenBSD as usr.sbin/acme-client, and
following a suggestion from the Let's Encrypt folks, formally rename to acme-client.
-b flag to backup certificate files.
Add the -a flag to provide an alternative license agreement.
(And update the default one.)
Include ChangeLog (with cvs2cl) in every release tarball as
requested by Bernard Spil.
Have the system return an error code depending on what happened and not just a blanket
success (0) or
Now, the success exit code (0) is only returned when certificates have been revoked or updated.
If no certificates were touched (e.g., they aren't out of date and -F wasn't provided), then the system
will return code 2.
This allows the caller to know (for example) when the web server should reload its certificates.
-N and -n only create the key if it does not exist.
Allow downstream to override
Bug-fix for the incorrect validation of domain names as noted by Remco and on
GitHub — thanks!
Add the - N flag to create the domain key.
This was indirectly requested in issues/7 and
Changed to using SHA512 instead of SHA256 (it always was, but was being incorrectly specified as SHA256) for the
download file (noted in issues/2).
Fixed up letskencrypt(1) with some examples.
First, introduce the -
m flag to make working with multiple certificates easier.
This appends the first domain to all path components.
Also have multiple - v invocations actually dump the transfer buffers, and fix the buffer dump.
Allow install directories (in -portable) to be overriden by the environment (thanks, Remco!).
Allow using Linux's default setresuid(2), also from a patch by
Thanks a third time for Remco in his work to internally abstract out RSA key functionality and
umask(2)ing created account keys.
Lastly, as suggested by Thomas Klausner, add NetBSD support.
Refine OpenBSD's usage of
The portable branch continues to use chroot(2) and privilege
dropping throughout, but the main branch depends much more upon pledging.
Also merge a set of fixes from Remco, Alexandre Perrin, and Caspar Schutijser. Thank you!
And special thanks to Remco for adding support for non-RSA domain keys.
libcurl and instead grow a small HTTP client loosely
inspired by snimmagadda/http.
On OpenBSD, there are no more external dependencies.
On other systems, you'll need libressl (for the excellent TLS interface).
Also enable some simple DNS caching and fix verifying SAN entries on existing certificates.
json-c and instead import jsmn directly into the sources.
This simplifies the source code and removes a dependency.
Also fix a possible bug when converting from ASN1 objects into strings, where the buffers would possibly
not be nil-terminated.
The utility has been on GitHub for a while, but this is the first stable release.
The tool has all the functionality you need: submission and revocation of certificates.