Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save enriluis/0697cf92267b01d0855cabab9ea2d973 to your computer and use it in GitHub Desktop.

Select an option

Save enriluis/0697cf92267b01d0855cabab9ea2d973 to your computer and use it in GitHub Desktop.
Let's encrypt SSL certificates using certbot in docker

Directories on host machine:

  • /data/certbot/letsencrypt

  • /data/certbot/www

  • Nginx server in docker container

docker run -d --name nginx \
    ...
    -v /data/certbot/letsencrypt:/etc/letsencrypt
    -v /data/certbot/www:/var/www/certbot
    nginx
    

config file for your site

server {
  listen 80;
  server_name mysite.com;

  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }

  location / {
      return 301 https://$host$request_uri;
  }
}


server {
  listen 443 ssl;
  server_name mysite.com;

  access_log /var/log/nginx/access.log combined_ssl;

  ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem;

  #include /data/letsencrypt/options-ssl-nginx.conf;
  #ssl_dhparam /data/letsencrypt/ssl-dhparams.pem;

  location / {
      set $upstream "site_upstream";

      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      proxy_set_header X-Real-Port $server_port;
      proxy_set_header X-Real-Scheme $scheme;
      proxy_set_header X-NginX-Proxy true;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Ssl on;

      expires off;

      proxy_pass http://$upstream;
  }
}

upstream site_upstream{
    server 51.1.0.20:80;
}

  • run certbot
docker run --rm --name temp_certbot \
    -v /data/certbot/letsencrypt:/etc/letsencrypt \
    -v /data/certbot/www:/tmp/letsencrypt \
    -v /data/servers-data/certbot/log:/var/log \
    certbot/certbot:v1.8.0 \
    certonly --webroot --agree-tos --renew-by-default \
    --preferred-challenges http-01 --server https://acme-v02.api.letsencrypt.org/directory \
    --text --email mxdevit@gmail.com \
    -w /tmp/letsencrypt -d mysite.com

it will create new certificates in /data/certbot/letsencrypt/live/mysite.com/.

restart nginx

docker restart nginx

Script to manage SSL certificates

/data/certbot/ssl_update.sh

  • generates a self-signed certificate if certificate doesn't exist
  • renew certificates with Let's Encrypt if certificate expires or about to expire

see the script below.

inspired by https://github.com/vdhpieter/docker-letsencrypt-webroot.

  • update certificates

ssl_mysite.sh

#!/bin/bash

export CERT_DIR_PATH="/data/certbot/letsencrypt";
export WEBROOT_PATH="/data/certbot/www";
export LE_RENEW_HOOK="docker restart nginx"; # <--- change to your nginx server docker container name
export DOMAINS="mysite.com";
export EMAIL="myemail@gmail.com";
export EXP_LIMIT="30";
export CHECK_FREQ="30";
export CHICKENEGG="1";
export STAGING="0";

bash /data/certbot/ssl_update.sh
                  
#!/bin/bash
if [[ -z $DOMAINS ]]; then
echo "No domains set, please fill -e 'DOMAINS=example.com www.example.com'"
exit 1
fi
if [[ -z $EMAIL ]]; then
echo "No email set, please fill -e 'EMAIL=your@email.tld'"
exit 1
fi
if [[ -z $CERT_DIR_PATH ]]; then
echo "No cert dir path set, please fill -e 'CERT_DIR_PATH=/etc/letsencrypt'"
exit 1
fi
if [[ -z $WEBROOT_PATH ]]; then
echo "No webroot path set, please fill -e 'WEBROOT_PATH=/tmp/letsencrypt'"
exit 1
fi
if [[ $STAGING -eq 1 ]]; then
echo "Using the staging environment"
ADDITIONAL="--staging"
fi
DARRAYS=(${DOMAINS})
EMAIL_ADDRESS=${EMAIL}
LE_DOMAINS=("${DARRAYS[*]/#/-d }")
exp_limit="${EXP_LIMIT:-30}"
check_freq="${CHECK_FREQ:-30}"
le_hook()
{
command=$(echo $LE_RENEW_HOOK)
echo "[INFO] Run: $command"
eval $command
}
le_fixpermissions() {
echo "[INFO] Fixing permissions"
chown -R ${CHOWN:-root:root} ${CERT_DIR_PATH}
find ${CERT_DIR_PATH} -type d -exec chmod 755 {} \;
find ${CERT_DIR_PATH} -type f -exec chmod ${CHMOD:-644} {} \;
}
le_renew() {
docker run --rm --name temp_certbot \
-v "${CERT_DIR_PATH}:/etc/letsencrypt" \
-v "${WEBROOT_PATH}:/tmp/letsencrypt" \
-v "/data/servers-data/certbot/log:/var/log" \
certbot/certbot:v1.8.0 certonly --webroot --agree-tos --renew-by-default \
--preferred-challenges http-01 \
--server https://acme-v02.api.letsencrypt.org/directory --text ${ADDITIONAL} \
--email ${EMAIL_ADDRESS} -w /tmp/letsencrypt ${LE_DOMAINS}
le_fixpermissions
le_hook
}
le_check() {
cert_file="$CERT_DIR_PATH/live/$DARRAYS/fullchain.pem";
echo "START check";
echo "file: $cert_file";
if [[ -e $cert_file ]]; then
exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
datenow=$(date -d "now" +%s)
days_exp=$[ ( $exp - $datenow ) / 86400 ]
echo "Checking expiration date for $DARRAYS..."
if [ "$days_exp" -gt "$exp_limit" ] ; then
echo "The certificate is up to date, no need for renewal ($days_exp days left)."
else
echo "The certificate for $DARRAYS is about to expire soon. Starting webroot renewal script..."
le_renew
echo "Renewal process finished for domain $DARRAYS"
fi
echo "Checking domains for $DARRAYS..."
domains=($(openssl x509 -in $cert_file -text -noout | grep -oP '(?<=DNS:)[^,]*'))
new_domains=($(
for domain in ${DARRAYS[@]}; do
[[ " ${domains[@]} " =~ " ${domain} " ]] || echo $domain
done
))
if [ -z "$new_domains" ] ; then
echo "The certificate have no changes, no need for renewal"
else
echo "The list of domains for $DARRAYS certificate has been changed. Starting webroot renewal script..."
le_renew
echo "Renewal process finished for domain $DARRAYS"
fi
else
echo "[INFO] certificate file not found for domain $DARRAYS. Starting webroot initial certificate request script..."
if [[ $CHICKENEGG -eq 1 ]]; then
echo "Making a temporary self signed certificate to prevent chicken and egg problems"
mkdir -p $CERT_DIR_PATH/live/$DARRAYS
openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout "$CERT_DIR_PATH/live/$DARRAYS/privkey.pem" -out "${cert_file}" -subj "/CN=example.com" -days 1
fi
le_renew
echo "Certificate request process finished for domain $DARRAYS"
fi
}
echo "--- start. $(date)";
le_check $1
@Elier2016
Copy link
Copy Markdown

Muy bien mi hermano, buen trabajo el que hiciste

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