I don’t think this really ought to be the support channel for acme.sh, but I’m not aware of another one other than filing an issue against it–if there’s one that I’m missing, please let me know.
I’m wanting to automate installation of the cert in an iXSystems TrueCommand system. This can be done with a relatively straightforward API call using this command: curl -l -g --data "{\"args\" : { \"pem\" : \"$(cat fullchain.cer)\", \"key\" : \"$(cat domain.key)\" } }" -u "user:pass" -X GET http://localhost/api/ssl/cert_import
Ordinarily I’d run acme.sh --install-cert -d whatever --renew-hook "long command with arguments". Simple enough in the normal case, but when the command includes, quotes, escaped quotes, command substitution, etc., I’m concerned that it might not get recorded correctly. What would be the best way to do this? Two possibilities come to mind:
Write a separate script to run this command (and optionally parse the result), and call that as the renew hook
Base64-encode the entire command string, edit .acme.sh/domain/domain.conf, and insert that value for Le_RenewHook Nope, this doesn’t do it–unless there’s an additional trick I’m missing. It simply tries to execute the base64-encoded string
Reissue the cert enclosing the command (as suggested by Osiris below) in single quotes
Thoughts between these, or a better way to make this happen?
That seems like it would be a much simpler answer (and carries with it the very real possibility that I was missing something really obvious), but when I tried it, no change was made anywhere. I wonder if the --install-cert command needs to have paths to create copies of at least one of the cert/key/chain files? Seems an odd requirement if so.
So in the .conf file, Le_RenewHook is set (by default) to an empty value enclosed by single quotes (''). I pasted in the base64-encoded string, which (as I said above) it tries to execute. But on reviewing the .conf file, I see that the value was changed into a different base64-encoded value, prefixed with __ACME_BASE64__START_ and followed by __ACME_BASE64__END_. I didn't decode it, but I'd bet it was the original encoded string, re-encoded with base64.
I expect the thing to do here is (as Osiris suggested) simply paste in the command between the single quotes. Since I don't know of a way to test it without forcing a new cert issuance, I'll give it a few days before I run it again to avoid any rate limit issues.
You can always put these commands into a bash file and ask acme.sh to execute the bash file instead, right?
According to dev, when using a hook you can also read the path of certificate/keys from env variable.
P.S. You don’t need to reissue one, just request a certificate in staging environment and run that instead.
The renew hook will always be converted to base64 and add the ACME_BASE64_START and End.
Yeah, that's my first bullet. I'm not too keen on creating an external script just to run a single command, but it would definitely avoid the issues I mentioned.
After a few days’ wait, and seeing what happened with the base64-encoded string I’d previously put in the .conf file, I tried a slightly different tactic. I still directly edited the .conf file, but I edited it to Le_RenewHook='curl -l -g --data "{\"args\" : { \"pem\" : \"$(cat /root/.acme.sh/domain.tld/fullchain.cer)\", \"key\" : \"$(cat /root/.acme.sh/domain.tld/domain.tld.key)\" } }" -u "admin:password" -X GET https://domain.tld/api/ssl/cert_import'
Obviously, paths, hostname, and user/password were changed to the actual correct value. Then ran acme.sh --cron -f, it ran and deployed the cert. Checking the .conf file confirms that the command was base64-encoded by acme.sh itself.
For new issuance, I expect @Osiris’ suggestion to simply enclose the entire command in single-quotes as the --renew-hook would be the right way to go. But if the cert’s already been issued, this looks like the way to do it.