How to create a Let’s Encrypt wildcard certificate on a Synology NAS

A little update on Synology DSM 6.2.3 build 25423 where Synology added wildcard support!

  • Added support for Let’s Encrypt wildcard certificates.

This does work, however only on Synology domains. If you are running a custom domain, you still need to go the route as described below.

The Guide

I love the Let’s Encrypt functionality on the Synology but the built-in solution will not allow you to create a wildcard certificate. From a security standpoint a good way to do certificates with SAN’s but if you are like me and run a home lab… The pain of doing it the SAN way with domain DNS validation and having a /29 ipv4 public subnet is a bitch…

I always need to change a few of my public DNS IP’s to point to the Synology or the auto-renewal will fail. Also, there is a stupid 255 character limit in the SAN text box on the Synology.. so having a few SAN’s is fine but there is a limit… Hence here comes the wildcard and for a lab, it makes life easy. Below is my guide to do this manually every 3 months. I will be working out on how to automate this renewal.

How to create a wildcard on a Synology

We are going to use the acme.sh script to accomplish this. For authentication of the domain name, we will use the DNS option. First login to your Synology with ssh as the admin user and then sudo -i to get root access. When you login into the Synology with ssh you will end up in the /root path. I assume for the rest of the guide we run everything from that path. Now we need to get the script and change the permissions so it is executable.

wget https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh
chmod a+x acme.sh
Next we issue the certificate:
Note: replace *.vdr.one with your own domain. To add top-level domain or multi-domain add “-d  yourdomain
./acme.sh --issue -d *.vdr.one --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please

You will get an output like below:

