Another Letsencrypt method

Discuss your pilot or production implementation with other Zimbra admins or our engineers.
Post Reply
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Another Letsencrypt method

Post by JDunphy »

myriad wrote:Will I be allowed to replace the certs before expiry?
Yes... acme.sh now uses 60 days as does letsencrypt I believe since I first began this thread last fall, but if you want to do it sooner... just add the --force option to acme.sh when you issue/renew them. This free cert thing is hard to get use to because they want you to generate them more often. The longer certs exist, the longer the window for potential abuse via PKI. If I didn't have to take any zimbra outage to replace my certs, I would replace them more frequently so its a trade off vs outages for me.
User avatar
myriad
Advanced member
Advanced member
Posts: 90
Joined: Fri Sep 12, 2014 11:51 pm
ZCS/ZD Version: Zimbra 9.0.0_ZEXTRAS_20211118.FOSS

Success with Another Letsencrypt method

Post by myriad »

Ok. So I got it going successfully and I just wanted to post how I did it in case others are having problems like I did with the certificates not creating properly. I have learned WAY more about acme.sh than I ever needed to and I found one really cool thing which helped me tremendously!

1. To create or issue new or broken certificates I used acme's DNS API which can be found at: https://github.com/Neilpang/acme.sh/tree/master/dnsapi (I use Linode), which is THE WAY to create certs using the --dns method if you are using one of their supported DNS providers. Acme supports many cloud/VPS providers and all you really need to do is get an API key from one of your providers on the list and enter the key in the acme.conf file. Then call the issue like so (substituting your remote DNS name) as a non-root user:

Code: Select all

acme.sh --issue --dns dns_linode --dnssleep 900 d mail.example.com mail.example.net -d tmail.example.com
That's it! It will upload the keys to your remote DNS server, wait 15 minutes and verify and then delete the keys off of the remote DNS server and your done creating the certs.

2. I then added two cron jobs. The first job is step one's --issue code which runs every night as the non_root_user. The second cron job calls Jim's deploy-zimbra-letsencrypt.sh script which is run as the zimbra user.

That's it!
Last edited by myriad on Fri Apr 28, 2017 2:29 pm, edited 1 time in total.
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Success with Another Letsencrypt method

Post by JDunphy »

myriad wrote: 2. Now you need to copy the: /home/your_non_root_user/.acme.sh folder with your new certs to your: /opt/letsencrypt directory. I added the following two lines to Jim's deploy-zimbra-letsencrypt.sh script:

Code: Select all

cd /opt/letsencrypt
/bin/cp -rf /home/your_non_root_user/.acme.sh .
Very nice! I will include this in the recipes on github.

PS. I am experimenting with the stateless method. Super simple. You generate a key:

Code: Select all

acme.sh --register-account
Thu Apr 17 12:23:09 PDT 2017] Registering account
[Thu Apr 17 12:23:09 PDT 2017] Already registered
[Thu Apr 17 12:23:09 PDT 2017] Update success.
[Thu Apr 17 12:23:09 PDT 2017] ACCOUNT_THUMBPRINT='6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd'


take this key and add it to one of the nginx files with an entry like this:
http {
...
server {
...
  location ~ "^/\.well-known/acme-challenge/([-_a-zA-Z0-9]+)$" {
    default_type text/plain;
    return 200 "6fXAG9VyG0IahirPEU2ZerUtItW2DHzDzD9wZaEKpqd";
  }
...
}
}
Once I figure the best way to insert this key, this might be the method for zimbra to work out of the box with letsencrypt because it could be available as a template and zmconfigd could configure it based if this variable was set with the key. Given the small foot print that acme.sh has it seems to be the least intrusive option for letsencrypt certificate issue/renewal that would universally work. One still needs to add the cron entry to issue/renew the certs and one entry to deploy them but the issue/renewal would always work. Everything would run as the zimbra user so in theory it could be done automatically and not require any interaction to make letsencrypt certificates the default vs self-signed. This stateless method requires that you have the latest acme.sh software.

Hint:

Code: Select all

acme.sh --upgrade
quyhoang
Posts: 1
Joined: Mon Nov 06, 2017 3:01 pm

Re: Another Letsencrypt method

Post by quyhoang »

Hello,

I am running all the script as instructed in the Github page.

But when I run

chmod 755 .acme.sh in the home directory of my username "administrator" (with sudo right)

Code: Select all

