Skip to content
Valentin Hilbig edited this page Aug 24, 2021 · 12 revisions

This once was a fork from dehydrated with ACME v1. When ACME v2 came I retired this archive in favor of the Debian package dehydrated.

HowTo use dehydrated with Debian

This here explains how to use the package dehydrated on Debian. It is not a complete solution, tough.

Perhaps I come around to publish my complete automated solution in a ready-to-use fashoin, but this currently contains too much private data I have to sort out.

Rationale

For security reason I do not recommend to run dehydrated directly on the servers. Due to following:

  • If somebody cracks the server, the web page and the web server's key are compromized.

    • In that case you want to revoke the certificate, right?
    • But how to do this if you are no more in control of your server, such that the attacker could have changed everything, including the LetsEncrypt account?
    • This does NOT protect you against somebody creating another LE certificate for your server. But this is not your problem. Your problem is to revoke your compromized certificate!
  • Even much more important, you perhaps need to use the certificate on different servers as well

    • Like in a "Loadbalancer with Failover" situation. There are 2 loadbalancers. Both need the same certificate.
    • In that case, if some attacker breaks into one machine, there will be a direct connection to the second machine. Break one and take it all. Bad.

Also it is good to have just one single point where to manage all the certificates. So you can keep everything easily in sight.

How to run on a separate host

  • Have a dedicated VM or similar running somewhere in a safe spot (DMZ at home). This can be done on a Raspberry PI easily, too.

  • Install a recent plain Debian. You do not need more than just the basic Debian.

    sudo apt-get install dehydrated

  • Create a config file like (the link may contain an update for following):

WELLKNOWN="${BASEDIR}/.acme-challenges"
HOOK=./hook.sh
PRIVATE_KEY_RENEW="no"
CONTACT_EMAIL=webmaster@example.com
#!/bin/bash

sftpdeploy()
{
  all="${3%.pem}full.pem"
  cat "$3" "$5" > "$all"
  dh=()
  for a in dhparam2048.pem dhparam4096.pem
  do
	[ -f "${3%/*}/$a" ] && dh+=("${3%/*}/$a")
  done

  for a in "$3" "$4" "$5" "$6" "$all" "${dh[@]}"
  do
	echo "put '$a' 'certs/$2/'"
  done
  for a in "$3" "$all" "${dh[@]}"
  do
	echo "chmod 640 'certs/$2/${a##*/}'"
  done
  for a in "$4" "$5" "$6"
  do
	echo "chmod 644 'certs/$2/${a##*/}'"
  done
}

HERE="$(dirname "$0")" &&
case "$1" in
deploy_challenge)	sftp -b- -o StrictHostKeyChecking=no "letsencrypt@$2" <<<"put '.acme-challenges/$3' 'web/.well-known/acme-challenge/'";;
clean_challenge)	sftp -b- "letsencrypt@$2" <<<"rm 'web/.well-known/acme-challenge/$3'";;
deploy_cert)		sftp -b- "letsencrypt@$2" <<<"mkdir 'certs/$2'"
			sftp -b- "letsencrypt@$2" < <(sftpdeploy "$@") && touch "updates/$2"
			;;
startup_hook)		true;;	# ignored for now
unchanged_cert)		true;;	# ignored for now
generate_csr)		true;;	# ignored for now
exit_hook)		true;;	# ignored for now
this_hookscript_is_broken__dehydrated_is_working_fine__please_ignore_unknown_hooks_in_your_script)	true;;
*)			printf 'WARNING! Unknown hook ignored: %q\r\n' "$1" >&2;;
esac && exit

{
  printf '\r\nerror code %s, call was:\r\n' "$?"
  printf ' %q\r\n' "$0" "$@"
  printf 'Press Return to continue: '
} >&2
read

Now edit domains.txt accordingly, then invoke ./run.sh.

hook.sh then consults .ssh/config to remotely log into the host to deploy the ACME-challenges and SSL certificates.

To see what to do on the remote, see hook.sh (or read on)

Setup on the managed hosts

hook.sh opens an sftp connection via ssh to the remote using letsencrypt@DOMAIN.

  • For example.com it tries to contact letsencrypt@example.com
  • For the challenges, it connects to all of the DOMAINs given on the line in domain.txt this way.
  • For the cert, it connects only to the first DOMAIN given on each line in domain.txt.

This way you can utilize the full power of ssh to automatically connect to some remote host.

  • This includes tunnelling over jumphosts for this purpose etc.
    • This includes the power to use something like a portcullis and intrinsic other ways to (automatically) open the gates to a machine
    • So this transport has nothing to do with hook.sh, it solely has to do with ssh
  • At the receiving side you do not need anything except ssh, as internal-sftp can be used
    • So again you have the full power of sshd without the need of more or other external references

Dedicated VM

Here is how I run it:

  • I created a dedicated VM which runs on some internal machine
    • The internal machine only needs to be up
    • It is able to connect to every server it needs to deploy certs
    • And it is able to connect to LetsEncrypt, too
  • In the VM I placed the files here into some subdirectory of a chosen user
    • See above
  • And then I run run.sh from cron
    • With some helper scripts
  • Also I added some more scripts which are able to
    • deploy the certs into more than one server (for redundant loadbalancers etc.)
    • check if everything works as expected (like

Unfortunately I cannot OpenSource my full scripting yet, because it contains too much private data. But perhaps when I need to extend it (for example for wildcard certificates) I can rework it to push the main parts to GitHub.

However without proper documentation it might be a bit difficult for others to use it.

Clone this wiki locally