I like my Synology NAS. I do not like its LetsEncrypt integration. I like to issue my certs with cert-manager running on Kubernetes.
To accomplish this, we will create some Kubernetes resources that:
- Create/maintain the certificate as a Secret
- Create a robot account with permissions to read the Secret
Then we will configure a script that runs weekly on the NAS. This script will download the certificate via curl
, load it into DSM and restart the web server.
This was written for DSM 7. If you are using DSM 6 this will not work as certificates are managed differently.
Assuming we already have a ClusterIssuer named letsencrypt
, we apply these manifests to the cluster.
Certificate (adjust hostname(s) for YOUR issuer/server):
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: synology-nas
namespace: default
spec:
secretName: tls-synology-nas
commonName: nas.mwlan.io
dnsNames:
- nas.mwlan.io
issuerRef:
name: letsencrypt
kind: ClusterIssuer
RBAC:
apiVersion: v1
kind: ServiceAccount
metadata:
name: synology-nas
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: synology-certificate-reader
namespace: default
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["tls-synology-nas"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: synology-certificate-reader
namespace: default
roleRef:
kind: Role
name: synology-certificate-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: synology-nas
namespace: default
This script runs as a cron task on the Synology. You can configure this at Control Panel > Task Scheduler
.
You need to replace config values in the script below:
#!/bin/bash
### BEGIN CONFIG ###
k8s_endpoint=""
k8s_sa_token=""
k8s_namespace="default"
k8s_secret_name="tls-synology-nas"
### END CONFIG ###
# Get cert files from cluster
cd /tmp
cert_secret_data_json=$(curl -s \
--insecure \
-H "Authorization: Bearer ${k8s_sa_token}" \
"${k8s_endpoint}/api/v1/namespaces/${k8s_namespace}/secrets/${k8s_secret_name}" | jq -cr '.data')
echo ${cert_secret_data_json} | jq -cr '.["tls.key"]' | base64 --decode > privkey.pem
echo ${cert_secret_data_json} | jq -cr '.["tls.crt"]' | base64 --decode > cert.pem
cp cert.pem fullchain.pem
# Overwrite Synology "default" cert
mv ./{privkey,fullchain,cert}.pem /usr/syno/etc/certificate/_archive/$(cat /usr/syno/etc/certificate/_archive/DEFAULT)
# Resync TLS certs across system
synow3tool --gen-all
# Reload webserver
systemctl reload nginx
Be sure to fill in the values under ### BEGIN CONFIG ###
. You can generate these values by running:
# Run the next few lines as 1 command, all the way from "cat" to the last "EOF"
cat <<EOF
k8s_endpoint="$(kubectl config view --minify -o json | jq -cr '.clusters[0].cluster.server')"
k8s_sa_token="$(kubectl get secret $(kubectl get sa synology-nas -o json | jq -cr '.secrets[0].name') -o json | jq -cr '.data.token | @base64d')"
k8s_namespace="$(kubectl get secret $(kubectl get sa synology-nas -o json | jq -cr '.secrets[0].name') -o json | jq -cr '.data.namespace | @base64d')"
k8s_secret_name="tls-synology-nas"
EOF