README.md (5858B)
1 # Using the ACME examples 2 3 ACME is a protocol for obtaining TLS certificates automatically. Before 4 issuing a certificate, the ACME service checks that the domain is really 5 yours: it requests a specific resource from that domain over plain HTTP. The 6 examples in this directory are minimal servers that answer such requests. 7 8 There is no shortage of helper tools that take much of the fiddly work out of 9 using ACME. This guide uses [`acme.sh`](https://github.com/acmesh-official/acme.sh), 10 which is distributed under the excellent GNU General Public License version 3 11 (GPLv3). 12 13 For the setup described here, `acme.sh` can use either `wget` or `curl` to talk 14 to ACME servers, and the examples in this directory to answer their HTTP-01 15 challenge requests. Beyond that, it needs only OpenSSL for the cryptographic 16 work involved in obtaining certificates automatically, plus the usual 17 command-line utilities. This small set of requirements makes the combination 18 particularly handy for compact and embedded systems. 19 20 ## Getting the first certificate 21 22 The simplest way to create a certificate is to run the commands below. Replace 23 the example email address and domain name with your own values. 24 25 The commands use the server selected in the `acme.sh` configuration. Testing 26 with a staging server first is strongly recommended, as its certificates are 27 deliberately not publicly trusted. Add `--staging` to both `acme.sh` commands 28 below to use the staging server. Another service can be selected in the 29 `acme.sh` configuration or with its `--server` option. 30 31 Register an ACME account first: 32 33 ```sh 34 acme.sh --register-account \ 35 --email admin@example.com 36 ``` 37 38 Registration is needed only once (for each ACME server). Prepare a temporary 39 webroot, then start the MHD example and leave it running: 40 41 ```sh 42 mkdir -p /tmp/acme-check 43 ./acme_http_01_files --webroot /tmp/acme-check 80 44 ``` 45 46 The last argument is the local listening port. ACME HTTP-01 requests always 47 arrive on public port 80; if that port is forwarded to another local port, give 48 the forwarded-to port here instead. 49 50 In another terminal, ask `acme.sh` to issue the certificate: 51 52 ```sh 53 acme.sh --issue \ 54 --domain example.com \ 55 --webroot /tmp/acme-check 56 ``` 57 58 The example is needed only while the validation is running. Once `acme.sh` 59 has finished, stop the example by pressing ENTER in its terminal; all the 60 examples in this directory are stopped this way. 61 62 With the current `acme.sh` defaults, the files needed by MHD are 63 `~/.acme.sh/example.com_ecc/fullchain.cer` and 64 `~/.acme.sh/example.com_ecc/example.com.key`. The former already contains the 65 server certificate followed by its signing chain. Load the contents of both 66 files and pass them to MHD as the certificate chain and private key, 67 respectively. 68 69 To renew the certificate, start the example with the same webroot again and 70 run: 71 72 ```sh 73 acme.sh --renew --domain example.com 74 ``` 75 76 `acme.sh` remembers the webroot and ACME server used for issuance. If renewal 77 is not due yet, it simply skips the operation; use `--force` only when an 78 immediate renewal is really wanted. 79 80 The example does not have to run as a separate process. Its code can be 81 integrated directly into an application that keeps its main MHD daemon on a TLS 82 port. When certificate renewal is due, the application can start a second MHD 83 daemon on port 80 solely to answer ACME HTTP-01 challenges, then stop it after 84 the validation has finished. 85 86 If this simple file-based setup is all you need, you can stop reading here. 87 88 ## Getting a certificate with an account thumbprint 89 90 > **Warning:** This method is not recommended. While the server is running, 91 > it will confirm every syntactically valid HTTP-01 challenge request that 92 > reaches it for the selected ACME account. See RFC 8555, section 8.3. 93 94 The challenge files can be avoided by building each response from the request 95 token and the thumbprint of the ACME account key. The following single command 96 registers the account if needed, extracts its thumbprint and immediately starts 97 the MHD example server in `--naive` mode: 98 99 ```sh 100 ./acme_http_01_token --naive 80 "$(acme.sh --register-account \ 101 --email admin@example.com 2>&1 | \ 102 sed -n "s/.*ACCOUNT_THUMBPRINT='\([^']*\)'.*/\1/p")" 103 ``` 104 105 The extraction is possible because `acme.sh` reports the thumbprint in a 106 fixed form, as a single line with the value in quotes: 107 108 ```text 109 [Mon Sep 1 02:32:00 CEST 2026] ACCOUNT_THUMBPRINT='pkZoLgVnRb3rWG1mAaKQm3ZDb6xU_c0dOtd_uBaC5Ns' 110 ``` 111 112 The `sed` expression above takes the value from between the quotes, so the 113 thumbprint never has to be copied by hand. 114 115 The same command can be run again whenever the server is needed. For an 116 existing account, no new registration is performed: `acme.sh` simply prints 117 its current thumbprint. As above, add `--staging` to the `acme.sh` command 118 when testing on the staging server. 119 120 In another terminal, request the certificate in stateless mode, using the same 121 ACME server and account configuration: 122 123 ```sh 124 acme.sh --issue --stateless --domain example.com 125 ``` 126 127 Add `--staging` here as well when staging was selected for the account. Once 128 the validation has finished, press ENTER to stop the example. The certificate 129 and key are stored in the same locations described above. 130 131 For renewal, start the example with the same account thumbprint again and run: 132 133 ```sh 134 acme.sh --renew --domain example.com 135 ``` 136 137 `acme.sh` remembers both stateless mode and the ACME server used for issuance, 138 so neither needs to be repeated in the renewal command. Stop the example as 139 soon as validation has finished. 140 141 This example can be integrated into an application as well. The application 142 keeps the account thumbprint, starts a second MHD daemon on port 80 when the 143 renewal is due and stops it once the validation has finished. No files are 144 involved, so nothing has to be shared between the processes.