kelunik/acme-client
is an ACME client written in PHP. ACME is the protocol that powers the Let's Encrypt certificate authority.
- PHP 7.4+ with OpenSSL
- Works on Unix-like systems and Windows
Let's Encrypt / ACME client written in PHP for the CLI.
License: MIT License
kelunik/acme-client
is an ACME client written in PHP. ACME is the protocol that powers the Let's Encrypt certificate authority.
When doing as root:
acme-client issue -d f.domain.com:h.domain.com -p /var/www/html:/var/www/html
or
acme-client issue -d f.domain.com:h.domain.com -p /var/www/html
you get:
Providing payload at http://h.domain.com/.well-known/acme-challenge/VOC........
h.domain.com is now authorized.
(red)Could not obtain directory.
exception 'Kelunik\Acme\AcmeException' with message 'Issuance failed, not all challenges could be solved.' in phar:///usr/local/bin/acme-client/src/Commands/Issue.php:106(/red)
But:
acme-client issue -d h.domain.com:f.domain.com -p /var/www/html
works fine.
I use: php 5.6.30-0+deb8u1
acme-client.yml:
storage: /etc/acme
server: letsencrypt
I changed my real used domain in this text to 'domain.com'.
There should be an easy way to update the client from the command line.
Implement a way to show the current version and the version of the bundled dependencies.
With over 150 domains I am experiencing a few issue on renewal using the "auto" command:
...
Invalid response: .
Request URI: https://acme-v01.api.letsencrypt.org/acme/new-authz.
Invalid response: .
Request URI: https://acme-v01.api.letsencrypt.org/acme/new-authz.
exception 'Kelunik\Acme\AcmeException' with message 'Issuance failed, not all challenges could be solved.' in phar://acme-client/build/acme-client.phar/src/Commands/Issue.php:104
' in phar://acme-client/build/acme-client.phar/src/Commands/Auto.php:236
Stack trace:
#0 [internal function]: Kelunik\AcmeClient\Commands\Auto::checkAndIssue(Array, 'letsencrypt', '/etc/acme')
#1 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/functions.php(876): Generator->send(Object(stdClass))
#2 [internal function]: Amp\__coroutineSend(NULL, Object(stdClass), Object(Amp\CoroutineState))
#3 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/Placeholder.php(91): call_user_func('Amp\\__coroutine...', NULL, Object(stdClass), Object(Amp\CoroutineState))
#4 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/PrivatePromisor.php(20): Amp\PrivatePlaceholder->resolve(NULL, Object(stdClass))
#5 [internal function]: Amp\PrivatePlaceholder->Amp\{closure}(NULL, Object(stdClass))
#6 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/PrivatePromisor.php(57): call_user_func(Object(Closure), NULL, Object(stdClass))
#7 phar://acme-client/build/acme-client.phar/vendor/amphp/process/Process.php(106): Amp\Deferred->succeed(Object(stdClass))
#8 [internal function]: Amp\Process->Amp\{closure}('00000000511c7e9...', NULL)
#9 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(100): call_user_func(Object(Closure), '00000000511c7e9...', NULL)
#10 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(172): Amp\NativeReactor->tryImmediate(Object(stdClass))
#11 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(71): Amp\NativeReactor->doTick(false)
#12 phar://acme-client/build/acme-client.phar/vendor/amphp/amp/lib/functions.php(46): Amp\NativeReactor->run(Object(Closure))
#13 phar://acme-client/build/acme-client.phar/bin/acme(170): Amp\run(Object(Closure))
#14 acme-client/build/acme-client.phar(2): include('phar:///root/Do...')
#15 {main}
To me it looks like I am hitting rate limits and thus the invalid response is received?
I mentioned this briefly before already.
It's nice that acme-client is asynchronous but I guess there is still an issue with that feature if you renew certs for many domains.
The following patch fixes it completely and all domains "auto" renew in one go just fine (although the overall process takes a bit longer with the patch, reliability is more important to me than super fast execution in a "90-day renewal timeframe"...):
diff --git a/src/Commands/Auto.php b/src/Commands/Auto.php
index 974280e..9a8082f 100644
--- a/src/Commands/Auto.php
+++ b/src/Commands/Auto.php
@@ -119,16 +119,13 @@ class Auto implements Command {
$values = [];
foreach ($certificateChunks as $certificateChunk) {
- $promises = [];
-
foreach ($certificateChunk as $certificate) {
+ $promises = [];
$promises[] = \Amp\resolve($this->checkAndIssue($certificate, $config["server"], $config["storage"]));
+ list($chunkErrors, $chunkValues) = (yield \Amp\any($promises));
+ $errors += $chunkErrors;
+ $values += $chunkValues;
}
-
- list($chunkErrors, $chunkValues) = (yield \Amp\any($promises));
-
- $errors += $chunkErrors;
- $values += $chunkValues;
}
$status = [
diff --git a/src/Commands/Issue.php b/src/Commands/Issue.php
index 864fdd2..79fbc4b 100644
--- a/src/Commands/Issue.php
+++ b/src/Commands/Issue.php
@@ -85,15 +85,12 @@ class Issue implements Command {
$domainChunks = array_chunk($domains, 10, true);
foreach ($domainChunks as $domainChunk) {
- $promises = [];
-
foreach ($domainChunk as $i => $domain) {
+ $promises = [];
$promises[] = \Amp\resolve($this->solveChallenge($acme, $keyPair, $domain, $docRoots[$i]));
+ list($chunkErrors) = (yield \Amp\any($promises));
+ $errors += $chunkErrors;
}
-
- list($chunkErrors) = (yield \Amp\any($promises));
-
- $errors += $chunkErrors;
}
if (!empty($errors)) {
The current solution is fine for using the client manually and scripting things, but it's not optimal to just automate a few domains in a few different certificates.
We already have a acme-config.yml
. We could extend it:
# Currently existing config variables
storage: /etc/acme
server: letsencrypt
# Important for expiry e-mails from Let's Encrypt
email: [email protected]
# Certificates to issue and renew
certificates:
- domains: ["a.com", "www.a.com"]
paths: ["/var/www/a.com"]
- domains: ["b.com", "www.b.com"]
paths: ["/var/www/b.com"]
user: www-data
We could then use a command like acme-client auto
to automatically do registration, issuance and renewal whenever invoked. Additionally, we could provide another --config
option, so it's possible to separate configs.
We might need an additional configuration option for a script to execute after renewal happened to restart the server or so. I don't know if that should be global per config file or per certificate. I think global makes sense if we have the --config
switch.
ACME.ERROR: Kelunik\Acme\AcmeException: No MX record defined for 'yandex.ru' in ~/acme-client/src/Commands/Register.php:97
Seeing a potential problem where the --ttl option appears to be ignored with the auto command.
From what I can see from the code, it looks like the ttl value is not being passed to the check request within the checkAndIssue function.
When running commands manually, i get...
C:\.....\ssl.le>php acme-client.phar check --name www.doneworking.com
Certificate is valid until 24.07.2017
C:\.....\ssl.le>echo %errorlevel%
0C:\.....\ssl.le>php acme-client.phar check --name www.doneworking.com --ttl 45
Certificate is valid until 24.07.2017
Certificate is going to expire within the specified 45 days.
C:\.....\ssl.le>echo %errorlevel%
1C:\.....\ssl.le>php acme-client.phar auto --ttl 45
C:\.....\ssl.le>echo %errorlevel%
0
0 = Nothing to do, all certs still valid
My guess is that the check call within checkAndIssue is not seeing the ttl value.
Providing payload at http://www.mydomain.com/.well-known/acme-challenge/7-smHbOwopaRKn2-zTmvxEvLe83x2HjG875uecm6Yk8
Providing payload at http://mydomain.com/.well-known/acme-challenge/sl9WKbCDYyK-DEObXWIHTaCiukm0vjQvMAzQDxk0uW8
selfVerify failed, please check http://www.mydomain.com/.well-known/acme-challenge/7-smHbOwopaRKn2-zTmvxEvLe83x2HjG875uecm6Yk8.
selfVerify failed, please check http://mydomain.com/.well-known/acme-challenge/sl9WKbCDYyK-DEObXWIHTaCiukm0vjQvMAzQDxk0uW8.
Kelunik\Acme\AcmeException: Issuance failed, not all challenges could be solved. in /home/u57374xxxx/acme-client/src/Commands/Issue.php:106
kelunik@s18149550:~$ acme-client setup --email [email protected]
No private key found, generating new one ...
Warning: mkdir(): Permission denied in phar:///usr/local/bin/acme-client/src/Stores/KeyStore.php on line 71
Amp\File\FilesystemException: file_put_contents(/etc/acme/accounts/acme-v01.api.letsencrypt.org.directory.pem): failed to open stream: No such file or directory in phar:///usr/local/bin/acme-client/vendor/amphp/file/lib/BlockingDriver.php:289
Next Kelunik\AcmeClient\Stores\KeyStoreException: Could not save key. in phar:///usr/local/bin/acme-client/src/Stores/KeyStore.php:77
This should result in a nice error message instead.
It is imperative to support PHP 5.x because that is what almost all real servers use. PHP 7 may take another year (or two) to reach enterprise Linux distros. We all run PHP 7 on our desktop computers, but this project is related to certificates on servers.
Forcing PHP 7 as a requirement is really killing this project.
ACME has some forms of account recovery, if a key is lost. Implement them.
I've got the client up and running on Windows, I've managed to register as a new user, and have set up a acme-client.yml global config file. All good so far.
Manually I can successfully obtain new certificates with the command:
acme-client.phar issue -d my.domain.com -p "D:/data/web/website"
However when I use 'acme-client auto' and try to use the certificates config from the .yml file I get an error: "Notice: undefined index: paths in ....... /Auto.php on line 178"
So apparently it can't read the certificates config in the .yml file properly, but what am I doing wrong in the following config section for that (after the storage, server and email section):
certificates:
paths:
"D:/data/web/website":
- my.domain.com
Any ideas greatly appreciated :-)
The docs example for a cron entry to run the auto command:
0 0 * * * acme-client auto; exit=$?; if [[ $exit = 4 ]] || [[ $exit = 5 ]]; then service nginx reload; fi
is not ideal, because it uses a bashism: [[
.
At least Ubuntu and maybe others use dash as the system shell, so this command fails.
Single [
works fine and is POSIX compliant. So:
0 0 * * * acme-client auto; exit=$?; if [ $exit = 4 ] || [ $exit = 5 ]; then service nginx reload; fi
works in bash or dash and probably most other shells.
For this to work, we need to change the ./data
directory, which is currently hardcoded.
Provide a possibility to provide a different storage directory than ./data
.
Thanks for writing this PHP client. It appears to be just what I need, but the problem I'm having is that my web server is not running on port 80, and when trying to install a cert I get an error to that effect:
Connection to tcp://myserver.com:80 failed: timeout exceeded (30000 ms) exception 'Kelunik\Acme\AcmeException' with message 'Issuance failed, not all challenges could be solved.' in phar://C:/LetsEncrypt/acme-client.phar/src/Commands/Issue.php:104
If I try to include the port number in the domain, it doesn't like that either:
exception 'Kelunik\Acme\AcmeException' with message 'Couldn't resolve the following domains to an IPv4 nor IPv6 record: 1234' in phar://C:/LetsEncrypt/acme-client.phar/src/Commands/Issue.php:197
Any help appreciated. Thanks!
Hello,
First thanks for the tools !
I've an error on my server (i've replaced real url with "exemple.com").
The same command /config work fine with the staging letsencrupt server.
When i try the the normale serveur i get the following error messsage :
What can cause that ? a missing package ?
The error :
Issuance for the following domains failed: exemple.com
Reason: exception 'Kelunik\Acme\AcmeException' with message 'Unexpected exit code (1) for ''/usr/bin/php' '/usr/bin/acme-client' 'issue' '--server' 'letsencrypt' '--storage' '/data/htdocs/letsencrypt_keys' '--domains' 'exemple.com' '--path' '/data/htdocs/acme' '--bits' '4096''.
Providing payload at http://exemple.com/.well-known/acme-challenge/mHJsDyc9NzAijTjxWb7Iwq4y0BYxqgELYn5Hl_y_2v0
Socket connection failed before data could be fully written. This *may* have occurred because you're attempting to connect via HTTP when the remote server only supports encrypted HTTPS connections. Try your request using an https:// URI.
exception 'Kelunik\Acme\AcmeException' with message 'Issuance failed, not all challenges could be solved.' in phar:///usr/bin/acme-client/src/Commands/Issue.php:104
' in phar:///usr/bin/acme-client/src/Commands/Auto.php:239
Stack trace:
#0 [internal function]: Kelunik\AcmeClient\Commands\Auto::checkAndIssue(Array, 'letsencrypt', '/data/htdocs/le...')
#1 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/functions.php(876): Generator->send(Object(stdClass))
#2 [internal function]: Amp\__coroutineSend(NULL, Object(stdClass), Object(Amp\CoroutineState))
#3 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/Placeholder.php(91): call_user_func('Amp\\__coroutine...', NULL, Object(stdClass), Object(Amp\CoroutineState))
#4 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/PrivatePromisor.php(20): Amp\PrivatePlaceholder->resolve(NULL, Object(stdClass))
#5 [internal function]: Amp\PrivatePlaceholder->Amp\{closure}(NULL, Object(stdClass))
#6 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/PrivatePromisor.php(57): call_user_func(Object(Closure), NULL, Object(stdClass))
#7 phar:///usr/bin/acme-client/vendor/amphp/process/Process.php(106): Amp\Deferred->succeed(Object(stdClass))
#8 [internal function]: Amp\Process->Amp\{closure}('0000000046df489...', NULL)
#9 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/NativeReactor.php(100): call_user_func(Object(Closure), '0000000046df489...', NULL)
#10 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/NativeReactor.php(172): Amp\NativeReactor->tryImmediate(Object(stdClass))
#11 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/NativeReactor.php(71): Amp\NativeReactor->doTick(false)
#12 phar:///usr/bin/acme-client/vendor/amphp/amp/lib/functions.php(46): Amp\NativeReactor->run(Object(Closure))
#13 phar:///usr/bin/acme-client/bin/acme(170): Amp\run(Object(Closure))
#14 /usr/bin/acme-client(2): include('phar:///usr/bin...')
#15 {main}
My command (after account creation) :
acme-client auto -c /data/htdocs/myscript/acme-client.yml
acme-client.yml file :
# Storage directory for certificates and keys.
storage: /data/htdocs/letsencrypt_keys
# Server to use. URL to the ACME directory.
# "letsencrypt" and "letsencrypt:staging" are valid shortcuts.
server: letsencrypt
# E-mail to use for the setup.
# This e-mail will receive expiration notices from Let's Encrypt.
email: [email protected]
# List of certificates to issue.
certificates:
# For each certificate, there are a few options.
#
# Required: paths
# Optional: bits, user
#
# paths: Map of document roots to domains. Maps each path to one or multiple
# domains. If one domain is given, it's automatically converted to an
# array. The first domain will be the common name.
#
# The client will place a file into $path/.well-known/acme-challenge/
# to verify ownership to the CA
#
# bits: Number of bits for the domain private key
#
# user: User running the web server. Challenge files are world readable,
# but some servers might require to be owner of files they serve.
#
- bits: 4096
paths:
/data/htdocs/acme:
- exemple.com
# You can have multiple certificate with different users and key options.
#- user: www-data
# paths:
# /var/www: example.org
I also like the new auto option, but having problems generating certificates where multiple domains map to the same directory.
As a simple example, if I want a certificate for both www.example.org and example.org, I would include this in acme-client.yml config file:
certificates:
- paths:
/www/example: www.example.org
/www/example: example.org
I do get a single SSL certificate, but only the first domain – www.example.org – is included as both names are using the same directory.
One way around this would be to swap the path and domain, as the domain is always going to be unique within a single certificate.
certificates:
- paths:
www.example.org: /www/example
example.org: /www/example
Any suggestions?
Running auto command with -c flag makes -s and --storage flags to be required despite this information being available in config file. In case of conflict between flag and config file what will be used?
-bash-4.1$ sudo ./acme-client.phar auto -s letsencrypt:staging -c /www/prod/external/lib/acme-client/my_prod_server/acme-client.yml
Usage: ./acme-client.phar auto [-c config, --config config] [-s server, --server server] [--storage storage]
Required Arguments:
-s server, --server server
ACME server to use for registration and issuance of certificates.
--storage storage
Storage directory for account keys and certificates.
-c config, --config config
Configuration file to read.
The following arguments are required: [--storage storage].
Is there any conflicts or issues having official letsencrypt client installed + this acme-client ?
could renewal be done by either official letsencrypt client OR acme-client interchangeably ?
looking at alternatives for low memory 128MB to 512MB VPS systems certbot/certbot#1081
can I use same email address to register with official letsencrypt client AND acme-client ?
cheers
George
Seeing same issue as #33 but with just 7 domains. Reduce list to 6 and all is well. Running version 0.2.11 under Windows 2008 Server and PHP 7.1 in a virtual environment, using a .yml file.
Error comes thru as something like...
C:\Apache24\conf\ssl.le>php acme-client.phar auto --ttl 45
Issuance for the following domains failed: older-browser.lodesys.com, aidswalkaz
.org, casadecristo.org, lodesys.com, redbrunch.org, redisthenight.org, thehopeta
pes.com
Reason: Kelunik\Acme\AcmeException: Unexpected exit code (1) for '"C:\php\php.ex
e" "acme-client.phar" "issue" "--server" "letsencrypt" "--storage" "/Apache24/co
nf/ssl.le" "--domains" "older-browser.lodesys.com,aidswalkaz.org,casadecristo.or
g,lodesys.com,redbrunch.org,redisthenight.org,thehopetapes.com" "--path" "/web-s
ites/_LetsEncrypt;/web-sites/_LetsEncrypt;/web-sites/_LetsEncrypt;/web-sites/_Le
tsEncrypt;/web-sites/_LetsEncrypt;/web-sites/_LetsEncrypt;/web-sites/_LetsEncryp
t"'.
Kelunik\Acme\AcmeException: Couldn't resolve the following domains to an IPv4 no
r IPv6 record: redbrunch.org, thehopetapes.com in phar://C:/Apache24/conf/ssl.le
/acme-client.phar/src/Commands/Issue.php:197
in phar://C:/Apache24/conf/ssl.le/acme-client.phar/src/Commands/Auto.php:239
Stack trace:
#0 [internal function]: Kelunik\AcmeClient\Commands\Auto->checkAndIssue(Array, '
letsencrypt', '/Apache24/conf/...')
#1 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/function
s.php(876): Generator->send(Object(stdClass))
#2 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/Placehol
der.php(91): Amp\__coroutineSend(NULL, Object(stdClass), Object(Amp\CoroutineSta
te))
#3 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/PublicPr
omisor.php(48): Amp\Deferred->resolve(NULL, Object(stdClass))
#4 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/process/Process.
php(106): Amp\Deferred->succeed(Object(stdClass))
#5 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/NativeRe
actor.php(100): Amp\Process->Amp\{closure}('000000002a25e11...', NULL)
#6 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/NativeRe
actor.php(172): Amp\NativeReactor->tryImmediate(Object(stdClass))
#7 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/NativeRe
actor.php(71): Amp\NativeReactor->doTick(false)
#8 phar://C:/Apache24/conf/ssl.le/acme-client.phar/vendor/amphp/amp/lib/function
s.php(46): Amp\NativeReactor->run(Object(Closure))
#9 phar://C:/Apache24/conf/ssl.le/acme-client.phar/bin/acme(170): Amp\run(Object
(Closure))
#10 C:\Apache24\conf\ssl.le\acme-client.phar(2): include('phar://C:/Apach...')
#11 {main}
Sometimes it has problems resolving just redbrunch.org domain.
The corresponding part of the .yml file is
- paths:
/web-sites/_LetsEncrypt:
- older-browser.lodesys.com
- aidswalkaz.org
- casadecristo.org
- lodesys.com
- redbrunch.org
- redisthenight.org
- thehopetapes.com
Eliminate one of the domains, and all is well. Using the letsencrypt staging server produces the same results.
Seems to be some sort of timing or time-out issue, but have not been able to narrow it down.
Hi Niklas,
I use acme-client extensively, in many of my servers, and couldn't be happier with it. Thanks for the awesome work you have put in!
I noticed some of the recent Github issues are about the users getting selfVerify
validation errors. I was wondering if it would be better if we expose more information to help them debug why it failed.
Most Apache configurations block dot-directories with a 403 error, and if we show the response status code returned from Artax (404, 403, 500, etc), it gives a hint if the web server is blocking the request. 404 requests could indicate a wrong doc root used in the issue
command, likewise.
Thanks.
I'm really sorry!
When trying to create a certificate (using auto command) with more than 48 domains I get error message as below. If I comment out one domain so I have 48 it works.
I'm not sure the limit is exactly 48 domains but somewhere close to it. It seems I get different results on number of domains depending on which I have in my file so maybe it is a line length limitation issue (?).
Acme-Client 0.2.8, PHP 5.6, Centos 6.5, bash
Error message and stack trace:
Issuance for the following domains failed: site1.example.com,site2.example.com,...,site49.example.com
Reason: exception 'Kelunik\Acme\AcmeException' with message 'Unexpected exit code (1) for ''/usr/bin/php' './acme-client.phar' 'issue' '--server' 'letsencrypt' '--storage' '/etc/acme' '--domains' 'site1.example.com,site2.example.com,...,site49.example.com' '--path' '/www/site1/htdocs:/www/site1/htdocs:...:/www/site49/htdocs''.
exception 'Kelunik\Acme\AcmeException' with message 'Couldn't resolve the following domains to an IPv4 record: site1.example.com' in phar:///www/prod/external/lib/acme-client/acme-client.phar/src/Commands/Issue.php:181
' in phar:///www/prod/external/lib/acme-client/acme-client.phar/src/Commands/Auto.php:215
Stack trace:
#0 [internal function]: Kelunik\AcmeClient\Commands\Auto::checkAndIssue(Array, 'letsencrypt', '/etc/acme')
#1 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/functions.php(876): Generator->send(Object(stdClass))
#2 [internal function]: Amp__coroutineSend(NULL, Object(stdClass), Object(Amp\CoroutineState))
#3 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/Placeholder.php(91): call_user_func('Amp__coroutine...', NULL, Object(stdClass), Object(Amp\CoroutineState))
#4 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/PrivatePromisor.php(20): Amp\PrivatePlaceholder->resolve(NULL, Object(stdClass))
#5 [internal function]: Amp\PrivatePlaceholder->Amp{closure}(NULL, Object(stdClass))
#6 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/PrivatePromisor.php(57): call_user_func(Object(Closure), NULL, Object(stdClass))
#7 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/process/Process.php(102): Amp\Deferred->succeed(Object(stdClass))
#8 [internal function]: Amp\Process->Amp{closure}('00000000007fbd7...', NULL)
#9 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(100): call_user_func(Object(Closure), '00000000007fbd7...', NULL)
#10 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(172): Amp\NativeReactor->tryImmediate(Object(stdClass))
#11 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/NativeReactor.php(71): Amp\NativeReactor->doTick(false)
#12 phar:///www/prod/external/lib/acme-client/acme-client.phar/vendor/amphp/amp/lib/functions.php(46): Amp\NativeReactor->run(Object(Closure))
#13 phar:///www/prod/external/lib/acme-client/acme-client.phar/bin/acme(165): Amp\run(Object(Closure))
#14 /www/prod/external/lib/acme-client/acme-client.phar(2): include('phar:///www/pro...')
#15 {main}
Is there anything in this package that actually requires PHP 7.0.0?
Depends on kelunik/acme#14.
I get the following error consistently, when using "setup", and only when using the PHAR but works perfectly using the Composer installed version:
No private key found, generating new one ...
Generated new private key with 4096 bits.
Registering with acme-staging.api.letsencrypt.org/directory ...
exception 'Amp\Socket\CryptoException' with message 'Crypto negotiation failed: stream_socket_enable_crypto(): failed to create an SSL handle' in phar:///home/fitzroyd/public_html/app/Console/acme-client.phar/vendor/amphp/socket/lib/functions.php:302
Next exception 'Kelunik\Acme\AcmeException' with message 'Could not obtain directory.' in phar:///home/fitzroyd/public_html/app/Console/acme-client.phar/vendor/kelunik/acme/lib/AcmeClient.php:189
Example command issued:
./acme-client.phar setup --email [email protected] -s https://acme-staging.api.letsencrypt.org/directory --storage /home/domain/.LetsEncrypt
Sorry if this is a double-up - I've seen similar issues but I'm not sure if this one has been addressed. May be related to #16
I really like the new auto option but I have some issues with getting it to work. Maybe it's because I'm not so good at YAML. It would be nice with some more examples on how to configure different cases.
An example:
I want to have two sites with different certificates so I put this in config file:
certificates:
- paths:
- /www/example1: site1.example.org
- /www/example2: site2.example.org
But then I get:
Issuance for the following domains failed: site1.example.org, site2.example.org
Reason: exception 'Kelunik\Acme\AcmeException' with message 'Unexpected exit code (1) for ''/usr/bin/php' './acme-client.phar' 'issue' '--server' 'letsencrypt' '--storage' '/etc/acme' '--domains' 'site1.example.org, site2.example.org' '--path' '0:1''.
If I try:
certificates:
- paths:
/www/example1: site1.example.org
/www/example2: site2.example.org
I get both sites in one certificate with name from the first site. Which I guess makes sense (at least if one is used to the issue command) and which will probably work as long as I don't have more than the limit of sites for one certificate.
Tested on 0.2.7
Hi There,
This might be a (simple?) issue with an upstream project but I'll report it where I found it :)
C:\exec>acme-client issue -d sso.<DOMAIN> -p C:\exec\Crowd\crowd-webapp
Providing payload at http://sso.<DOMAIN>/.well-known/acme-challenge/<CHALLANGE>
Fatal error: Uncaught Error: Call to undefined function idn_to_ascii() in phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Cookie/PublicSuffixList.php:76
Stack trace:
#0 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Cookie/PublicSuffixList.php(61): Amp\Artax\Cookie\PublicSuffixList::toRegex('a\xC3\xA9roport.ci', false)
#1 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Cookie/PublicSuffixList.php(13): Amp\Artax\Cookie\PublicSuffixList::readList()
#2 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Client.php(666): Amp\Artax\Cookie\PublicSuffixList::isPublicSuffix('<DOMAIN>')
#3 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Client.php(531): Amp\Artax\Client->storeResponseCookie('sso.<DOMAIN>', '__cfduid=d9dfb8...')
#4 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Client.php(489): Amp\Artax\Client->assignParsedResponse(Object(Amp\Artax\RequestCycle), Array)
#5 phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Client.php(476): Amp\Artax\Client->parseSocketData(Object(A in phar://C:/exec/acme-client.phar/vendor/amphp/artax/lib/Cookie/PublicSuffixList.php on line 76
So amphp/artax
appears to rely on the intl extension. Is this a known requirement of this project? If not, can this exception be trapped and handled accordingly? If it is a requirement, perhaps a better message is in order. Regardless, it's a good error handling policy to trap and convert known exceptions to sane and useful error messages.
C:\exec>acme-client version
Γöî kelunik/acme-client @ 0.2.14 (built: May 10th 2017 08:32:52 UTC)
Γöö Let's Encrypt / ACME client written in PHP for the CLI.
C:\exec>php -v
PHP 7.1.3 (cli) (built: Mar 14 2017 23:33:39) ( ZTS MSVC14 (Visual C++ 2015) x64 )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
Dependency of your repo, amphp/dns
, behaves weirdly on my local pc and hosting, despite that php native gethostbyname
works without any problems. It persistently gives me 'All name resolution requests failed' for some servers, let it be google.com
or github.com
.
Would be cool if it was possible to set custom nameserver by some additional command line option ;)
Using the last release I got this error at the first step.
Running php acme-client.phar setup --email [email protected]
throws me
exception 'Kelunik\Acme\AcmeException' with message 'No MX record defined for 'domain.com'' in phar://D:/WWW/le/acme-client.phar/src/Commands/Setup.php:84
MX-record for domain allready exists.
What's wrong?
for some shared hosting envs it would be awesome to have the ability to run the client as non root user
I have the following error and I can't figure out what is causing it. I can use DNS normally with dig but this asynchronous resolver fails to work.
[2016-01-21 17:22:09] ACME.INFO: Generating key keys ...
[2016-01-21 17:22:10] ACME.INFO: Registering with ACME server acme-v01.api.letsencrypt.org/directory ...
[2016-01-21 17:22:11] ACME.ERROR: Amp\CombinatorException: All promises passed to Amp\some() failed
[2016-01-21 17:22:11] ACME.ERROR: UnexpectedValueException: Decode error: Incomplete packet (tried to read 4 bytes from index 510 in /home/ciapi/acme-client/vendor/daverandom/libdns/src/Decoder/Decoder.php:111
[2016-01-21 17:22:11] ACME.ERROR: Next Amp\Dns\ResolutionException: Response decode error in /home/ciapi/acme-client/vendor/amphp/dns/lib/functions.php:542
[2016-01-21 17:22:11] ACME.ERROR: UnexpectedValueException: Decode error: Incomplete packet (tried to read 4 bytes from index 510 in /home/ciapi/acme-client/vendor/daverandom/libdns/src/Decoder/Decoder.php:111
[2016-01-21 17:22:11] ACME.ERROR: Next Amp\Dns\ResolutionException: Response decode error in /home/ciapi/acme-client/vendor/amphp/dns/lib/functions.php:542
[2016-01-21 17:22:11] ACME.ERROR: UnexpectedValueException: Decode error: Incomplete packet (tried to read 4 bytes from index 510 in /home/ciapi/acme-client/vendor/daverandom/libdns/src/Decoder/Decoder.php:111
[2016-01-21 17:22:11] ACME.ERROR: Next Amp\Dns\ResolutionException: Response decode error in /home/ciapi/acme-client/vendor/amphp/dns/lib/functions.php:542
[2016-01-21 17:22:11] ACME.ERROR: UnexpectedValueException: Decode error: Incomplete packet (tried to read 4 bytes from index 510 in /home/ciapi/acme-client/vendor/daverandom/libdns/src/Decoder/Decoder.php:111
[2016-01-21 17:22:11] ACME.ERROR: Next Amp\Dns\ResolutionException: Response decode error in /home/ciapi/acme-client/vendor/amphp/dns/lib/functions.php:542
[2016-01-21 17:22:11] ACME.ERROR: Next Amp\Dns\ResolutionException: All name resolution requests failed in /home/ciapi/acme-client/vendor/amphp/dns/lib/functions.php:266
[2016-01-21 17:22:11] ACME.ERROR: Next Kelunik\Acme\AcmeException: Could not obtain directory. in /home/ciapi/acme-client/vendor/kelunik/acme/lib/AcmeClient.php:118
ACME allows for account key rotation. There should be support for that.
Hi folks,
I'm trying configure the certification on my hosting, but all time I received the error below. Could you provide me some help?
selfVerify failed, please check http://webmail.mydomain/.well-known/acme-challenge/xVqhrAXQ1VGvee2x-I2tqRnTf_Ywqu5E0GLepS37168. Kelunik\Acme\AcmeException: Issuance failed, not all challenges could be solved. in /home/myhome/downs/acme-client/src/Commands/Issue.php:106
[ ]s
R. Martins
There should be an option like --renew-key
or --rekey
for the issue
subcommand, that generates a new private key, even if another key already exists.
Running the code
sudo bin/acme issue \
--server acme-v01.api.letsencrypt.org/directory \
--domains bratteng.xyz,www.bratteng.xyz \
--path /home/nginx/bratteng.xyz/ssl
And I'm getting the error
[2016-01-17 08:33:40] ACME.INFO: Checked DNS records, all fine.
[2016-01-17 08:33:40] ACME.INFO: Found account keys.
[2016-01-17 08:33:40] ACME.DEBUG: Generating payload...
[2016-01-17 08:33:40] ACME.ERROR: Kelunik\Acme\AcmeException: Unknown user: www-data in /root/acme-client/src/Commands/Issue.php:88
Running latest version of nginx and php
If a domain is added to an existing configuration, but the certificate is still valid, the certificate isn't renewed to include the new name yet.
I keep getting the below error, upon attempting to issue certificates for any number of my domains.
$ acme-client issue --bits 4096 -d www.URL1.com:URL1.com:www.URL2.com:URL2.com -p $HOME/public_html:$HOME/addon_domains/URL2
selfVerify failed, please check http://PLACEHOLDER-URL.com/.well-known/acme-challenge/CmheUieDk5C-46IPqyiCsAByScw--Ete_2J43FhSnyE.
Challenge marked as invalid!
Challenge marked as invalid!
exception 'Kelunik\Acme\AcmeException' with message 'Issuance failed, not all challenges could be solved.' in phar:///$HOME/bin/acme-client/src/Commands/Issue.php:104
The specified directories exist and also contain a .well-known/acme-challenge directory with read/write permissions; yet, no challenges are even being written to those directories, which is likely resulting in the issue.
as letsencrypt is now in production mode, the --server argument should be deprecated or not set as mandatory to make the commands more readable 😄
When challenge file creation fails for any reason (non-existing document root, wrong permissions, and so on), ChallengeStore::doPut()
throws a ChallengeStoreException
and corresponding promise returned by ChallengeStore::put()
fails. However, Issue::solveChallenge()
doesn't check this promise, so the challenge process fails on self-check (yield $acme->verifyHttp01Challenge($domain, $token, $payload);
) without any indication on why the challenge file wasn't created.
Sometimes on slow connections I get this error Name resolution timed out
. Is any options available for customize network timeouts(if this is network timeouts of course)?
Great work, This issue I am having is with the cron renewal: error:
PHP Fatal error: Undefined constant 'STDOUT' in /home/username/acme-client/vendor/league/climate/src/Util/Writer/StdOut.php on line 14
shared hosting using a cron job set up in cpanel. I cant seem to find an answer to this?
Any ideas thanks for your help:)
see: #55
$ acme-client auto
TypeError: Argument 1 passed to Kelunik\AcmeClient\Commands\Auto::toDomainPathMap() must be of the type array, null given, called in /usr/home/czat/acme-client/src/Commands/Auto.php on line 181 and defined in /usr/home/czat/acme-client/src/Commands/Auto.php:257
Issueing a new certificate fails with the following error message:
Fatal error: Call to undefined function Kelunik\AcmeClient\getServer() in
/htdocs/.../resources/letsencrypt/src/Commands/Issue.php on line 40
When I use acme-client to request a certificate for several domains at once (e.g. with --domains mysite.com,www.mysite.com), I only get a certificate for the first domain in the list.
While challenge/auth for every domain listed takes place, the X509v3 Subject Alternative Name field in the resulting certificate contains just the same single value as the CN field.
I'm not sure whether this is a problem with the acme-client or the library (or if I'm just being stupid). If you need any additional information, I'd be glad to help.
Hi!
I've found this https://github.com/kelunik/acme-client/blob/master/src/Commands/Issue.php#L101-L107 in code. Maybe it's better to throw an real exception message instead of Issuance failed, not all challenges could be solved.
? Because in current implementation foreach is useless.
Add a way to get the version of the client
[shawn@web acme-challenge]$ /usr/local/bin/acme-client issue -d DOMAIN.com -p /PATH/TO/web
Providing payload at http://DOMAIN.com/.well-known/acme-challenge/_2Jw33jIHPAk1557R1QXNXul9VCtXTQ5dKZGt8KtxrA
selfVerify failed, please check http://DOMAIN.com/.well-known/acme-challenge/_2Jw33jIHPAk1557R1QXNXul9VCtXTQ5dKZGt8KtxrA.
Kelunik\Acme\AcmeException: Issuance failed, not all challenges could be solved. in phar:///usr/local/bin/acme-client/src/Commands/Issue.php:104
So, the path is right because it makes a .well-known folder in the webroot, and in it is an acme-challenge folder. But I cannot catch it while the file is there before the solving fails.
Sometimes I am not interested in the output of the commands I just need the exit code.
For this it would be nice to have a quiet flag.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.