[administrator@cogman ~]$ chmod 755 .acme.sh/
[administrator@cogman ~]$ ls -la
total 40
drwx------. 5 administrator administrator 4096 Nov  6 19:05 .
drwxr-xr-x. 4 root          root          4096 Nov  6 17:46 ..
drwxr-xr-x. 6 administrator administrator 4096 Nov  6 19:05 .acme.sh
drwxrwxr-x. 6 administrator administrator 4096 Nov  6 19:03 acme.sh
-rw-------. 1 administrator administrator  573 Nov  6 19:03 .bash_history
-rw-r--r--. 1 administrator administrator   18 Aug  3 04:11 .bash_logout
-rw-r--r--. 1 administrator administrator  193 Aug  3 04:11 .bash_profile
-rw-r--r--. 1 administrator administrator  276 Nov  6 19:03 .bashrc
drwxrw----. 3 administrator administrator 4096 Nov  6 19:03 .pki
-rw-------. 1 administrator administrator 1024 Nov  6 19:05 .rnd
when I run the deploy code as zimbra user in /opt/letsencrypt, I faced error:

Code: Select all

[zimbra@cogman letsencrypt]$ ./deploy-zimbra-letsencrypt.sh
/bin/cp: cannot stat '/home/administrator/.acme.sh/cogman.url.com': Permission denied
Check permissions: CERT cp failed for /home/administrator/.acme.sh
zimbra/
zimbra/ca/
zimbra/ca/index.txt.attr
zimbra/ca/newcerts/
zimbra/ca/newcerts/1509969026.pem
zimbra/ca/newcerts/1509969013.pem
zimbra/ca/newcerts/1509969017.pem
zimbra/ca/newcerts/1509969021.pem
zimbra/ca/ca.key
zimbra/ca/ca.srl
zimbra/ca/ca.srl.old
zimbra/ca/zmssl.cnf
zimbra/ca/index.txt
zimbra/ca/index.txt.old
zimbra/ca/ca.pem
zimbra/server/
zimbra/server/server.key
zimbra/server/server.crt
zimbra/server/server.csr
zimbra/jetty.pkcs12
zimbra/commercial/
./deploy-zimbra-letsencrypt.sh: line 105: cd: /opt/letsencrypt/.acme.sh/cogman.url.com/: No such file or directory
** Verifying 'cogman.url.com.cer' against 'cogman.url.com.key'
ERROR: Can't read file 'cogman.url.com.key'
ERROR: Can't read file 'cogman.url.com.cer'
cert did not verify
I am running zimbra OE 8.7.1 and Centos 7

Thank you.
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Another Letsencrypt method

Post by JDunphy »

quyhoang wrote:Hello,

I am running all the script as instructed in the Github page.

But when I run

chmod 755 .acme.sh in the home directory of my username "administrator" (with sudo right)

Code: Select all

[administrator@cogman ~]$ chmod 755 .acme.sh/
when I run the deploy code as zimbra user in /opt/letsencrypt, I faced error:

Code: Select all

[zimbra@cogman letsencrypt]$ ./deploy-zimbra-letsencrypt.sh
/bin/cp: cannot stat '/home/administrator/.acme.sh/cogman.url.com': Permission denied
Check permissions: CERT cp failed for /home/administrator/.acme.sh
You are very close.

Code: Select all

ls -ld /home/administrator/.acme.sh/cogman.url.com
So your solution is:

Code: Select all

chmod -R 755 .acme.sh
or
chmod -R 755 /home/administrator/.acme.sh/cogman.url.com
Just enough permissions so that the zimbra user can copy the certs and install them.
dynamica
Posts: 3
Joined: Mon Jul 10, 2017 7:15 pm

Re: Another Letsencrypt method

Post by dynamica »

First : Thank you... very very mutch !!! :D

Second : I'm on Zimbra 8.7 on CentOS 7

for me the first time manualy i create the folder .acme.sh/ on /opt/letsencrypt/.acme.sh/

