Skip to content

Instantly share code, notes, and snippets.

@mwthink
Last active December 8, 2021 07:26
Show Gist options
  • Save mwthink/6888103c358c4ad17a870e2e56b010b2 to your computer and use it in GitHub Desktop.
Save mwthink/6888103c358c4ad17a870e2e56b010b2 to your computer and use it in GitHub Desktop.
synology + k8s + cert-manager

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.

Cluster

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

Script

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

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment