#format wiki
#language en
 * Links: [[Linux/OpenSSL]] , [[security/ssl]]
= LetsEncrypt - Free certificate authority =
 * Web server updates can be automated.

== 2025 Cert expiry monitoring ==
 * Sign up for a third-party monitoring service that may provide expiration emails. We can recommend Red Sift Certificates Lite, which provides free expiration emails for up to 250 active certificates:
   * https://redsift.com/pulse-platform/certificates-lite
   * Automated Renewal Information (ARI)

== 2021-05 Run letsencrypt in podman container ==
 * Create dirs /etc/letsencrypt and /var/lib/letsencrypt, owned by current user.
 * Allow normal user to bind to port 80 {{{
sysctl net.ipv4.ip_unprivileged_port_start=80
}}}
 * Command to get cert, see --security-opt {{{
$ podman run -it --rm --name certbot --security-opt label=disable  -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/l
etsencrypt"  certbot/certbot certonly
}}}

== 2021 - Ubuntu letsencrypt - add domain to SAN list in certificate ==
 1. Run {{{
# certbot certonly --cert-name www.vigor.nz --webroot --webroot-path /var/www/static  -d www.vigor.nz,vigor.nz,git.vigor.nz,smtp.vigor.nz,pin.vigor.nz,ssl.vigor.nz,wiki.vigor.nz,vigor.co.za,keulder.com,www.keulder.com,johan.keulder.com,smtp.probfaci.co.za

}}}
 2. Using existing nginx with static dir, select {{{
2: Place files in webroot directory (webroot)
}}}
 3. Specify the static path e.g. {{{
/var/www/static
}}}
1. Output e.g. {{{
...
Using the webroot path /var/www/static for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
...
}}}

== 2017 - Cloudflare - LetsEncrypt certificate automation ==
 * Use the letsencrypt certbot package on ubuntu
 * Run
   {{{
  export CF_EMAIL='name@me.com'
export CF_KEY='PutCFKeyHere-AND-REMOVE'
certbot certonly \
        --manual \
        --preferred-challenges dns \
        --manual-auth-hook ~/certbot-cloudflare-hook-authenticator.sh \
        --config-dir . \
        --work-dir .   \
        --logs-dir .   \
   -d test1.me.com    \
   -d test2.me.com    \
   -d www.me.com

}}} 
 * Bash script 
   {{{
#!/bin/bash

## certbot certonly --manual --preferred-challenges=dns --manual-auth-hook ~/certbot-cloudflare-hook-authenticator.sh -d secure.me.com
#
# Get your API key from https://www.cloudflare.com/a/account/my-account
API_KEY="$CF_KEY"
EMAIL="$CF_EMAIL"

# Strip only the top domain to get the zone id
DOMAIN=$(expr match "$CERTBOT_DOMAIN" '.*\.\(.*\..*\)')

# Get the Cloudflare zone id
ZONE_EXTRA_PARAMS="status=active&page=1&per_page=20&order=status&direction=desc&match=all"
ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN&$ZONE_EXTRA_PARAMS" \
     -H     "X-Auth-Email: $EMAIL" \
     -H     "X-Auth-Key: $API_KEY" \
     -H     "Content-Type: application/json" | python -c "import sys,json;print(json.load(sys.stdin)['result'][0]['id'])")

# Create TXT record
CREATE_DOMAIN="_acme-challenge.$CERTBOT_DOMAIN"
RECORD_ID=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
     -H     "X-Auth-Email: $EMAIL" \
     -H     "X-Auth-Key: $API_KEY" \
     -H     "Content-Type: application/json" \
     --data '{"type":"TXT","name":"'"$CREATE_DOMAIN"'","content":"'"$CERTBOT_VALIDATION"'","ttl":120}' \
             | python -c "import sys,json;print(json.load(sys.stdin)['result']['id'])")
# Save info for cleanup
if [ ! -d /tmp/CERTBOT_$CERTBOT_DOMAIN ];then
        mkdir -m 0700 /tmp/CERTBOT_$CERTBOT_DOMAIN
fi
echo $ZONE_ID > /tmp/CERTBOT_$CERTBOT_DOMAIN/ZONE_ID
echo $RECORD_ID > /tmp/CERTBOT_$CERTBOT_DOMAIN/RECORD_ID

# Sleep to make sure the change has time to propagate over to DNS
sleep 25
}}}

...