Registering account
Registered
ACCOUNT_THUMBPRINT='abjJHFIUTDGIBDYDDJBDJKkhHk'
Creating domain key
The domain key is here: /root/.acme.sh/*.vdr.one/*.vdr.one.key
Single domain='*.vdr.one'
Getting domain auth token for each domain
Getting webroot for domain='*.vdr.one'
You need to add the txt record manually.
Add the following TXT record:
Domain: '_acme-challenge.vdr.one'
TXT value: 'ThIsISNoTtHeReAlKeY'
Please be aware that you prepend _acme-challenge. before your domain
so the resulting subdomain will be: _acme-challenge.vdr.one
Please add the TXT records to the domains, and re-run with --renew.
Please add '--debug' or '--log' to check more details.

As you can see you will have to create a DNS text record with your domain name provider according to the output I marked. Needless to say that you need to use your own values.After you created it we will have to run the acme.sh script again with –renew.
Note: It can take some time for DNS records to get updated. Depends on your provider for my provider it is less than a minute. For renewal, after 3 months you can just run the renew command.

./acme.sh --renew -d *.vdr.one --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please

When all goes well you get an output like below:

Your cert is in /root/.acme.sh/*.vdr.one/*.vdr.one.cer
Your cert key is in /root/.acme.sh/*.vdr.one/*.vdr.one.key
The intermediate CA cert is in /root/.acme.sh/*.vdr.one/ca.cer
And the full chain certs is there: /root/.acme.sh/*.vdr.one/fullchain.cer

Now copy the files to an accessible share on your NAS. In my case a made a share called Certs with the subfolder of vdr.one in it.:

cp "/root/.acme.sh/*.vdr.one/*.vdr.one.cer" "/volume1/Certs/vdr.one/vdr.one.cer"
cp "/root/.acme.sh/*.vdr.one/*.vdr.one.key" "/volume1/Certs/vdr.one/vdr.one.key"
cp "/root/.acme.sh/*.vdr.one/ca.cer" "/volume1/Certs/vdr.one/ca.cer"
cp "/root/.acme.sh/*.vdr.one/fullchain.cer" "/volume1/Certs/vdr.one/fullchain.cer"

You will see that the files will be in that folder after running the cp actions.

You can close the SSH session now and for security reasons, you can also disable SSH.
All you need to do now is to import your certificate on the Synology if you want or just start using it where you need it!

To import it on your Synology

If you use your Synology as a reverse proxy and ssl ofloader like me this is pretty darn handy!
Go to the Control Panel, then Security and Certificate. Choose Add.

Then import

And put in the files requested.

Now you’re done and you have a Let’s Encrypt wildcard certificate.

63 thoughts on “How to create a Let’s Encrypt wildcard certificate on a Synology NAS

  1. Tone

    You’re a wizard, thank so much! I was looking for a single solution for synology and you give me!

    Reply
  2. Nick

    Thanks a mil for the wite up, learnt a lot about SSL today!

    If it helps I have automated mine by using Synology’s “Task Scheduler” to run a bash script every month.

    The only thing i had to change vs what you have is include the –force tag to force the renewal ahead of schedule.
    “`
    ./acme.sh –renew –force -d *.vdr.one –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please
    “`
    Works like a charm on a test run we will soon see in June when it comes to renewals 🙂

    Reply
      1. Monten

        I followed your instructions but I receive error message :
        .
        dsemo.com:Challenge error: {
        “type”: “urn:ietf:params:acme:error:malformed”,
        “detail”: “Unable to update challenge :: authorization must be pending”,
        “status”: 400
        }

        See log hereunder. Any idea of what I’m doing wrong ?

        Thank you for your feedback.

        Erik

        root@NAS_ERIK:~# ./acme.sh –renew –debug –log -d *.dsemo.com –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please
        [Fri May 17 15:58:11 CEST 2019] Wildcard domain
        [Fri May 17 15:58:11 CEST 2019] Lets find script dir.
        [Fri May 17 15:58:11 CEST 2019] _SCRIPT_=’./acme.sh’
        [Fri May 17 15:58:11 CEST 2019] _script=’/root/acme.sh’
        [Fri May 17 15:58:11 CEST 2019] _script_home=’/root’
        [Fri May 17 15:58:11 CEST 2019] Using default home:/root/.acme.sh
        [Fri May 17 15:58:11 CEST 2019] Using config home:/root/.acme.sh
        https://github.com/Neilpang/acme.sh
        v2.8.2
        [Fri May 17 15:58:11 CEST 2019] Using config home:/root/.acme.sh
        [Fri May 17 15:58:11 CEST 2019] ACME_DIRECTORY=’https://acme-v02.api.letsencrypt.org/directory’
        [Fri May 17 15:58:11 CEST 2019] DOMAIN_PATH=’/root/.acme.sh/*.dsemo.com’
        [Fri May 17 15:58:11 CEST 2019] Renew: ‘*.dsemo.com’
        [Fri May 17 15:58:11 CEST 2019] Le_API
        [Fri May 17 15:58:11 CEST 2019] _main_domain=’*.dsemo.com’
        [Fri May 17 15:58:11 CEST 2019] _alt_domains=’no’
        [Fri May 17 15:58:11 CEST 2019] Using ACME_DIRECTORY: https://acme-v02.api.letsencrypt.org/directory
        [Fri May 17 15:58:11 CEST 2019] _init api for server: https://acme-v02.api.letsencrypt.org/directory
        [Fri May 17 15:58:11 CEST 2019] GET
        [Fri May 17 15:58:11 CEST 2019] url=’https://acme-v02.api.letsencrypt.org/directory’
        [Fri May 17 15:58:11 CEST 2019] timeout=
        [Fri May 17 15:58:11 CEST 2019] _CURL=’curl -L –silent –dump-header /root/.acme.sh/http.header -g ‘
        [Fri May 17 15:58:11 CEST 2019] ret=’0′
        [Fri May 17 15:58:12 CEST 2019] ACME_KEY_CHANGE=’https://acme-v02.api.letsencrypt.org/acme/key-change’
        [Fri May 17 15:58:12 CEST 2019] ACME_NEW_AUTHZ
        [Fri May 17 15:58:12 CEST 2019] ACME_NEW_ORDER=’https://acme-v02.api.letsencrypt.org/acme/new-order’
        [Fri May 17 15:58:12 CEST 2019] ACME_NEW_ACCOUNT=’https://acme-v02.api.letsencrypt.org/acme/new-acct’
        [Fri May 17 15:58:12 CEST 2019] ACME_REVOKE_CERT=’https://acme-v02.api.letsencrypt.org/acme/revoke-cert’
        [Fri May 17 15:58:12 CEST 2019] ACME_AGREEMENT=’https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf’
        [Fri May 17 15:58:12 CEST 2019] ACME_NEW_NONCE=’https://acme-v02.api.letsencrypt.org/acme/new-nonce’
        [Fri May 17 15:58:12 CEST 2019] ACME_VERSION=’2′
        [Fri May 17 15:58:12 CEST 2019] Le_NextRenewTime
        [Fri May 17 15:58:12 CEST 2019] _on_before_issue
        [Fri May 17 15:58:12 CEST 2019] _chk_main_domain=’*.dsemo.com’
        [Fri May 17 15:58:12 CEST 2019] _chk_alt_domains
        [Fri May 17 15:58:12 CEST 2019] Le_LocalAddress
        [Fri May 17 15:58:12 CEST 2019] d=’*.dsemo.com’
        [Fri May 17 15:58:12 CEST 2019] Check for domain=’*.dsemo.com’
        [Fri May 17 15:58:12 CEST 2019] _currentRoot=’dns’
        [Fri May 17 15:58:12 CEST 2019] d
        [Fri May 17 15:58:12 CEST 2019] _saved_account_key_hash is not changed, skip register account.
        [Fri May 17 15:58:12 CEST 2019] Read key length:
        [Fri May 17 15:58:12 CEST 2019] _createcsr
        [Fri May 17 15:58:12 CEST 2019] Single domain=’*.dsemo.com’
        [Fri May 17 15:58:12 CEST 2019] Getting domain auth token for each domain
        [Fri May 17 15:58:12 CEST 2019] ok, let’s start to verify
        [Fri May 17 15:58:12 CEST 2019] Verifying: *.dsemo.com
        [Fri May 17 15:58:12 CEST 2019] d=’*.dsemo.com’
        [Fri May 17 15:58:12 CEST 2019] keyauthorization=’frb0-z-hQF_Eqmrdu7bKjhcHOTfZYLcTG6Szrj7tv3s.A_dkXhoIBF-KZMy1A9pG9BoaxF1fRNOkxlMu2bSPazg’
        [Fri May 17 15:58:12 CEST 2019] uri=’https://acme-v02.api.letsencrypt.org/acme/challenge/vFciD3wF5QkQH-w-78RkVl521N8gybKkmd1jibJLJPA/15965441778′
        [Fri May 17 15:58:12 CEST 2019] _currentRoot=’dns’
        [Fri May 17 15:58:12 CEST 2019] url=’https://acme-v02.api.letsencrypt.org/acme/challenge/vFciD3wF5QkQH-w-78RkVl521N8gybKkmd1jibJLJPA/15965441778′
        [Fri May 17 15:58:12 CEST 2019] payload='{}’
        [Fri May 17 15:58:13 CEST 2019] RSA key
        [Fri May 17 15:58:13 CEST 2019] HEAD
        [Fri May 17 15:58:13 CEST 2019] _post_url=’https://acme-v02.api.letsencrypt.org/acme/new-nonce’
        [Fri May 17 15:58:13 CEST 2019] _CURL=’curl -L –silent –dump-header /root/.acme.sh/http.header -g ‘
        [Fri May 17 15:58:13 CEST 2019] _ret=’0′
        [Fri May 17 15:58:13 CEST 2019] POST
        [Fri May 17 15:58:13 CEST 2019] _post_url=’https://acme-v02.api.letsencrypt.org/acme/challenge/vFciD3wF5QkQH-w-78RkVl521N8gybKkmd1jibJLJPA/15965441778’
        [Fri May 17 15:58:13 CEST 2019] _CURL=’curl -L –silent –dump-header /root/.acme.sh/http.header -g ‘
        [Fri May 17 15:58:13 CEST 2019] _ret=’0′
        [Fri May 17 15:58:13 CEST 2019] code=’400′
        [Fri May 17 15:58:14 CEST 2019] *.dsemo.com:Challenge error: {
        “type”: “urn:ietf:params:acme:error:malformed”,
        “detail”: “Unable to update challenge :: authorization must be pending”,
        “status”: 400
        }
        [Fri May 17 15:58:14 CEST 2019] Skip for removelevel:
        [Fri May 17 15:58:14 CEST 2019] pid
        [Fri May 17 15:58:14 CEST 2019] No need to restore nginx, skip.
        [Fri May 17 15:58:14 CEST 2019] _clearupdns
        [Fri May 17 15:58:14 CEST 2019] dns_entries
        [Fri May 17 15:58:14 CEST 2019] skip dns.
        [Fri May 17 15:58:14 CEST 2019] _on_issue_err
        [Fri May 17 15:58:14 CEST 2019] Please check log file for more details: /root/.acme.sh/acme.sh.log
        [Fri May 17 15:58:14 CEST 2019] url=’https://acme-v02.api.letsencrypt.org/acme/challenge/vFciD3wF5QkQH-w-78RkVl521N8gybKkmd1jibJLJPA/15965441778′
        [Fri May 17 15:58:14 CEST 2019] payload='{}’
        [Fri May 17 15:58:14 CEST 2019] POST
        [Fri May 17 15:58:14 CEST 2019] _post_url=’https://acme-v02.api.letsencrypt.org/acme/challenge/vFciD3wF5QkQH-w-78RkVl521N8gybKkmd1jibJLJPA/15965441778′
        [Fri May 17 15:58:14 CEST 2019] _CURL=’curl -L –silent –dump-header /root/.acme.sh/http.header -g ‘
        [Fri May 17 15:58:14 CEST 2019] _ret=’0′
        [Fri May 17 15:58:14 CEST 2019] code=’400’
        [Fri May 17 15:58:14 CEST 2019] The dns manual mode can not renew automatically, you must issue it again manually. You’d better use the other modes instead.
        [Fri May 17 15:58:14 CEST 2019] socat doesn’t exists.
        [Fri May 17 15:58:14 CEST 2019] Diagnosis versions:
        openssl:openssl
        OpenSSL 1.0.2r-fips 26 Feb 2019
        apache:
        apache doesn’t exists.
        nginx:
        nginx version: nginx/1.15.7
        TLS SNI support enabled
        socat:

        Reply
        1. LaurensvanDuijn Post author

          Your DNS challenge has extra quotes! ‘” it’s wrong 🙂 You can check if the record exists with:
          nslookup -type=txt _acme-challenge.dsemo.com and compare it with mine.

          _acme-challenge.dsemo.com text = “‘a9JdivAfGYtjFO64S_dmiM9logZ8T9PDnNwYrXXBb2k‘”

          Reply
          1. Monten

            Thank you very much !! Problem solved. Works perfectly. Very much appreciated.

    1. Felix Bühler

      So if I see this right, your script contains this?

      ./acme.sh –renew –force -d *domain.tld –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please

      cp “/root/.acme.sh/*.domain.tld/*.domain.tld.cer” “/volume1/certs/domain.tld.cer”
      cp “/root/.acme.sh/*.domain.tld/*.domain.tld.key” “/volume1/certs/domain.tld.key”
      cp “/root/.acme.sh/*.domain.tld/ca.cer” “/volume1/certs/ca.cer”
      cp “/root/.acme.sh/*.domain.tld/fullchain.cer” “/volume1/certs/fullchain.cer”

      Reply
      1. LaurensvanDuijn Post author

        Yeah, those last “cp” are copy actions. Copies the cert files to a share called “certs”

        Reply
  3. René

    Hello,

    thank you very much for this great instruction! Do you have any news in automate the renewal?

    Reply
  4. Pingback: Install Let’s Encrypt Certificates on Synology – The Knowledge Base

    1. LaurensvanDuijn Post author

      Not yet.. working on it but since the dns challenge changes every time.. you need a dns provider with api access.

      Reply
      1. René

        Can you provide more feedback what you mean with DNS provider with API access please?

        Reply
        1. LaurensvanDuijn Post author

          What i mean is that you need a dns provider where you can change dns records via scripting. (Api) instead of doing it manually every time.

          Reply
          1. Leroy

            If you got a DNS Provider supported by acme.sh thats not an issue.
            But is where any way around manual importing the Certificate into synology via gui? I hoped i could simple copy it in some directory and override it?

  5. Jan

    hello, is there such a simple procedure (step by step) to install it and then proceed auto-renewal separately?

    Reply
    1. Felix

      Hey Jan,

      1) Connect via SSH to your Synology.
      2) Run
      sudo nano /volume1/scripts/wildcard_renewal.sh

      You might want to use another editor than nano. I prefer this one. You also can chose another path and filename.

      3) Fill the (empty) file with this. Make sure to replace any “DOMAIN” entry with your domain name and any “TLD” entry with your top-level-domain. Also edit the path “/volume1/certs” to your corresponding path which you set in the steps earlier.

      #!/bin/bash
      sh /acme.sh –renew –force -d *.DOMAIN.TLD –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please

      cp “/root/.acme.sh/*.DOMAIN.TLD /*.DOMAIN.TLD .cer” “/volume1/Certs/DOMAIN.TLD/DOMAIN.TLD .cer”
      cp “/root/.acme.sh/*.DOMAIN.TLD /*.DOMAIN.TLD .key” “/volume1/Certs/DOMAIN.TLD/DOMAIN.TLD .key”
      cp “/root/.acme.sh/*.DOMAIN.TLD /ca.cer” “/volume1/Certs/DOMAIN.TLD/ca.cer”
      cp “/root/.acme.sh/*.DOMAIN.TLD /fullchain.cer” “/volume1/Certs/DOMAIN.TLD/fullchain.cer”

      4) Save with CTRL + O and then quit with CTRL + X.
      I’m not quite sure yet, if Synology recognizes the new files automatically as new certificates, but I think it should.

      5) Open the DSM and go to Control Panel > Task Scheduler > Create > Scheduled Task > User-defined script >
      Name: Anything you want; User: root; Enabled: yes.
      Schedule: Once a month
      Task settings: sh /volume1/scripts/wildcard_renewal.sh
      Press OK and you are done.

      Reply
    2. Felix

      Ok, addition: DSM does not automatically renew the cert files. Anyone have an idea how to automate the step for the renewal in DSM?

      Reply
      1. LaurensvanDuijn Post author

        It’s automatable but your dns provider needs api access so the script can change the dns challange for you.

        Reply
        1. Felix

          Ok, so we better just hope, that Synology starts offering a wildcard certificate option in the DSM?

          Reply
      1. Leroy

        @someone he askey *after renewal* so the import process is meant
        @ipguy Synology stores imported certificates at /usr/syno/etc/certificate/system/default . You could try overwriting these files with your new certificate. Just found out myself the location so i didnt test it. If you try it please report back.

        Reply
  6. Pingback: Použití bezplatného certifikátu od Let’s Encrypt na Synology. – ANCC

  7. micky1067

    My question is where I can build this DNS text record ?
    Is it only a text file or what I must do ?

    Thanks…

    Reply
    1. LaurensvanDuijn Post author

      Did you put your synology into root? Seems not. Before you start anything, logon to ssh and run sudo -i first. Then follow the guide.

      Reply
  8. Austin

    Have been looking for solutions as my auto-renewal with Synology does not work. Your article saved me! Thx!

    Reply
  9. anson

    Hi there was invalidEmail issues on creating account .

    :/volume1/homes/admin/acme# acme.sh –issue -d *.passwordhk.com –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please –debug –log
    [Fri Jan 10 00:46:00 CST 2020] Lets find script dir.
    [Fri Jan 10 00:46:00 CST 2020] _SCRIPT_=’/usr/local/share/acme.sh/acme.sh’
    [Fri Jan 10 00:46:00 CST 2020] _script=’/usr/local/share/acme.sh/acme.sh’
    [Fri Jan 10 00:46:00 CST 2020] _script_home=’/usr/local/share/acme.sh’
    [Fri Jan 10 00:46:00 CST 2020] Using config home:/usr/local/share/acme.sh
    https://github.com/Neilpang/acme.sh
    v2.8.4
    [Fri Jan 10 00:46:00 CST 2020] Running cmd: issue
    [Fri Jan 10 00:46:00 CST 2020] _main_domain=’*.passwordhk.com’
    [Fri Jan 10 00:46:00 CST 2020] _alt_domains=’no’
    [Fri Jan 10 00:46:00 CST 2020] Using config home:/usr/local/share/acme.sh
    [Fri Jan 10 00:46:00 CST 2020] ACME_DIRECTORY=’https://acme-v02.api.letsencrypt.org/directory’
    [Fri Jan 10 00:46:00 CST 2020] DOMAIN_PATH=’/usr/local/share/acme.sh/*.passwordhk.com’
    [Fri Jan 10 00:46:00 CST 2020] Using ACME_DIRECTORY: https://acme-v02.api.letsencrypt.org/directory
    [Fri Jan 10 00:46:00 CST 2020] _init api for server: https://acme-v02.api.letsencrypt.org/directory
    [Fri Jan 10 00:46:00 CST 2020] GET
    [Fri Jan 10 00:46:00 CST 2020] url=’https://acme-v02.api.letsencrypt.org/directory’
    [Fri Jan 10 00:46:00 CST 2020] timeout=
    [Fri Jan 10 00:46:00 CST 2020] _CURL=’curl -L –silent –dump-header /usr/local/share/acme.sh/http.header -g ‘
    [Fri Jan 10 00:46:01 CST 2020] ret=’0′
    [Fri Jan 10 00:46:01 CST 2020] ACME_KEY_CHANGE=’https://acme-v02.api.letsencrypt.org/acme/key-change’
    [Fri Jan 10 00:46:01 CST 2020] ACME_NEW_AUTHZ
    [Fri Jan 10 00:46:01 CST 2020] ACME_NEW_ORDER=’https://acme-v02.api.letsencrypt.org/acme/new-order’
    [Fri Jan 10 00:46:01 CST 2020] ACME_NEW_ACCOUNT=’https://acme-v02.api.letsencrypt.org/acme/new-acct’
    [Fri Jan 10 00:46:01 CST 2020] ACME_REVOKE_CERT=’https://acme-v02.api.letsencrypt.org/acme/revoke-cert’
    [Fri Jan 10 00:46:01 CST 2020] ACME_AGREEMENT=’https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf’
    [Fri Jan 10 00:46:01 CST 2020] ACME_NEW_NONCE=’https://acme-v02.api.letsencrypt.org/acme/new-nonce’
    [Fri Jan 10 00:46:01 CST 2020] ACME_VERSION=’2′
    [Fri Jan 10 00:46:01 CST 2020] Le_NextRenewTime
    [Fri Jan 10 00:46:01 CST 2020] _on_before_issue
    [Fri Jan 10 00:46:01 CST 2020] _chk_main_domain=’*.passwordhk.com’
    [Fri Jan 10 00:46:01 CST 2020] _chk_alt_domains
    [Fri Jan 10 00:46:01 CST 2020] Le_LocalAddress
    [Fri Jan 10 00:46:01 CST 2020] d=’*.passwordhk.com’
    [Fri Jan 10 00:46:01 CST 2020] Check for domain=’*.passwordhk.com’
    [Fri Jan 10 00:46:01 CST 2020] _currentRoot=’dns’
    [Fri Jan 10 00:46:01 CST 2020] d
    [Fri Jan 10 00:46:01 CST 2020] config file is empty, can not read CA_KEY_HASH
    [Fri Jan 10 00:46:01 CST 2020] Using config home:/usr/local/share/acme.sh
    [Fri Jan 10 00:46:01 CST 2020] ACME_DIRECTORY=’https://acme-v02.api.letsencrypt.org/directory’
    [Fri Jan 10 00:46:01 CST 2020] _init api for server: https://acme-v02.api.letsencrypt.org/directory
    [Fri Jan 10 00:46:01 CST 2020] RSA key
    [Fri Jan 10 00:46:01 CST 2020] Registering account
    [Fri Jan 10 00:46:01 CST 2020] url=’https://acme-v02.api.letsencrypt.org/acme/new-acct’
    [Fri Jan 10 00:46:01 CST 2020] payload='{“contact”: [“mailto: email@gmailcom”], “termsOfServiceAgreed”: true}’
    [Fri Jan 10 00:46:01 CST 2020] HEAD
    [Fri Jan 10 00:46:01 CST 2020] _post_url=’https://acme-v02.api.letsencrypt.org/acme/new-nonce’
    [Fri Jan 10 00:46:01 CST 2020] _CURL=’curl -L –silent –dump-header /usr/local/share/acme.sh/http.header -g -I ‘
    [Fri Jan 10 00:46:02 CST 2020] _ret=’0′
    [Fri Jan 10 00:46:02 CST 2020] POST
    [Fri Jan 10 00:46:02 CST 2020] _post_url=’https://acme-v02.api.letsencrypt.org/acme/new-acct’
    [Fri Jan 10 00:46:02 CST 2020] _CURL=’curl -L –silent –dump-header /usr/local/share/acme.sh/http.header -g ‘
    [Fri Jan 10 00:46:03 CST 2020] _ret=’0′
    [Fri Jan 10 00:46:03 CST 2020] code=’400’
    [Fri Jan 10 00:46:03 CST 2020] Register account Error: {
    “type”: “urn:ietf:params:acme:error:invalidEmail”,
    “detail”: “Error creating new account :: contact email \”email@gmailcom\” has invalid domain : Domain name needs at least one dot”,
    “status”: 400
    }
    [Fri Jan 10 00:46:03 CST 2020] _on_issue_err
    [Fri Jan 10 00:46:03 CST 2020] Please check log file for more details: /usr/local/share/acme.sh/acme.sh.log
    [Fri Jan 10 00:46:03 CST 2020] socat doesn’t exists.
    [Fri Jan 10 00:46:03 CST 2020] Diagnosis versions:
    openssl:openssl
    OpenSSL 1.0.2n-fips 7 Dec 2017
    apache:
    apache doesn’t exists.
    nginx:
    nginx version: nginx/1.13.3
    TLS SNI support enabled

    Reply
      1. anson

        thanks for replying . may i know how the define the email in the script and run it.

        Reply
  10. Henrik Nielsen

    I got renewal of the cert files working, i.e. the acme.sh –renew part. But that just leaves me with updated cert files, they are not actually imported into Synology DSM.

    Any way to automate this as well? I saw the comment above about the location /usr/syno/etc/certificate/system/default/ containing the installed certificates. But I am unable to deduce what I need to do to get my cert files to appear there (apart from going through the motions in the DSM UI).

    My cert folder with updated cert contains these files: ca.cer fullchain.cer mydomain.tld.cer mydomain.tld.key
    The syno system folder contains these files: cert.pem chain.pem fullchain.pem privkey.pem

    Is it just a copy/rename operation or is there some other thing that the import-operation does?

    Looking at file sizes, they appear identical and a diff also indicates that they are just renamed versions of the cert files.

    Reply
  11. Igor

    Good start for a wildcard certificate!

    Then use following script to update your certificate every three months.

    Unfortunately I don’t know how to force Synology to use the new certificate except restarting the whole server. It’s a reason why the last command in the script forces the server to restart at 4 AM.

    # 1. replace “MyDomain.com” with your domain name
    # 2. schedule this script to be run once per three months in Task Scheduler

    echo “======================================================================”
    echo “Certificate Renewal”
    echo “======================================================================”
    ./acme.sh –force –renew -d *.MyDomain.com –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please –log
    echo “”

    # echo “======================================================================”
    # echo “Copying New Files to folder: certs”
    # echo “======================================================================”
    # cp “/root/.acme.sh/*.MyDomain.com/*.MyDomain.com.cer” “/volume1/certs/MyDomain.com/MyDomain.com.cer”
    # cp “/root/.acme.sh/*.MyDomain.com/*.MyDomain.com.key” “/volume1/certs/MyDomain.com/MyDomain.com.key”
    # cp “/root/.acme.sh/*.MyDomain.com/ca.cer” “/volume1/certs/MyDomain.com/ca.cer”
    # cp “/root/.acme.sh/*.MyDomain.com/fullchain.cer” “/volume1/certs/MyDomain.com/fullchain.cer”
    echo “”

    echo “======================================================================”
    echo “Renewed Certificate Publication”
    echo “======================================================================”
    certFile=”/root/.acme.sh/*.MyDomain.com/*.MyDomain.com.cer”
    chainFile=”/root/.acme.sh/*.MyDomain.com/ca.cer”
    fullchainFile=”/root/.acme.sh/*.MyDomain.com/fullchain.cer”
    privkeyFile=”/root/.acme.sh/*.MyDomain.com/*.MyDomain.com.key”
    privkey_fullchainFile=”/root/.acme.sh/*.MyDomain.com/*.MyDomain.com.privkey_fullchain”
    echo “”

    # Create file privkey_fullchain.pem
    cp $privkeyFile $privkey_fullchainFile
    echo “”>>$privkey_fullchainFile
    echo “”>>$privkey_fullchainFile
    cat $certFile>>$privkey_fullchainFile
    cat $chainFile>>$privkey_fullchainFile
    echo “”>>$privkey_fullchainFile
    echo “”>>$privkey_fullchainFile
    # echo “Copy privkey_fullchain.pem to folder: certs”
    # cp “$privkey_fullchainFile” /volume1/certs/MyDomain.com/privkey_fullchain.pem

    echo “”
    echo “======================================================================”
    echo “List of new certificate files”
    echo “======================================================================”
    md5sum –tag “$certFile”
    md5sum –tag “$chainFile”
    md5sum –tag “$fullchainFile”
    md5sum –tag “$privkeyFile”
    md5sum –tag “$privkey_fullchainFile”
    echo “”
    echo “======================================================================”
    echo “Replacing the expired certificate files”
    echo “======================================================================”

    function CopyFile() {
    if test -f “$dst”; then
    echo “———————————————————————-”
    echo “Copying file: $dst”
    fileOwner=$(ls -la “$dst”|awk ‘{print $3”:”$4}’)
    cp “$src” “$dst”
    chmod 400 “$dst”
    chown $fileOwner “$dst”
    md5sum –tag “$dst”
    ls -la “$dst”
    fi
    }

    function CopyCert() {

    # Display a name of the folder processed
    echo “Folder Name: $i”

    # Get an owner and group name of the folder

    src=”$certFile”
    dst=”$i/cert.pem”
    CopyFile

    src=”$chainFile”
    dst=”$i/chain.pem”
    CopyFile

    src=”$fullchainFile”
    dst=”$i/fullchain.pem”
    CopyFile

    src=”$privkeyFile”
    dst=”$i/privkey.pem”
    CopyFile

    src=”$privkey_fullchainFile”
    dst=”$i/privkey_fullchain.pem”
    CopyFile

    echo “======================================================================”
    }

    i=”/usr/syno/etc/certificate/system/default”
    CopyCert

    find “/usr/syno/etc/certificate/AppPortal/” -name “privkey.pem” -printf “%h\n”|while read i
    do
    CopyCert
    done

    find “/usr/local/etc/certificate/” -name “privkey.pem” -printf “%h\n”|while read i
    do
    CopyCert
    done

    # Restart server at 4AM
    /sbin/shutdown -r 04:00

    Reply
    1. James

      I have just been prompted for renewal, and although I have attempted the renewal process. I am being informed that…
      ——————————————————————————————————————————————-
      [Mon Oct 12 10:31:53 IST 2020] The dns manual mode can not renew automatically, you must issue it again manually. You’d better use the other m odes instead.
      ——————————————————————————————————————————————-
      Therefore I have had to update my txt entry.

      I would like to enable the script above. However, I do not believe that it will circumvent the error that I have been faced with above. Also I may just be too much of what the kids call a noob to know what’s the best way to schedule the script. Is there away of doing it within the Synology GUI or should I be using the traditional Linux Cron method?

      Any pointers would be appreciated.

      Reply
  12. MarkFace91

    When i trie to copy to a shared folder i get “no such file in directory”
    please help!

    Reply
  13. Lain

    Hello, Laurensvan-Duijn,
    thank you very much for this great guide! With me everything worked at first go. I am very happy!
    But I’m worried what will happen if “Let’s Encrypt” changes the rules! Did you develop the file “acme.sh” yourself and continue to support it? Or where did you get the file?
    Thank you very much.

    Reply
  14. AJ

    Hi,

    Thanks for this, it helped me alot. I have a different question however, I know using this method will issue a wild card cert for domain.tld as such: *.domain.tld.

    Can I use this script to “Expand” the certificate that already been issued and add another SubjAltName to it?

    I tried the following and it did not work:
    ./acme.sh –renew -d *.domain.tld -d domain.tld –dns –yes-I-know-dns-manual-mode-enough-go-ahead-please –force

    Any thoughts?

    Reply
    1. LaurensvanDuijn Post author

      Why add a san to a wildcard? You are talking about a multi domain certificate?

      Reply
      1. AJ

        I guess I am asking if the root of the domain (domain.tld) is covered with the wildcard? Google Chrome was throwing an error saying the cert is not valid for root of the domain, but had no issue if there was a subdomain such as http://www.domain.tld

        Reply
        1. TheotherAJ

          AJ – I had exactly the same problem as you did: the root was not included in the wildcard domain. The wildcard certificate only worked for something.root.TLD, and not root.TLD .
          However, I thought of exactly the same workaround you did, listing both *.root.TD and root.TLD, each preceded by the -d —- only for me, it worked fine. I ended up with a certificate that covered both the root used alone, and all subdomains. I found that there were two folders created in the …/acme.sh folder : *.root.TLD and *root.TLD. I grabbed the certs from *.root.TLD.

          Reply
  15. Robert Meushaw

    Thanks for a great tutorial on wildcard certificates for Synology. I was just about to try this when I saw the following info about the release of DSM update Version: 6.2.3-25423.

    Included in the description of new features is:
    What’s New in DSM 6.2.3
    Added support for Let’s Encrypt wildcard certificates.

    I was wondering if this DSM update would accomplish the same results as the procedure you described? It would certainly be handy to have wildcard certificate support built into DSM.

    Thanks.

    Reply
    1. LaurensvanDuijn Post author

      I checked this but this only works when you are using synology ddns.. this does not work with a custom domain like i do. I will continue using my way instead of the new synology option in 6.2.3

      Reply
  16. Egan Solo

    For the time being, I’m using a dynamic DNS with synology. Could I still use this script? I’m not sure where I can add the TXT record since synology’s website does not offer that facility. I guess I need to wait until I use a registered url then?

    Reply
  17. Egan Solo

    Never mind my previous question! Since I’m relying on Synology DDNS I was able to solve my problem easily. Here’s what I did, in case this might help someone else.
    Assume that the URL is MyDomain.Com and that I have also domain1.MyDomain.Com, domain2.MyDomain.com and domain3MyDomain.com
    Initially, I had created four separate certs, one for the top domain and three for each of the sub-domains, then I read here that synology does offer a wildcard cert for ddns registered with them, which is my case.
    I created a fifth let’s encrypt cert from the Synology user interface (Control Panel => Security -> Certificates) and I included in that request domain1.Mydomain.com; domain2.MyDomain.com; domain3.Mydomain.com
    Once the cert was created, I right-clicked it on it and selected set as default.
    That was it! I didn’t have to modify the Apache conf files for my domains. I did check to see if Synology modified any of the content in sites-enabled or even the main httpd conf, but that’s not the case. I’m not sure where it keeps the SSL related information but when I invoked domain1.MyDomain1.com, domain2.MyDomain.com and domain3.MyDomain.com, the browser told me that these sites were secure and the info on the cert showed the wild-card cert in action.
    So thank you for that last tip! It did make a difference for me!

    Reply
  18. James

    You’re a legend.

    My setup took 24 hours to globally propagate. One thing to note to anyone. Do not be impatient as if you perform the renew command and your ‘TXT’ file has not propagated. A new ‘TXT’ key will be generated and you will have to start the process again.

    Finally, a question to @LaurensvanDuijn

    Do you know if you are able to use any of the obtain certificate files on another hosted system? As this is a wildcard mask certificate?

    Reply
  19. Erik

    Thank you for this tutorial. I use it every three months to update my certificate.
    I have 3 questions though:
    1. Can I generate the certificates using these steps only on my Synology device? Or can I do it with any random Linux machine as well and afterward import the certificates on my Synology?
    2. The acme-script complains that I generate the certificates using the root account. it gives a warning but I can work around it using the –force parameter while issuing. Is it really necessary to do sudo -i in the very beginning?
    3. Can I remove the DNS text record after I received my certificate? Or should I leave it there?

    Reply
    1. LaurensvanDuijn Post author

      Can do it on any linux device too. You need root rights and you can remove the record. Only needed for the request

      Reply
  20. George

    Have you tried any of these:

    synoservicecfg –restart nginx

    synoservice –restart pkgctl-Apache2.4

    synoservice –restart pkgctl-WebStation

    Reply
  21. Pingback: WordPress with Docker – 自動更新憑證 – SkyLake's Blog

  22. Monten

    I do not know how I did it , but I have now following situation in my Certificates overview. Several duplicate alternative names in the certificate .
    Domain is *.DSDOMAIN.COM. (fake name)
    It worked for very long time correctly.
    The duplicate names only appeared after I created an addition certificate for domain : DSDOMAIN.COM (so without the *).
    I’m now not able anymore to remove the duplicate alternative names in the certificate..
    Do you have any idea how I can remove them. I tried deleting the certificate and creating a new one, but than he just moves the duplicate alternative names to the default certificate.
    I link it to an error message I got when creating the reverse proxy record. When saving it said operation failed. I didn’t know why , so I tried again … and again…. . And now I have these multiple alternative names that I can not remove anymore.

    Thanks in advance for your ideas.

    Reply
  23. joe

    Thanks for post. I got it to work fine. Is there a way to add Sub alternative domains as with a regular Let’s Encript Certificate done through synology? My site is blog.songswell.com and if I use *.blog.songswell.com as my default it covers all my 50 language subdomains EXCEPT blog.songswell.com

    Reply
  24. Alkaline Knight

    Not sure, but very likely that since updating my NAS to Version: 7.0.1-42218 and now finding myself having to renew my SSL. It seems broke :'( not ruling out that it is just a layer 8 issue,

    Do we now need to register an account with acme.zerossl.com?

    Reply
  25. Andrew DeFaria

    My problem is that my ISP (Cox) does not allow inbound port 80 traffic – No running web servers for residential customers! And Synology does not support Let’s Encrypt via DNS-01 challenge. The deal here is that Let’s Encrypt needs to validate that you have control over the domain. They do this by going to your web server (of course anybody having a domain must run a web server right?). But since Cox blocks inbound port 80 traffic Let’s Encrypt cannot validate that you have control over the domain. So there’s the DNS challenge in which the domain owner can assert ownership by creating a DNS TXT record.

    I’ve written a script that attempts to use Acme’s certbot to generate new wildcard certs by automatically adding a DNS TXT record (provided your DNS provider supports an API) and then waits patiently for the DNS TXT record to propagate. It leaves you with the cert files. I do this on my Ubuntu desktop because I was not sure if I could install the required Acme certbot on Synology.. These scripts are on my github

    1) https://github.com/adefaria/clearscm/blob/master/bin/certbot_authentication.sh
    2) https://github.com/adefaria/clearscm/blob/master/bin/certbot_deploy.sh
    3) https://github.com/adefaria/clearscm/blob/master/bin/certbot_cleanup.sh.

    I don’t think Igor’s script is correct. It seems to copy the certs into /usr/syno/etc/certificate/system/default which I believe is Synology’s own certificate.! I have a number of UUID-named directories on my system under /usr/syno/etc/certificate/ReverseProxy. Each directory has several files – cert.pem, fullchain.pem, privkey.pem, short-chain.pem, chain.pem, info and root.pem. All the files have the same contents! It turns out each directory is there for each of my domains in the wildcard.

    In order to get the certs activated one needs to restart nginx but first needs to place the new .pem files in the proper place. This turns out to be in /usr/syno/etc/certificate/_archive. When you restart nginx it will pull certs from this location and populate the UUID-named directories above. On my system, in the _archive directory, there was a file named INFO that contained stuff like:

    {
    “1zZdc0” : {
    “desc” : “DeFaria Home”,
    “services” : [
    {
    “display_name” : “service1.defariahome.com”,
    “isPkg” : false,
    “multiple_cert” : true,
    “owner” : “root”,
    “service” : “ec94d46d-9efc-4ace-898e-524c39b60746”,
    “subscriber” : “ReverseProxy”,
    “user_setable” : true
    },
    {
    “display_name” : “service2.defariahome.com”,
    “isPkg” : false,
    “multiple_cert” : true,
    “owner” : “root”,
    “service” : “e11fcef6-a84f-453a-9212-69c28968f84b”,
    “subscriber” : “ReverseProxy”,
    “user_setable” : true
    },

    }
    }

    “izZdco” is a strange name but there was a directory there with that name. Contained therein were .pem files (cert, chain, fullchain, privkey, root, short-chain). Certbot did not produce root or short-chain.pem files. Also, they were files. I decided instead to put the new .pem files under /System/Certificates which is NFS mounted from the Synology to my desktop. I altered the INFO file to use defariahome instead of izZdco. Further, I created a directory called defariahome and did symlinks to the .pem files in /System/Certificates.

    The final thing was to create certbot_deploy.sh which merely does a systemctl restart nginx (for DSM 7.x it’s systemctl. On DSM 6.x it may be synosystemctl). When nginx restarts a lot of things restart including the DSM web page. Also, docker restarts. It’s worrisome but it comes back up for me and the new certs are active.

    So now all I need is a root crontab entry of the form

    0 0 20 */3 0 certbot renew

    This renews my certs every 3 months on the 20th.

    Hope this helps others. If you have questions feel free to email me.

    Reply
  26. Srikanth Kamath

    Thanks Andrew & Laurence for the TuT and information,
    after a bit of search and .. many coffee found a GitHub script, which does the generate the Certificates and updates the Certificates in DSM 7. also renew the certificates and loads to the correct location.
    https://github.com/JessThrysoee/synology-letsencrypt
    of course it still requires API for DNS Access, The list of Supported DNS provider is at
    https://go-acme.github.io/lego/dns/
    also the synology-letsencrypt can be uninstalled.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.