{"id":2376,"date":"2019-03-12T21:53:40","date_gmt":"2019-03-12T21:53:40","guid":{"rendered":"http:\/\/www.incredigeek.com\/home\/?p=2376"},"modified":"2020-10-13T11:22:12","modified_gmt":"2020-10-13T16:22:12","slug":"auto-renew-ssl-cert-for-unifi-and-unifi-video","status":"publish","type":"post","link":"https:\/\/www.incredigeek.com\/home\/auto-renew-ssl-cert-for-unifi-and-unifi-video\/","title":{"rendered":"Auto renew ssl cert for UniFI and UniFi-Video"},"content":{"rendered":"\n<p>The following script was taken from <a href=\"https:\/\/www.reddit.com\/r\/Ubiquiti\/comments\/43v23u\/using_letsencrypt_with_the_unifi_controller\/\">here<\/a><\/p>\n\n\n\n<p>Added unifi-video support.  Script uses letsencrypt to get the cert and automatically updates the UniFi and UniFi-Video Keystores.<\/p>\n\n\n\n<p>Would be a good idea to check and make sure the the UniFi-Video cameras reconnect and still work after running script.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Let&#8217;s Encrypt<\/h2>\n\n\n\n<p>Install Let&#8217;s Encrypt with the following<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo apt install letsencrypt<\/pre>\n\n\n\n<p>And generate a cert for your domain with<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo certbot certonly -d unifi.domain.com<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Executing Script to Renew Certificate <\/h2>\n\n\n\n<p>Copy the script at the bottom of this post and put it in a file called gen-unifi-cert.sh<br>Run the script to insert the cert into the UniFi and UniFi-Video services.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo .\/gen-unifi-cert.sh -e email@domain.com -d unifi.domain.com<\/pre>\n\n\n\n<p>You can run it with no or the -h argument to show the options and arguments to use.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.\/gen-unifi-cert.sh -h<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Setup Cron Job<\/h2>\n\n\n\n<p>You should be able to add the following to a cronjob to auto renew the certificate.  Replace path to script and domain name.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">30 2 * * * \/root\/gen-unifi-cert.sh -r -d unifi.domain.com<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">UniFi SSL Cert Renew Script<\/h2>\n\n\n\n<div style=\"height: 250px; position:relative; margin-bottom: 50px;\" class=\"wp-block-simple-code-block-ace\"><pre class=\"wp-block-simple-code-block-ace\" style=\"position:absolute;top:0;right:0;bottom:0;left:0\" data-mode=\"php\" data-theme=\"monokai\" data-fontsize=\"14\" data-lines=\"Infinity\" data-showlines=\"true\" data-copy=\"false\">#!\/usr\/bin\/env bash\n# Added support to do UniFi and UniFi controllers at the same time using the same cert.\n# Original script from https:\/\/git.sosdg.org\/brielle\/lets-encrypt-scripts\/raw\/branch\/master\/gen-unifi-cert.sh\n# More info here https:\/\/www.reddit.com\/r\/Ubiquiti\/comments\/43v23u\/using_letsencrypt_with_the_unifi_controller\/ \n# And here https:\/\/www.reddit.com\/r\/Ubiquiti\/comments\/43v23u\/using_letsencrypt_with_the_unifi_controller\/\n# Modified script from here: https:\/\/github.com\/FarsetLabs\/letsencrypt-helper-scripts\/blob\/master\/letsencrypt-unifi.sh\n# Modified by: Brielle Bruns &lt;bruns@2mbit.com>\n# Download URL: https:\/\/source.sosdg.org\/brielle\/lets-encrypt-scripts\n# Version: 1.7\n# Last Changed: 09\/26\/2018\n# 02\/02\/2016: Fixed some errors with key export\/import, removed lame docker requirements\n# 02\/27\/2016: More verbose progress report\n# 03\/08\/2016: Add renew option, reformat code, command line options\n# 03\/24\/2016: More sanity checking, embedding cert\n# 10\/23\/2017: Apparently don't need the ace.jar parts, so disable them\n# 02\/04\/2018: LE disabled tls-sni-01, so switch to just tls-sni, as certbot 0.22 and later automatically fall back to http\/80 for auth\n# 05\/29\/2018: Integrate patch from Donald Webster &lt;fryfrog[at]gmail.com> to cleanup and improve tests\n# 09\/26\/2018: Change from TLS to HTTP authenticator\n\n# Location of LetsEncrypt binary we use.  Leave unset if you want to let it find automatically\n#LEBINARY=\"\/usr\/src\/letsencrypt\/certbot-auto\"\n\nPATH=\"\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin\"\n\nfunction usage() {\n  echo \"Usage: $0 -d &lt;domain> [-e &lt;email>] [-r] [-i]\"\n  echo \"  -d &lt;domain>: The domain name to use.\"\n  echo \"  -e &lt;email>: Email address to use for certificate.\"\n  echo \"  -r: Renew domain.\"\n  echo \"  -i: Insert only, use to force insertion of certificate.\"\n}\n\nwhile getopts \"hird:e:\" opt; do\n  case $opt in\n    i) onlyinsert=\"yes\";;\n    r) renew=\"yes\";;\n    d) domains+=(\"$OPTARG\");;\n    e) email=\"$OPTARG\";;\n    h) usage\n       exit;;\n  esac\ndone\n\nDEFAULTLEBINARY=\"\/usr\/bin\/certbot \/usr\/bin\/letsencrypt \/usr\/sbin\/certbot\n  \/usr\/sbin\/letsencrypt \/usr\/local\/bin\/certbot \/usr\/local\/sbin\/certbot\n  \/usr\/local\/bin\/letsencrypt \/usr\/local\/sbin\/letsencrypt\n  \/usr\/src\/letsencrypt\/certbot-auto \/usr\/src\/letsencrypt\/letsencrypt-auto\n  \/usr\/src\/certbot\/certbot-auto \/usr\/src\/certbot\/letsencrypt-auto\n  \/usr\/src\/certbot-master\/certbot-auto \/usr\/src\/certbot-master\/letsencrypt-auto\"\n\nif [[ ! -v LEBINARY ]]; then\n  for i in ${DEFAULTLEBINARY}; do\n    if [[ -x ${i} ]]; then\n      LEBINARY=${i}\n      echo \"Found LetsEncrypt\/Certbot binary at ${LEBINARY}\"\n      break\n    fi\n  done\nfi\n\n# Command line options depending on New or Renew.\nNEWCERT=\"--renew-by-default certonly\"\nRENEWCERT=\"-n renew\"\n\n# Check for required binaries\nif [[ ! -x ${LEBINARY} ]]; then\n  echo \"Error: LetsEncrypt binary not found in ${LEBINARY} !\"\n  echo \"You'll need to do one of the following:\"\n  echo \"1) Change LEBINARY variable in this script\"\n  echo \"2) Install LE manually or via your package manager and do #1\"\n  echo \"3) Use the included get-letsencrypt.sh script to install it\"\n  exit 1\nfi\n\nif [[ ! -x $( which keytool ) ]]; then\n  echo \"Error: Java keytool binary not found.\"\n  exit 1\nfi\n\nif [[ ! -x $( which openssl ) ]]; then\n  echo \"Error: OpenSSL binary not found.\"\n  exit 1\nfi\n\nif [[ ! -z ${email} ]]; then\n  email=\"--email ${email}\"\nelse\n  email=\"\"\nfi\n\nshift $((OPTIND -1))\nfor val in \"${domains[@]}\"; do\n        DOMAINS=\"${DOMAINS} -d ${val} \"\ndone\n\nMAINDOMAIN=${domains[0]}\n\nif [[ -z ${MAINDOMAIN} ]]; then\n  echo \"Error: At least one -d argument is required\"\n  usage\n  exit 1\nfi\n\nif [[ ${renew} == \"yes\" ]]; then\n  LEOPTIONS=\"${RENEWCERT}\"\nelse\n  LEOPTIONS=\"${email} ${DOMAINS} ${NEWCERT}\"\nfi\n\n#if [[ ${onlyinsert} != \"yes\" ]]; then\nif [[ ${onlyinsert} == \"yes\" ]]; then\n  echo \"Firing up standalone authenticator on TCP port 80 and requesting cert...\"\n  ${LEBINARY} --server https:\/\/acme-v01.api.letsencrypt.org\/directory \\\n              --agree-tos --standalone --preferred-challenges http ${LEOPTIONS}\nfi\n\n#if [[ ${onlyinsert} != \"yes\" ]] &amp;&amp; md5sum -c \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/cert.pem.md5\" &amp;>\/dev\/null; then\nif [[ ${onlyinsert} == \"yes\" ]] &amp;&amp; md5sum -c \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/cert.pem.md5\" &amp;>\/dev\/null; then\n  echo \"Cert has not changed, not updating controller.\"\n  exit 0\nelse\n  echo \"Cert has changed or -i option was used, updating controller...\"\n  TEMPFILE=$(mktemp)\n  CATEMPFILE=$(mktemp)\n\n  # Identrust cross-signed CA cert needed by the java keystore for import.\n  # Can get original here: https:\/\/www.identrust.com\/certificates\/trustid\/root-download-x3.html\n  cat > \"${CATEMPFILE}\" &lt;&lt;'_EOF'\n-----BEGIN CERTIFICATE-----\nMIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA\/\nMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\nDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\nPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\nEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM\/IUmTrE4O\nrz5Iy2Xu\/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\nOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\nxiqKqy69cK3FCxolkHRyxXtqqzTWMIn\/5WgTe1QLyNau7Fqckh49ZLOMxt+\/yUFw\n7BZy1SbsOFU5Q9D8\/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\naeQQmxkqtilX4+U9m5\/wAl0CAwEAAaNCMEAwDwYDVR0TAQH\/BAUwAwEB\/zAOBgNV\nHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX\/xBVghYkQMA0GCSqG\nSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\nikugdB\/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\nAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\nR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir\/md2cXjbDaJWFBM5\nJDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\nOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n-----END CERTIFICATE-----\n_EOF\n\n  md5sum \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/cert.pem\" > \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/cert.pem.md5\"\n  echo \"Using openssl to prepare certificate...\"\n  cat \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/chain.pem\" >> \"${CATEMPFILE}\"\n  openssl pkcs12 -export  -passout pass:aircontrolenterprise \\\n          -in \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/cert.pem\" \\\n          -inkey \"\/etc\/letsencrypt\/live\/${MAINDOMAIN}\/privkey.pem\" \\\n          -out \"${TEMPFILE}\" -name unifi \\\n          -CAfile \"${CATEMPFILE}\" -caname root\n\n  echo \"Stopping Unifi and UniFi-Video controllers...\"\n  systemctl stop unifi unifi-video  \n\n  echo \"Removing existing certificate from Unifi protected keystore...\"\n  keytool -delete -alias unifi -keystore \/usr\/lib\/unifi\/data\/keystore -deststorepass aircontrolenterprise\n  echo \"Removing existing certificate from Unifi-Video protected keystore...\"\n  keytool -delete -alias unifi -keystore \/usr\/lib\/unifi-video\/data\/keystore -deststorepass ubiquiti\n  # following lines are needed for unifi-video\n \n  echo \"Inserting certificate into Unifi keystore...\"\n  keytool -trustcacerts -importkeystore \\\n          -deststorepass aircontrolenterprise \\\n          -destkeypass aircontrolenterprise \\\n          -destkeystore \/usr\/lib\/unifi\/data\/keystore \\\n          -srckeystore \"${TEMPFILE}\" -srcstoretype PKCS12 \\\n          -srcstorepass aircontrolenterprise \\\n          -alias unifi\n\n  echo \"Inserting certificate into Unifi-Video keystore...\"\n  keytool -trustcacerts -importkeystore \\\n          -deststorepass ubiquiti \\\n          -destkeypass ubiquiti \\\n          -destkeystore \/usr\/lib\/unifi-video\/data\/keystore \\\n          -srckeystore \"${TEMPFILE}\" -srcstoretype PKCS12 \\\n          -srcstorepass aircontrolenterprise \\\n\n          rm -f \"${TEMPFILE}\" \"${CATEMPFILE}\"\n\n  mv \/usr\/lib\/unifi-video\/data\/ufv-truststore{,.old} # Delete old unifi-video keystore\n  sleep 5\n  echo \"Starting Unifi and UniFi-Video controllers...\"\n  systemctl start unifi unifi-video \n\n  echo \"Done!\"\nfi<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The following script was taken from here Added unifi-video support. Script uses letsencrypt to get the cert and automatically updates the UniFi and UniFi-Video Keystores. Would be a good idea to check and make sure the the UniFi-Video cameras reconnect &hellip; <a href=\"https:\/\/www.incredigeek.com\/home\/auto-renew-ssl-cert-for-unifi-and-unifi-video\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,129,370],"tags":[211,358,508,7,173,356,188,265],"class_list":["post-2376","post","type-post","status-publish","format-standard","hentry","category-linux","category-ubiquiti","category-unifi-video","tag-bash","tag-cert","tag-letsencrypt","tag-linux-2","tag-script","tag-ssl","tag-unifi","tag-unifi-video"],"_links":{"self":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/2376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/comments?post=2376"}],"version-history":[{"count":4,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/2376\/revisions"}],"predecessor-version":[{"id":3580,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/posts\/2376\/revisions\/3580"}],"wp:attachment":[{"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/media?parent=2376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/categories?post=2376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.incredigeek.com\/home\/wp-json\/wp\/v2\/tags?post=2376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}