I have a synology NAS server in my home that I would like to access from external networks. Obviously the only viable option is to use HTTPS to connect to its webpage. Before 2012, getting a certificate to use for HTTPS would cost you some money. With the advent of Let’s Encrypt this became completely free of charge, but not free of complexity if you know what I mean. The good news is that synology supports Let’s Encrypt certificates out of the box. The bad news is that it supports only the HTTP-01 method for customized domains. If you happen to use the synology DDNS service (you use the synology.me domain to access your NAS) then you could use the preferred method DNS-01 but that’s not my case since I have my own domain.
The problem with the HTTP-01 method is that you need to open port 80 or 443 to your NAS in order to make it work and this is something I am not willing to do. Furthermore many ISP’s block by default those ports. I definitely prefer the DNS-01 method as you don’t need to expose any ports to the internet. With this method, you prove that you control the DNS of your domain by putting a specific value in a TXT record under that domain name. The drawback here is that in order to do that, you need to have API access from your DNS provider.
You will find more info on those methods here.
So how do you get Let’s encrypt certificates and renew them in an automated way ?
To issue and deploy the let’s encrypt certificates I use Neil Pang’s acme.sh script. It supports a multitude of DNS APIs, it’s really easy to use, it’s automated and also comes in a docker container. Throughout the years I have used many variations of the script but this is the latest and simplest so far. Please note that the script is very actively developed so it could be that it has additional features by the time you read this article.
I install the docker container of the script to have it easily maintained and to keep it separated from the rest of the Synology stuff. So make sure you have the docker package installed.
As a pre-requisite you need to have a DDNS provider (unless you have a static ip address), to be the owner of a domain and your DNS provider to be supported by acme.sh. I use FreeDNS but you can use any other provider from that list along with the relevant instructions.
I use the latest DSM 7 on synology and the acme.sh version 3.0.2
New Synology admin user
We first need to create a separate admin user account that will only be used to issue / renew the certificates. You can use an existing one but I really prefer to have a separate user.
Go to Control Panel –> User & Group. Click on Create –> Create Users. Give the user a name, email address and a password at a minimum.
Make sure you add the user to the administrators group
Let’s create an acme folder in synology where we are going to store the configuration of the acme.sh container via docker volumes. This way we can change the container without losing the static configuration.
Make sure SSH is enabled on your synology and login as admin. Issue the following
Create an account.conf file that will be read by acme.sh when it issues / renews the certificates
In that file add the following
Note: FREEDNS_User and FREEDNS_Password use the FreeDNS API, you need to use the one that corresponds to your DNS provider here.
Note: The SYNO_Username and SYNO_Password is taken from the admin user creation above
Now that you have the admin user and the static configuration you can download the docker image. Simply go to docker in synology and do the following
In the Registry search for Neil Pang’s acme.sh container and download it by using the latest tag. It’s pretty light as it is based on alpine linux
Then go to Image and once the image is downloaded click on Launch. Click on the Advanced Settings.
Check Enable auto-restart.
In the Volume tab click Add Folder and select the /docker/acme folder we created above. The mount path should be /acme.sh. Basically what this does is to map the acme.sh folder of the container to the /docker/acme folder we had created in Synology with the static configuration. That way, even if we delete the container and redownload it, the configuration is conserved in docker/acme.
In the Network tab check the Use the same network as Docker Host. That way the container has internet access just like the Synology server has.
In the Environment tab type daemon in the command field. That way the container remains up as per the guidelines. The container will remain up and will take charge of the renewal of the certificate.
That’s it. Click Apply and start the container if it did not start automatically.
In the docker window go to Container. You should now see the acme.sh container running. Click on the details and make sure you have the same configuration as below
In the Terminal tab make sure you create a new terminal and put sh in the Launch with command field. You need to do that because the default bash script does not exist.
Issue and deploy let’s encrypt certificate
Now we are all set for getting those certificates. Get into the shell as I described above and issue the following command
acme.sh --set-default-ca --server letsencrypt
acme.sh default CA changed from Let’s Encrypt to ZeroSSL on August 2021. The above command changes the default CA back to Let’s Encrypt.
if your DNS provider is not FREEDNS you need to use the relevant dns argument as described here.
acme.sh --issue --dns dns_freedns -d yourdomain
Note: Make sure you don’t make typos, the script might give you false leads if you do.
If this is completed successfully you will get the certificates downloaded to synology. In the past you had to manually transfer them to specific folders within synology in order for the the applications to pick them up successfully. Now you just need to use the synology hook provided here.
acme.sh --deploy -d yourdomain --deploy-hook synology_dsm
Et voila! Your files are moved to the right folders and the necessary services are restarted.
Next time you refresh your browser you will be using the newly generated certificate
Scheduling the renewal of the certificates
You will have to use synology’s scheduler to create a task that runs every x amount of days. Remember the certificates expire after 3 months so make sure you renew them earlier. I have create a task that runs once per month.
Go to Control Panel and then click on the Task Scheduler. Click on Create –> Scheduled Task –> User-defined script. In the Task give it a name and use root as the user that will execute the script. Unfortunately I tried with my admin user but I hit permissions issue so you need to use root.
In the schedule tab just define the frequency of the scheduled task. Here’s mine
In the Task Settings you add the following command in the User-defined script.
docker exec neilpang-acme.sh1 acme.sh --renew -d "yourdomain"
Note: You can add –force if you just want to force the script to issue a new certificate
Additionally, you can define an email so that you are notified when the task completes.
It should look like this once you finish
Tip: If the script fails for some reason re-run it, this time with the –debug flag. For example
docker exec neilpang-acme.sh1 acme.sh --renew -d "yourdomain" --debug
This will give you some tips as to what might be going wrong
Tip: If you try too many times to renew the certificate you might be blocked if you hit Let’s Encrypt rate limit.