entrypoint.sh 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/bin/bash
  2. # shellcheck disable=SC2155
  3. set -u
  4. function check_deprecated_env_var {
  5. if [[ -n "${ACME_TOS_HASH:-}" ]]; then
  6. echo "Info: the ACME_TOS_HASH environment variable is no longer used by simp_le and has been deprecated."
  7. echo "simp_le now implicitly agree to the ACME CA ToS."
  8. fi
  9. }
  10. function check_docker_socket {
  11. if [[ $DOCKER_HOST == unix://* ]]; then
  12. socket_file=${DOCKER_HOST#unix://}
  13. if [[ ! -S $socket_file ]]; then
  14. echo "Error: you need to share your Docker host socket with a volume at $socket_file" >&2
  15. echo "Typically you should run your container with: '-v /var/run/docker.sock:$socket_file:ro'" >&2
  16. exit 1
  17. fi
  18. fi
  19. }
  20. function check_writable_directory {
  21. local dir="$1"
  22. if [[ $(get_self_cid) ]]; then
  23. docker_api "/containers/$(get_self_cid)/json" | jq ".Mounts[].Destination" | grep -q "^\"$dir\"$"
  24. [[ $? -ne 0 ]] && echo "Warning: '$dir' does not appear to be a mounted volume."
  25. else
  26. echo "Warning: can't check if '$dir' is a mounted volume without self container ID."
  27. fi
  28. if [[ ! -d "$dir" ]]; then
  29. echo "Error: can't access to '$dir' directory !" >&2
  30. echo "Check that '$dir' directory is declared as a writable volume." >&2
  31. exit 1
  32. fi
  33. touch $dir/.check_writable 2>/dev/null
  34. if [[ $? -ne 0 ]]; then
  35. echo "Error: can't write to the '$dir' directory !" >&2
  36. echo "Check that '$dir' directory is export as a writable volume." >&2
  37. exit 1
  38. fi
  39. rm -f $dir/.check_writable
  40. }
  41. function check_dh_group {
  42. # Credits to Steve Kamerman for the background Diffie-Hellman creation logic.
  43. # https://github.com/jwilder/nginx-proxy/pull/589
  44. local DHPARAM_BITS="${DHPARAM_BITS:-2048}"
  45. re='^[0-9]*$'
  46. if ! [[ "$DHPARAM_BITS" =~ $re ]] ; then
  47. echo "Error: invalid Diffie-Hellman size of $DHPARAM_BITS !" >&2
  48. exit 1
  49. fi
  50. # If a dhparam file is not available, use the pre-generated one and generate a new one in the background.
  51. local PREGEN_DHPARAM_FILE="/app/dhparam.pem.default"
  52. local DHPARAM_FILE="/etc/nginx/certs/dhparam.pem"
  53. local GEN_LOCKFILE="/tmp/le_companion_dhparam_generating.lock"
  54. # The hash of the pregenerated dhparam file is used to check if the pregen dhparam is already in use
  55. local PREGEN_HASH=$(sha256sum "$PREGEN_DHPARAM_FILE" | cut -d ' ' -f1)
  56. if [[ -f "$DHPARAM_FILE" ]]; then
  57. local CURRENT_HASH=$(sha256sum "$DHPARAM_FILE" | cut -d ' ' -f1)
  58. if [[ "$PREGEN_HASH" != "$CURRENT_HASH" ]]; then
  59. # There is already a dhparam, and it's not the default
  60. set_ownership_and_permissions "$DHPARAM_FILE"
  61. echo "Info: Custom Diffie-Hellman group found, generation skipped."
  62. return 0
  63. fi
  64. if [[ -f "$GEN_LOCKFILE" ]]; then
  65. # Generation is already in progress
  66. return 0
  67. fi
  68. fi
  69. echo "Info: Creating Diffie-Hellman group in the background."
  70. echo "A pre-generated Diffie-Hellman group will be used for now while the new one
  71. is being created."
  72. # Put the default dhparam file in place so we can start immediately
  73. cp "$PREGEN_DHPARAM_FILE" "$DHPARAM_FILE"
  74. set_ownership_and_permissions "$DHPARAM_FILE"
  75. touch "$GEN_LOCKFILE"
  76. # Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator).
  77. (
  78. (
  79. nice -n +5 openssl dhparam -out "${DHPARAM_FILE}.new" "$DHPARAM_BITS" 2>&1 \
  80. && mv "${DHPARAM_FILE}.new" "$DHPARAM_FILE" \
  81. && echo "Info: Diffie-Hellman group creation complete, reloading nginx." \
  82. && set_ownership_and_permissions "$DHPARAM_FILE" \
  83. && reload_nginx
  84. ) | grep -vE '^[\.+]+'
  85. rm "$GEN_LOCKFILE"
  86. ) & disown
  87. }
  88. function check_default_cert_key {
  89. local cn='letsencrypt-nginx-proxy-companion'
  90. if [[ -e /etc/nginx/certs/default.crt && -e /etc/nginx/certs/default.key ]]; then
  91. default_cert_cn="$(openssl x509 -noout -subject -in /etc/nginx/certs/default.crt)"
  92. # Check if the existing default certificate is still valid for more
  93. # than 3 months / 7776000 seconds (60 x 60 x 24 x 30 x 3).
  94. check_cert_min_validity /etc/nginx/certs/default.crt 7776000
  95. cert_validity=$?
  96. [[ "$(lc $DEBUG)" == true ]] && echo "Debug: a default certificate with $default_cert_cn is present."
  97. fi
  98. # Create a default cert and private key if:
  99. # - either default.crt or default.key are absent
  100. # OR
  101. # - the existing default cert/key were generated by the container
  102. # and the cert validity is less than three months
  103. if [[ ! -e /etc/nginx/certs/default.crt || ! -e /etc/nginx/certs/default.key ]] || [[ "${default_cert_cn:-}" =~ $cn && "${cert_validity:-}" -ne 0 ]]; then
  104. openssl req -x509 \
  105. -newkey rsa:4096 -sha256 -nodes -days 365 \
  106. -subj "/CN=$cn" \
  107. -keyout /etc/nginx/certs/default.key.new \
  108. -out /etc/nginx/certs/default.crt.new \
  109. && mv /etc/nginx/certs/default.key.new /etc/nginx/certs/default.key \
  110. && mv /etc/nginx/certs/default.crt.new /etc/nginx/certs/default.crt
  111. echo "Info: a default key and certificate have been created at /etc/nginx/certs/default.key and /etc/nginx/certs/default.crt."
  112. elif [[ "$(lc $DEBUG)" == true && "${default_cert_cn:-}" =~ $cn ]]; then
  113. echo "Debug: the self generated default certificate is still valid for more than three months. Skipping default certificate creation."
  114. elif [[ "$(lc $DEBUG)" == true ]]; then
  115. echo "Debug: the default certificate is user provided. Skipping default certificate creation."
  116. fi
  117. set_ownership_and_permissions "/etc/nginx/certs/default.key"
  118. set_ownership_and_permissions "/etc/nginx/certs/default.crt"
  119. }
  120. source /app/functions.sh
  121. if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
  122. acmev1_r='acme-(v01\|staging)\.api\.letsencrypt\.org'
  123. if [[ "${ACME_CA_URI:-}" =~ $acmev1_r ]]; then
  124. echo "Error: the ACME v1 API is no longer supported by simp_le."
  125. echo "See https://github.com/zenhack/simp_le/pull/119"
  126. echo "Please use one of Let's Encrypt ACME v2 endpoints instead."
  127. exit 1
  128. fi
  129. check_docker_socket
  130. if [[ -z "$(get_nginx_proxy_container)" ]]; then
  131. echo "Error: can't get nginx-proxy container ID !" >&2
  132. echo "Check that you are doing one of the following :" >&2
  133. echo -e "\t- Use the --volumes-from option to mount volumes from the nginx-proxy container." >&2
  134. echo -e "\t- Set the NGINX_PROXY_CONTAINER env var on the letsencrypt-companion container to the name of the nginx-proxy container." >&2
  135. echo -e "\t- Label the nginx-proxy container to use with 'com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy'." >&2
  136. exit 1
  137. elif [[ -z "$(get_docker_gen_container)" ]] && ! is_docker_gen_container "$(get_nginx_proxy_container)"; then
  138. echo "Error: can't get docker-gen container id !" >&2
  139. echo "If you are running a three containers setup, check that you are doing one of the following :" >&2
  140. echo -e "\t- Set the NGINX_DOCKER_GEN_CONTAINER env var on the letsencrypt-companion container to the name of the docker-gen container." >&2
  141. echo -e "\t- Label the docker-gen container to use with 'com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen.'" >&2
  142. exit 1
  143. fi
  144. check_writable_directory '/etc/nginx/certs'
  145. check_writable_directory '/etc/nginx/vhost.d'
  146. check_writable_directory '/usr/share/nginx/html'
  147. check_deprecated_env_var
  148. check_default_cert_key
  149. check_dh_group
  150. reload_nginx
  151. fi
  152. exec "$@"