lightweight client for the RFC8555 ACMEv2 protocol, written in plain C with minimal dependencies (libcurl, GnuTLS and libev). The ACMEv2 protocol allows a Certificate Authority (Let's Encrypt is a popular one) and an applicant to automate the process of verification and certificate issuance. The protocol also provides facilities for other certificate management functions, such as certificate revocation.

Installation Instructions

Once you have obtained [uacme][uacme] (see Installation above) the next step is creating an ACME account:

uacme -v -c /path/to/uacme.d new

The configuration directory and account private key should have been created:


You can then issue a certificate for your domain by doing

uacme -v -c /path/to/uacme.d issue

If everything goes well [uacme][uacme] asks you to set up a challenge, for example

uacme: challenge=http-01 token=kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4 key_auth=kZjqYgAss_sl4XXDfFq-jeQV1_lqsE76v2BoCGegFk4.2evcXalKLhAybRuxxE-HkSUihdzQ7ZDAKA9EZYrTXwU

Note the challenge type in the example is http-01 which means you should set up your web server to serve a URL based on the token:

The URL must return a text file containing a single line with the key authorization:


After setting up the web server you can then type 'y' followed by a newline. This notifies the ACME server that it can proceed with the challenge verification. If the procedure is successful [uacme][uacme] saves the certificate and the key at:

/path/to/uacme.d/ /path/to/uacme.d/private/

Note several challenge types are possible. If you type anything other than 'y', [uacme][uacme] skips the challenge and proposes a different one. The easiest is http-01 but any other type can be dealt with. Keep in mind that challenge types may be served in random order by the server. Do not make any assumptions and read what [uacme][uacme] outputs carefully.

Automating updates

Use the -h flag to manage the challenge with a hook script:

uacme -v -c /path/to/uacme.d -h /usr/share/uacme/ issue

or (depending on your installation)

uacme -v -c /path/to/uacme.d -h /usr/local/share/uacme/ issue

This will use the example [][] hook script included in the distribution to manage http-01 challenges. You might need to edit the script to match your webserver's environment.

Once everything works correctly you can also set up cron, for example

6 15 * * * /usr/bin/uacme -c /path/to/uacme.d -h /usr/share/uacme/ issue

The cron job will automatically update the certificate when needed. Note the absence of -v flag, this makes [uacme][uacme] only produce output upon errors.

Note also that you will need to restart or reload any service that uses the certificate, to make sure it uses the renewed one. This is system and installation dependent. I normally put the necessary instructions in another script (for example /usr/share/uacme/ that is executed by cron when [uacme][uacme] returns 0 (indicating the certificate has been reissued).

6 15 * * * /usr/bin/uacme -c /path/to/uacme.d -h /usr/share/uacme/ issue && /usr/share/uacme/

Check for a complete, ready-to-go solution.

dns-01 challenge support

The [][] hook script included in the distribution allows managing dns-01 challenges with [nsupdate][nsupdate]. This only works if your name server supports [RFC2136][RFC2136] ([bind][bind] does, [nsd][nsd] doesn't). is another example that works with [nsd][nsd]. shows how to integrate with [Cloudflare API][Cloudflare]. works with [][gandi].

tls-alpn-01 challenge support

[ualpn][ualpn] is a lightweight proxying [tls-alpn-01][RFC8737] challenge responder, designed to handle incoming HTTPS connections on port 443. Most of the time it just transparently proxies connections to the real web server (which can be on either another machine, or a different TCP port on the same machine). When a tls-alpn-01 challenge handshake comes in [ualpn][ualpn] handles it on the fly instead of proxying it to the webserver. This means that unlike other available tls-alpn-01 responders, [ualpn][ualpn] does not require your webserver to stop during the challenge (zero downtime).

The high performance event-driven implementation is based on [libev][libev] which considerably reduces the cost of context switches and memory usage. In addition on systems such as Linux supporting the [splice()][splice] system call, [ualpn][ualpn] is able to move network data entirely in kernel memory without a round trip to user space, which further enhances performance.

[ualpn][ualpn] also listens to a UNIX domain socket so that it can be fed the necessary tls-alpn-01 key authorizations for the domains being validated by the ACME server. [ualpn][ualpn] was designed to be easy to integrate with not only [uacme][uacme] (check the example [][] hook script) but also other ACME clients. A [certbot plugin][plugin] is also available.

To get started with [ualpn][ualpn]:

  • move your real HTTPS server to port 4443 which doesn't need to be open to the outside (only ualpn will connect to it) and set it up to accept the [PROXY protocol][proxy]:
    • for nginx:

      server { listen ssl proxy_protocol; set_real_ip_from; real_ip_header proxy_protocol; proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $proxy_protocol_addr; ...

    • for apache:

      Listen 4443 <VirtualHost *:4443> RemoteIPProxyProtocol On ...

  • launch [ualpn][ualpn] as a daemon and check the logs (by default in syslog)

    sudo ualpn -v -d -u nobody:nogroup -c -S 666

  • create an ACME account

    uacme -v -s -c /path/to/uacme.d -y new

  • try obtaining a certificate with tls-alpn-01 challenge

    uacme -v -s -c /path/to/uacme.d -h /usr/share/uacme/ issue

    or, depending on your installation

    uacme -v -s -c /path/to/uacme.d -h /usr/local/share/uacme/ issue

Active Releases

The following unofficial repositories are provided as-is by owner of this project. Contact the owner directly for bugs or issues (IE: not bugzilla).

* Total number of packages downloaded in the last seven days.

This is a companion discussion topic for the original entry at