the script fail when /bin/cp -rf $user/.acme.sh/$domain $certs ( on destination folder $certs don't exist .acme.sh )

because on certs=/opt/letsencrypt/.acme.sh/$domain/ the folder .acme.sh dont' exist

after that it's all awsome

third : Thank's again
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Another Letsencrypt method

Post by JDunphy »

Thanks for the feedback and I am happy to hear you got it working.

The script assumes that .acme.sh folder is outside the /opt/letsencrypt directory if I understood what maybe failed with the cp. I had observed that acme.sh when run or updated over time tends to chmod the domain directory and sometimes the ~/.acme.sh directory back to 700. I run the acme.sh script as a different user than zimbra. As a result, I isolated that acme.sh directory and have my script copy it under /opt/letsencrypt before zmcertmgr see the certs. Should zimbra not have all the permissions, it is possible to trip this [bug]107454[/bug] with /opt/zimbra/bin/zmcertmgr and leave the installation broken until you fix the permissions and rerun the script. My less than ideal solution was to cp -r the .acme.sh directory and hopefully avoid the problem.

If you do it all from the zimbra user (retrieve your certs as zimbra and install them), it makes more sense to run acme.sh script from inside the directory (/opt/letsencrypt) as I believe you have. In that case, you could comment out that cp since it isn't necessary because you should never have permission problems.

Note: why do I run acme.sh outside of zimbra and as a different user? Probably because I am too paranoid that acme.sh might have some bug and/or security issue ... or maybe that is how I tested it first and now can't change. Pick one. LOL
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Another Letsencrypt method

Post by JDunphy »

There has been some changes to letsencrypt https://community.letsencrypt.org/t/201 ... ture/50188 that may eventually cause issues for those using other letsencrypt validation methods that use acme TLS-SNI-02 and TLS-SNI-02 verification methods. If you use the DNS or http methods than the problem doesn't exist for you. I have upgraded acme.sh to the newest version to keep up with the new acme protocol standards... Upgrading can be done by:

Code: Select all

acme.sh --upgrade
WARNING. You should observe the ~/.acme.sh directory permissions after upgrading if you require zimbra to have read permission of your certs for installation... ie. You will trip this [bug]107454[/bug] during cert install otherwise. The certs will validate but will fail on the install portion leaving you with an ldap server failure. Solution: fix permission and rerun your zimbra cert install again.

The simplest method continues to be the DNS validation method if your DNS provider supports API access. One would add their API update key to your account.conf file in your ~/.acme.sh directory.

Example with CF ie. cloudflare (account.conf):
SAVED_CF_Key='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
SAVED_CF_Email='user@example.com'

See https://github.com/Neilpang/acme.sh section 9 to see if your DNS provider is supported. My github also discusses this and the install script I use for zimbra.

The advantage of the DNS method is you don't have to be on the same server and do not have to take down zimbra while you get your certs sorted and verified. This allows a central repository verification and push methodology if you are so inclined. I also tend to throw an extra -d 'test.example.com' for my larger domains to facilitate testing new servers for upgrades, etc.
User avatar
zimico
Outstanding Member
Outstanding Member
Posts: 225
Joined: Mon Nov 14, 2016 8:03 am
Location: Vietnam
ZCS/ZD Version: 8.8.15 P3
Contact:

Re: Another Letsencrypt method

Post by zimico »

Dear JDunphy,

Could you please intruct how to renew cert automatically? Currently I put in cron 2 job:

Code: Select all

For zimbra user:
5 1 * * * /opt/letsencrypt/deploy-zimbra-letsencrypt.sh
For user which I use to run acme.
@daily /home/administrator/.acme.sh/acme.sh --renew -d mail.zimilab.com
However, my cert is now expired and can not renew automatically.

Many thanks.
User avatar
JDunphy
Outstanding Member
Outstanding Member
Posts: 889
Joined: Fri Sep 12, 2014 11:18 pm
Location: Victoria, BC
ZCS/ZD Version: 9.0.0_P39 NETWORK Edition

Re: Another Letsencrypt method

Post by JDunphy »

zimico wrote:Dear JDunphy,

Could you please intruct how to renew cert automatically? Currently I put in cron 2 job:

Code: Select all

For zimbra user:
5 1 * * * /opt/letsencrypt/deploy-zimbra-letsencrypt.sh
For user which I use to run acme.
@daily /home/administrator/.acme.sh/acme.sh --renew -d mail.zimilab.com
However, my cert is now expired and can not renew automatically.

Many thanks.
Yea the problem is you need to do it in 59 days or less... acme.sh will not let you do that unless you use the --force option because it doesn't think it is time to renew given you have 90 days.

If you are using the dns method and it has expired, the process is two step but it would be manual if you are entering the TXT records by hand for verification so you can't automate that unless you use the DNS API or use one of the other verification methods. If you get to it before 60 days, the process is 1 step with the --renew. From what you typed, it probably is using the previous method you used to initially verify the domain so I am guessing DNS since you are using the zimbra user to do this and it has expired.
Summary:

Code: Select all

acme.sh --issue --dns -d mail.zimilab.com -d zimilab.com -d othernames, etc
acme.sh  --renew --dns -d  mail.zimilab.com -d zimilab.com -d othernames, etc
If you have a DNS provider like cloudflare, godaddy, etc you can add the API key to your account.conf file in ~/.acme.sh directory. So you would have and entry like this for Cloudflare (ie. CF stands for cloudflare):

Code: Select all

echo 'SAVED_CF_Key="....."' >> ~/.acme.sh/account.conf
echo 'SAVE_CF_Email='user@domain.com' >> ~/.acme.sh/account.conf
Then you could do this:

Code: Select all

acme.sh --issue --dns dns_cf -d mail.zimilab.com -d zimilab.com -d othernames, etc
You can also use other methods for acme.sh if you don't want to do DNS... see the https://github.com/Neilpang/acme.sh. If you haven't updated in a while, do this:

Code: Select all

acme.sh --upgrade
Double check your permissions afterwords if you do this other than the zimbra user or deploy-zimbra-letsencrypt.sh won't have permissions to copy the files. Note: You might also investigate some of the other methods for verification with acme.sh from the github page if they are more convenient ... The deploy-zimbra-letsencrypt.sh won't care what method you use for verification provided you have a valid certificate.

HTH,

Jim
Post Reply