]> git.proxmox.com Git - mirror_acme.sh.git/blame - le.sh
add fedora
[mirror_acme.sh.git] / le.sh
CommitLineData
4c3b3608 1#!/usr/bin/env bash
2VER=1.1.8
3PROJECT="https://github.com/Neilpang/le"
4
5DEFAULT_CA="https://acme-v01.api.letsencrypt.org"
6DEFAULT_AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
7
8STAGE_CA="https://acme-staging.api.letsencrypt.org"
9
10VTYPE_HTTP="http-01"
11VTYPE_DNS="dns-01"
12
13if [ -z "$AGREEMENT" ] ; then
14 AGREEMENT="$DEFAULT_AGREEMENT"
15fi
16
17_debug() {
18
19 if [ -z "$DEBUG" ] ; then
20 return
21 fi
22
23 if [ -z "$2" ] ; then
24 echo $1
25 else
26 echo "$1"="$2"
27 fi
28}
29
30_info() {
31 if [ -z "$2" ] ; then
32 echo "$1"
33 else
34 echo "$1"="$2"
35 fi
36}
37
38_err() {
39 if [ -z "$2" ] ; then
40 echo "$1" >&2
41 else
42 echo "$1"="$2" >&2
43 fi
44 return 1
45}
46
47_h2b() {
48 hex=$(cat)
49 i=1
50 j=2
51 while [ '1' ] ; do
52 h=$(printf $hex | cut -c $i-$j)
53 if [ -z "$h" ] ; then
54 break;
55 fi
56 printf "\x$h"
57 let "i+=2"
58 let "j+=2"
59 done
60}
61
62_base64() {
63 openssl base64 -e | tr -d '\n'
64}
65
34c27e09 66_ss() {
67 _port="$1"
68 if command -v "netstat" >/dev/null 2>&1 ; then
251fc37c 69 _debug "Using: netstat"
34c27e09 70 netstat -ntpl | grep :$_port" "
71 return 0
72 fi
73 if command -v "ss" >/dev/null 2>&1 ; then
251fc37c 74 _debug "Using: ss"
34c27e09 75 ss -ntpl | grep :$_port" "
76 return 0
77 fi
78 return 1
79}
80
4c3b3608 81#domain [2048]
82createAccountKey() {
83 _info "Creating account key"
84 if [ -z "$1" ] ; then
85 echo Usage: createAccountKey account-domain [2048]
86 return
87 fi
88
89 account=$1
90 length=$2
91
92 if [[ "$length" == "ec-"* ]] ; then
93 length=2048
94 fi
95
96 if [ -z "$2" ] ; then
97 _info "Use default length 2048"
98 length=2048
99 fi
100 _initpath
101
102 if [ -f "$ACCOUNT_KEY_PATH" ] ; then
103 _info "Account key exists, skip"
104 return
105 else
106 #generate account key
f89d991d 107 openssl genrsa $length 2>/dev/null > "$ACCOUNT_KEY_PATH"
4c3b3608 108 fi
109
110}
111
112#domain length
113createDomainKey() {
114 _info "Creating domain key"
115 if [ -z "$1" ] ; then
116 echo Usage: createDomainKey domain [2048]
117 return
118 fi
119
120 domain=$1
121 length=$2
122 isec=""
123 if [[ "$length" == "ec-"* ]] ; then
124 isec="1"
125 length=$(printf $length | cut -d '-' -f 2-100)
126 eccname="$length"
127 fi
128
129 if [ -z "$length" ] ; then
130 if [ "$isec" ] ; then
131 length=256
132 else
133 length=2048
134 fi
135 fi
136 _info "Use length $length"
137
138 if [ "$isec" ] ; then
139 if [ "$length" == "256" ] ; then
140 eccname="prime256v1"
141 fi
142 if [ "$length" == "384" ] ; then
143 eccname="secp384r1"
144 fi
145 if [ "$length" == "521" ] ; then
146 eccname="secp521r1"
147 fi
148 _info "Using ec name: $eccname"
149 fi
150
151 _initpath $domain
152
153 if [ ! -f "$CERT_KEY_PATH" ] || ( [ "$FORCE" ] && ! [ "$IS_RENEW" ] ); then
154 #generate account key
155 if [ "$isec" ] ; then
156 openssl ecparam -name $eccname -genkey 2>/dev/null > "$CERT_KEY_PATH"
157 else
158 openssl genrsa $length 2>/dev/null > "$CERT_KEY_PATH"
159 fi
160 else
161 if [ "$IS_RENEW" ] ; then
162 _info "Domain key exists, skip"
163 return 0
164 else
165 _err "Domain key exists, do you want to overwrite the key?"
166 _err "Set FORCE=1, and try again."
167 return 1
168 fi
169 fi
170
171}
172
173# domain domainlist
174createCSR() {
175 _info "Creating csr"
176 if [ -z "$1" ] ; then
177 echo Usage: $0 domain [domainlist]
178 return
179 fi
180 domain=$1
181 _initpath $domain
182
183 domainlist=$2
184
185 if [ -f "$CSR_PATH" ] && [ "$IS_RENEW" ] && ! [ "$FORCE" ]; then
186 _info "CSR exists, skip"
187 return
188 fi
189
190 if [ -z "$domainlist" ] ; then
191 #single domain
192 _info "Single domain" $domain
1ad65f7d 193 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\n" > "$DOMAIN_SSL_CONF"
194 openssl req -new -sha256 -key "$CERT_KEY_PATH" -subj "/CN=$domain" -config "$DOMAIN_SSL_CONF" -out "$CSR_PATH"
4c3b3608 195 else
196 alt="DNS:$(echo $domainlist | sed "s/,/,DNS:/g")"
197 #multi
198 _info "Multi domain" "$alt"
199 printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\n[SAN]\nsubjectAltName=$alt" > "$DOMAIN_SSL_CONF"
200 openssl req -new -sha256 -key "$CERT_KEY_PATH" -subj "/CN=$domain" -reqexts SAN -config "$DOMAIN_SSL_CONF" -out "$CSR_PATH"
201 fi
202
203}
204
205_b64() {
206 __n=$(cat)
207 echo $__n | tr '/+' '_-' | tr -d '= '
208}
209
210_time2str() {
211 #BSD
212 if date -u -d@$1 2>/dev/null ; then
213 return
214 fi
215
216 #Linux
217 if date -u -r $1 2>/dev/null ; then
218 return
219 fi
220
221}
222
44df2967 223_stat() {
224 #Linux
225 if stat -c '%U:%G' "$1" 2>/dev/null ; then
226 return
227 fi
228
229 #BSD
230 if stat -f '%Su:%Sg' "$1" 2>/dev/null ; then
231 return
232 fi
233}
234
4c3b3608 235_send_signed_request() {
236 url=$1
237 payload=$2
238 needbase64=$3
239
240 _debug url $url
241 _debug payload "$payload"
242
243 CURL_HEADER="$LE_WORKING_DIR/curl.header"
244 dp="$LE_WORKING_DIR/curl.dump"
245 CURL="curl --silent --dump-header $CURL_HEADER "
246 if [ "$DEBUG" ] ; then
247 CURL="$CURL --trace-ascii $dp "
248 fi
249 payload64=$(echo -n $payload | _base64 | _b64)
250 _debug payload64 $payload64
251
252 nonceurl="$API/directory"
253 nonce="$($CURL -I $nonceurl | grep -o "^Replay-Nonce:.*$" | tr -d "\r\n" | cut -d ' ' -f 2)"
254
255 _debug nonce "$nonce"
256
257 protected="$(printf "$HEADERPLACE" | sed "s/NONCE/$nonce/" )"
258 _debug protected "$protected"
259
260 protected64="$(printf "$protected" | _base64 | _b64)"
261 _debug protected64 "$protected64"
262
263 sig=$(echo -n "$protected64.$payload64" | openssl dgst -sha256 -sign $ACCOUNT_KEY_PATH | _base64 | _b64)
264 _debug sig "$sig"
265
266 body="{\"header\": $HEADER, \"protected\": \"$protected64\", \"payload\": \"$payload64\", \"signature\": \"$sig\"}"
267 _debug body "$body"
268
269 if [ "$needbase64" ] ; then
270 response="$($CURL -X POST --data "$body" $url | _base64)"
271 else
272 response="$($CURL -X POST --data "$body" $url)"
273 fi
274
275 responseHeaders="$(cat $CURL_HEADER)"
276
277 _debug responseHeaders "$responseHeaders"
278 _debug response "$response"
279 code="$(grep ^HTTP $CURL_HEADER | tail -1 | cut -d " " -f 2 | tr -d "\r\n" )"
280 _debug code $code
281
282}
283
284_get() {
285 url="$1"
286 _debug url $url
287 response="$(curl --silent $url)"
288 ret=$?
289 _debug response "$response"
290 code="$(echo $response | grep -o '"status":[0-9]\+' | cut -d : -f 2)"
291 _debug code $code
292 return $ret
293}
294
295#setopt "file" "opt" "=" "value" [";"]
296_setopt() {
297 __conf="$1"
298 __opt="$2"
299 __sep="$3"
300 __val="$4"
301 __end="$5"
302 if [ -z "$__opt" ] ; then
303 echo usage: _setopt '"file" "opt" "=" "value" [";"]'
304 return
305 fi
306 if [ ! -f "$__conf" ] ; then
307 touch "$__conf"
308 fi
309
310 if grep -H -n "^$__opt$__sep" "$__conf" > /dev/null ; then
311 _debug OK
312 if [[ "$__val" == *"&"* ]] ; then
313 __val="$(echo $__val | sed 's/&/\\&/g')"
314 fi
315 text="$(cat $__conf)"
6dfaaa70 316 echo "$text" | sed "s|^$__opt$__sep.*$|$__opt$__sep$__val$__end|" > "$__conf"
4c3b3608 317
318 elif grep -H -n "^#$__opt$__sep" "$__conf" > /dev/null ; then
319 if [[ "$__val" == *"&"* ]] ; then
320 __val="$(echo $__val | sed 's/&/\\&/g')"
321 fi
322 text="$(cat $__conf)"
6dfaaa70 323 echo "$text" | sed "s|^#$__opt$__sep.*$|$__opt$__sep$__val$__end|" > "$__conf"
4c3b3608 324
325 else
326 _debug APP
4c3b3608 327 echo "$__opt$__sep$__val$__end" >> "$__conf"
328 fi
329 _debug "$(grep -H -n "^$__opt$__sep" $__conf)"
330}
331
332#_savedomainconf key value
333#save to domain.conf
334_savedomainconf() {
335 key="$1"
336 value="$2"
337 if [ "$DOMAIN_CONF" ] ; then
338 _setopt $DOMAIN_CONF "$key" "=" "$value"
339 else
340 _err "DOMAIN_CONF is empty, can not save $key=$value"
341 fi
342}
343
344#_saveaccountconf key value
345_saveaccountconf() {
346 key="$1"
347 value="$2"
348 if [ "$ACCOUNT_CONF_PATH" ] ; then
349 _setopt $ACCOUNT_CONF_PATH "$key" "=" "$value"
350 else
351 _err "ACCOUNT_CONF_PATH is empty, can not save $key=$value"
352 fi
353}
354
355_startserver() {
356 content="$1"
1b2e940d 357 _NC="nc -q 1 -l"
358
359 nchelp="$(nc -h 2>&1)"
bce55f42 360 #centos
1b2e940d 361 if echo "$nchelp" | grep "nmap.org/ncat" >/dev/null ; then
362 _NC="nc -l"
4c3b3608 363 fi
1b2e940d 364
051c706d 365 _debug "$_NC $Le_HTTPPort"
4c3b3608 366# while true ; do
367 if [ "$DEBUG" ] ; then
3aff11f6 368 if ! echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort -vv ; then
369 echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort -vv ;
370 fi
4c3b3608 371 else
3aff11f6 372 if ! echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC -p $Le_HTTPPort > /dev/null ; then
373 echo -e -n "HTTP/1.1 200 OK\r\n\r\n$content" | $_NC $Le_HTTPPort > /dev/null
374 fi
4c3b3608 375 fi
051c706d 376 if [ "$?" != "0" ] ; then
377 _err "nc listen error."
378 return 1
379 fi
4c3b3608 380# done
381}
382
383_stopserver() {
384 pid="$1"
385
386}
387
388_initpath() {
389
390 if [ -z "$LE_WORKING_DIR" ]; then
391 LE_WORKING_DIR=$HOME/.le
392 fi
393
394 if [ -z "$ACCOUNT_CONF_PATH" ] ; then
395 ACCOUNT_CONF_PATH="$LE_WORKING_DIR/account.conf"
396 fi
397
398 if [ -f "$ACCOUNT_CONF_PATH" ] ; then
399 source "$ACCOUNT_CONF_PATH"
400 fi
401
402 if [ -z "$API" ] ; then
403 if [ -z "$STAGE" ] ; then
404 API="$DEFAULT_CA"
405 else
406 API="$STAGE_CA"
407 _info "Using stage api:$API"
408 fi
409 fi
410
411 if [ -z "$ACME_DIR" ] ; then
412 ACME_DIR="/home/.acme"
413 fi
414
415 if [ -z "$APACHE_CONF_BACKUP_DIR" ] ; then
416 APACHE_CONF_BACKUP_DIR="$LE_WORKING_DIR/"
417 fi
418
419 domain="$1"
420 if ! mkdir -p "$LE_WORKING_DIR" ; then
421 _err "Can not craete working dir: $LE_WORKING_DIR"
422 return 1
423 fi
424
425 if [ -z "$ACCOUNT_KEY_PATH" ] ; then
426 ACCOUNT_KEY_PATH="$LE_WORKING_DIR/account.key"
427 fi
428
429 if [ -z "$domain" ] ; then
430 return 0
431 fi
432
433 domainhome="$LE_WORKING_DIR/$domain"
434 mkdir -p "$domainhome"
435
436 if [ -z "$DOMAIN_PATH" ] ; then
437 DOMAIN_PATH="$domainhome"
438 fi
439 if [ -z "$DOMAIN_CONF" ] ; then
1ad65f7d 440 DOMAIN_CONF="$domainhome/$domain.conf"
4c3b3608 441 fi
442
443 if [ -z "$DOMAIN_SSL_CONF" ] ; then
1ad65f7d 444 DOMAIN_SSL_CONF="$domainhome/$domain.ssl.conf"
4c3b3608 445 fi
446
447 if [ -z "$CSR_PATH" ] ; then
448 CSR_PATH="$domainhome/$domain.csr"
449 fi
450 if [ -z "$CERT_KEY_PATH" ] ; then
451 CERT_KEY_PATH="$domainhome/$domain.key"
452 fi
453 if [ -z "$CERT_PATH" ] ; then
454 CERT_PATH="$domainhome/$domain.cer"
455 fi
456 if [ -z "$CA_CERT_PATH" ] ; then
457 CA_CERT_PATH="$domainhome/ca.cer"
458 fi
caf1fc10 459 if [ -z "$CERT_FULLCHAIN_PATH" ] ; then
850db6d4 460 CERT_FULLCHAIN_PATH="$domainhome/fullchain.cer"
caf1fc10 461 fi
4c3b3608 462
463}
464
465
466_apachePath() {
467 httpdroot="$(apachectl -V | grep HTTPD_ROOT= | cut -d = -f 2 | tr -d '"' )"
468 httpdconfname="$(apachectl -V | grep SERVER_CONFIG_FILE= | cut -d = -f 2 | tr -d '"' )"
469 httpdconf="$httpdroot/$httpdconfname"
470 if [ ! -f $httpdconf ] ; then
471 _err "Apache Config file not found" $httpdconf
472 return 1
473 fi
474 return 0
475}
476
477_restoreApache() {
478 if [ -z "$usingApache" ] ; then
479 return 0
480 fi
481 _initpath
482 if ! _apachePath ; then
483 return 1
484 fi
485
486 if [ ! -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname" ] ; then
487 _debug "No config file to restore."
488 return 0
489 fi
490
491 cp -p "$APACHE_CONF_BACKUP_DIR/$httpdconfname" "$httpdconf"
492 if ! apachectl -t ; then
493 _err "Sorry, restore apache config error, please contact me."
494 return 1;
495 fi
496 rm -f "$APACHE_CONF_BACKUP_DIR/$httpdconfname"
497 return 0
498}
499
500_setApache() {
501 _initpath
502 if ! _apachePath ; then
503 return 1
504 fi
505
506 #backup the conf
507 _debug "Backup apache config file" $httpdconf
508 cp -p $httpdconf $APACHE_CONF_BACKUP_DIR/
509 _info "JFYI, Config file $httpdconf is backuped to $APACHE_CONF_BACKUP_DIR/$httpdconfname"
510 _info "In case there is an error that can not be restored automatically, you may try restore it yourself."
511 _info "The backup file will be deleted on sucess, just forget it."
512
513 #add alias
514 echo "
515Alias /.well-known/acme-challenge $ACME_DIR
516
517<Directory $ACME_DIR >
518Require all granted
519</Directory>
520 " >> $httpdconf
521
522 if ! apachectl -t ; then
523 _err "Sorry, apache config error, please contact me."
524 _restoreApache
525 return 1;
526 fi
527
528 if [ ! -d "$ACME_DIR" ] ; then
529 mkdir -p "$ACME_DIR"
530 chmod 755 "$ACME_DIR"
531 fi
532
533 if ! apachectl graceful ; then
534 _err "Sorry, apachectl graceful error, please contact me."
535 _restoreApache
536 return 1;
537 fi
538 usingApache="1"
539 return 0
540}
541
542_clearup () {
543 _stopserver $serverproc
544 serverproc=""
545 _restoreApache
546}
547
548# webroot removelevel tokenfile
549_clearupwebbroot() {
550 __webroot="$1"
551 if [ -z "$__webroot" ] ; then
552 _debug "no webroot specified, skip"
553 return 0
554 fi
555
556 if [ "$2" == '1' ] ; then
557 _debug "remove $__webroot/.well-known"
558 rm -rf "$__webroot/.well-known"
559 elif [ "$2" == '2' ] ; then
560 _debug "remove $__webroot/.well-known/acme-challenge"
561 rm -rf "$__webroot/.well-known/acme-challenge"
562 elif [ "$2" == '3' ] ; then
563 _debug "remove $__webroot/.well-known/acme-challenge/$3"
564 rm -rf "$__webroot/.well-known/acme-challenge/$3"
565 else
566 _info "Skip for removelevel:$2"
567 fi
568
569 return 0
570
571}
572
573issue() {
574 if [ -z "$2" ] ; then
575 _err "Usage: le issue webroot|no|apache|dns a.com [www.a.com,b.com,c.com]|no [key-length]|no"
576 return 1
577 fi
578 Le_Webroot="$1"
579 Le_Domain="$2"
580 Le_Alt="$3"
581 Le_Keylength="$4"
582 Le_RealCertPath="$5"
583 Le_RealKeyPath="$6"
584 Le_RealCACertPath="$7"
585 Le_ReloadCmd="$8"
586
587
588 _initpath $Le_Domain
589
590 if [ -f "$DOMAIN_CONF" ] ; then
591 Le_NextRenewTime=$(grep "^Le_NextRenewTime=" "$DOMAIN_CONF" | cut -d '=' -f 2)
592 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ] ; then
593 _info "Skip, Next renewal time is: $(grep "^Le_NextRenewTimeStr" "$DOMAIN_CONF" | cut -d '=' -f 2)"
594 return 2
595 fi
596 fi
597
598 if [ "$Le_Alt" == "no" ] ; then
599 Le_Alt=""
600 fi
601 if [ "$Le_Keylength" == "no" ] ; then
602 Le_Keylength=""
603 fi
604 if [ "$Le_RealCertPath" == "no" ] ; then
605 Le_RealCertPath=""
606 fi
607 if [ "$Le_RealKeyPath" == "no" ] ; then
608 Le_RealKeyPath=""
609 fi
610 if [ "$Le_RealCACertPath" == "no" ] ; then
611 Le_RealCACertPath=""
612 fi
613 if [ "$Le_ReloadCmd" == "no" ] ; then
614 Le_ReloadCmd=""
615 fi
616
617 _setopt "$DOMAIN_CONF" "Le_Domain" "=" "$Le_Domain"
618 _setopt "$DOMAIN_CONF" "Le_Alt" "=" "$Le_Alt"
619 _setopt "$DOMAIN_CONF" "Le_Webroot" "=" "$Le_Webroot"
620 _setopt "$DOMAIN_CONF" "Le_Keylength" "=" "$Le_Keylength"
621 _setopt "$DOMAIN_CONF" "Le_RealCertPath" "=" "\"$Le_RealCertPath\""
622 _setopt "$DOMAIN_CONF" "Le_RealCACertPath" "=" "\"$Le_RealCACertPath\""
623 _setopt "$DOMAIN_CONF" "Le_RealKeyPath" "=" "\"$Le_RealKeyPath\""
624 _setopt "$DOMAIN_CONF" "Le_ReloadCmd" "=" "\"$Le_ReloadCmd\""
625
626 if [ "$Le_Webroot" == "no" ] ; then
627 _info "Standalone mode."
628 if ! command -v "nc" > /dev/null ; then
629 _err "Please install netcat(nc) tools first."
630 return 1
631 fi
632
633 if [ -z "$Le_HTTPPort" ] ; then
634 Le_HTTPPort=80
635 fi
636 _setopt "$DOMAIN_CONF" "Le_HTTPPort" "=" "$Le_HTTPPort"
637
251fc37c 638 netprc="$(_ss "$Le_HTTPPort" | grep "$Le_HTTPPort")"
4c3b3608 639 if [ "$netprc" ] ; then
640 _err "$netprc"
641 _err "tcp port $Le_HTTPPort is already used by $(echo "$netprc" | cut -d : -f 4)"
642 _err "Please stop it first"
643 return 1
644 fi
645 fi
646
647 if [ "$Le_Webroot" == "apache" ] ; then
648 if ! _setApache ; then
649 _err "set up apache error. Report error to me."
650 return 1
651 fi
652 wellknown_path="$ACME_DIR"
653 else
654 usingApache=""
655 fi
656
657 createAccountKey $Le_Domain $Le_Keylength
658
659 if ! createDomainKey $Le_Domain $Le_Keylength ; then
660 _err "Create domain key error."
661 return 1
662 fi
663
664 if ! createCSR $Le_Domain $Le_Alt ; then
665 _err "Create CSR error."
666 return 1
667 fi
668
669 pub_exp=$(openssl rsa -in $ACCOUNT_KEY_PATH -noout -text | grep "^publicExponent:"| cut -d '(' -f 2 | cut -d 'x' -f 2 | cut -d ')' -f 1)
670 if [ "${#pub_exp}" == "5" ] ; then
671 pub_exp=0$pub_exp
672 fi
673 _debug pub_exp "$pub_exp"
674
675 e=$(echo $pub_exp | _h2b | _base64)
676 _debug e "$e"
677
678 modulus=$(openssl rsa -in $ACCOUNT_KEY_PATH -modulus -noout | cut -d '=' -f 2 )
679 n=$(echo $modulus| _h2b | _base64 | _b64 )
680
681 jwk='{"e": "'$e'", "kty": "RSA", "n": "'$n'"}'
682
683 HEADER='{"alg": "RS256", "jwk": '$jwk'}'
684 HEADERPLACE='{"nonce": "NONCE", "alg": "RS256", "jwk": '$jwk'}'
685 _debug HEADER "$HEADER"
686
687 accountkey_json=$(echo -n "$jwk" | tr -d ' ' )
688 thumbprint=$(echo -n "$accountkey_json" | openssl dgst -sha256 -binary | _base64 | _b64)
689
690
691 _info "Registering account"
692 regjson='{"resource": "new-reg", "agreement": "'$AGREEMENT'"}'
693 if [ "$ACCOUNT_EMAIL" ] ; then
694 regjson='{"resource": "new-reg", "contact": ["mailto: '$ACCOUNT_EMAIL'"], "agreement": "'$AGREEMENT'"}'
695 fi
696 _send_signed_request "$API/acme/new-reg" "$regjson"
697
698 if [ "$code" == "" ] || [ "$code" == '201' ] ; then
699 _info "Registered"
700 echo $response > $LE_WORKING_DIR/account.json
701 elif [ "$code" == '409' ] ; then
702 _info "Already registered"
703 else
704 _err "Register account Error."
705 _clearup
706 return 1
707 fi
708
709 vtype="$VTYPE_HTTP"
710 if [[ "$Le_Webroot" == "dns"* ]] ; then
711 vtype="$VTYPE_DNS"
712 fi
713
714 vlist="$Le_Vlist"
715 # verify each domain
716 _info "Verify each domain"
717 sep='#'
718 if [ -z "$vlist" ] ; then
719 alldomains=$(echo "$Le_Domain,$Le_Alt" | tr ',' ' ' )
720 for d in $alldomains
721 do
722 _info "Getting token for domain" $d
723 _send_signed_request "$API/acme/new-authz" "{\"resource\": \"new-authz\", \"identifier\": {\"type\": \"dns\", \"value\": \"$d\"}}"
724 if [ ! -z "$code" ] && [ ! "$code" == '201' ] ; then
725 _err "new-authz error: $response"
726 _clearup
727 return 1
728 fi
729
348cddd7 730 entry="$(printf $response | egrep -o '\{[^{]*"type":"'$vtype'"[^}]*')"
4c3b3608 731 _debug entry "$entry"
732
733 token="$(printf "$entry" | egrep -o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
734 _debug token $token
735
736 uri="$(printf "$entry" | egrep -o '"uri":"[^"]*'| cut -d : -f 2,3 | tr -d '"' )"
737 _debug uri $uri
738
739 keyauthorization="$token.$thumbprint"
740 _debug keyauthorization "$keyauthorization"
741
742 dvlist="$d$sep$keyauthorization$sep$uri"
743 _debug dvlist "$dvlist"
744
745 vlist="$vlist$dvlist,"
746
747 done
748
749 #add entry
750 dnsadded=""
751 ventries=$(echo "$vlist" | tr ',' ' ' )
752 for ventry in $ventries
753 do
754 d=$(echo $ventry | cut -d $sep -f 1)
755 keyauthorization=$(echo $ventry | cut -d $sep -f 2)
756
757 if [ "$vtype" == "$VTYPE_DNS" ] ; then
758 dnsadded='0'
759 txtdomain="_acme-challenge.$d"
760 _debug txtdomain "$txtdomain"
761 txt="$(echo -e -n $keyauthorization | openssl dgst -sha256 -binary | _base64 | _b64)"
762 _debug txt "$txt"
763 #dns
764 #1. check use api
765 d_api=""
766 if [ -f "$LE_WORKING_DIR/$d/$Le_Webroot" ] ; then
767 d_api="$LE_WORKING_DIR/$d/$Le_Webroot"
768 elif [ -f "$LE_WORKING_DIR/$d/$Le_Webroot.sh" ] ; then
769 d_api="$LE_WORKING_DIR/$d/$Le_Webroot.sh"
770 elif [ -f "$LE_WORKING_DIR/$Le_Webroot" ] ; then
771 d_api="$LE_WORKING_DIR/$Le_Webroot"
772 elif [ -f "$LE_WORKING_DIR/$Le_Webroot.sh" ] ; then
773 d_api="$LE_WORKING_DIR/$Le_Webroot.sh"
774 elif [ -f "$LE_WORKING_DIR/dnsapi/$Le_Webroot" ] ; then
775 d_api="$LE_WORKING_DIR/dnsapi/$Le_Webroot"
776 elif [ -f "$LE_WORKING_DIR/dnsapi/$Le_Webroot.sh" ] ; then
777 d_api="$LE_WORKING_DIR/dnsapi/$Le_Webroot.sh"
778 fi
779 _debug d_api "$d_api"
780
781 if [ "$d_api" ]; then
782 _info "Found domain api file: $d_api"
783 else
784 _err "Add the following TXT record:"
785 _err "Domain: $txtdomain"
786 _err "TXT value: $txt"
787 _err "Please be aware that you prepend _acme-challenge. before your domain"
788 _err "so the resulting subdomain will be: $txtdomain"
789 continue
790 fi
791
792 if ! source $d_api ; then
793 _err "Load file $d_api error. Please check your api file and try again."
794 return 1
795 fi
796
797 addcommand="$Le_Webroot-add"
798 if ! command -v $addcommand ; then
f8ad8f34 799 _err "It seems that your api file is not correct, it must have a function named: $addcommand"
4c3b3608 800 return 1
801 fi
802
803 if ! $addcommand $txtdomain $txt ; then
804 _err "Error add txt for domain:$txtdomain"
805 return 1
806 fi
807 dnsadded='1'
808 fi
809 done
810
811 if [ "$dnsadded" == '0' ] ; then
812 _setopt "$DOMAIN_CONF" "Le_Vlist" "=" "\"$vlist\""
813 _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
814 _err "Please add the TXT records to the domains, and retry again."
815 return 1
816 fi
817
818 fi
819
820 if [ "$dnsadded" == '1' ] ; then
821 _info "Sleep 60 seconds for the txt records to take effect"
822 sleep 60
823 fi
824
825 _debug "ok, let's start to verify"
826 ventries=$(echo "$vlist" | tr ',' ' ' )
827 for ventry in $ventries
828 do
829 d=$(echo $ventry | cut -d $sep -f 1)
830 keyauthorization=$(echo $ventry | cut -d $sep -f 2)
831 uri=$(echo $ventry | cut -d $sep -f 3)
832 _info "Verifying:$d"
833 _debug "d" "$d"
834 _debug "keyauthorization" "$keyauthorization"
835 _debug "uri" "$uri"
836 removelevel=""
837 token=""
838 if [ "$vtype" == "$VTYPE_HTTP" ] ; then
839 if [ "$Le_Webroot" == "no" ] ; then
840 _info "Standalone mode server"
841 _startserver "$keyauthorization" &
842 serverproc="$!"
843 sleep 2
844 _debug serverproc $serverproc
845 else
846 if [ -z "$wellknown_path" ] ; then
847 wellknown_path="$Le_Webroot/.well-known/acme-challenge"
848 fi
849 _debug wellknown_path "$wellknown_path"
850
851 if [ ! -d "$Le_Webroot/.well-known" ] ; then
852 removelevel='1'
853 elif [ ! -d "$Le_Webroot/.well-known/acme-challenge" ] ; then
854 removelevel='2'
855 else
856 removelevel='3'
857 fi
858
859 token="$(echo -e -n "$keyauthorization" | cut -d '.' -f 1)"
860 _debug "writing token:$token to $wellknown_path/$token"
861
862 mkdir -p "$wellknown_path"
863 echo -n "$keyauthorization" > "$wellknown_path/$token"
864
44df2967 865 webroot_owner=$(_stat $Le_Webroot)
4c3b3608 866 _debug "Changing owner/group of .well-known to $webroot_owner"
867 chown -R $webroot_owner "$Le_Webroot/.well-known"
868
869 fi
870 fi
871
872 _send_signed_request $uri "{\"resource\": \"challenge\", \"keyAuthorization\": \"$keyauthorization\"}"
873
874 if [ ! -z "$code" ] && [ ! "$code" == '202' ] ; then
875 _err "$d:Challenge error: $resource"
876 _clearupwebbroot "$Le_Webroot" "$removelevel" "$token"
877 _clearup
878 return 1
879 fi
880
881 while [ "1" ] ; do
882 _debug "sleep 5 secs to verify"
883 sleep 5
884 _debug "checking"
885
886 if ! _get $uri ; then
887 _err "$d:Verify error:$resource"
888 _clearupwebbroot "$Le_Webroot" "$removelevel" "$token"
889 _clearup
890 return 1
891 fi
892
893 status=$(echo $response | egrep -o '"status":"[^"]+"' | cut -d : -f 2 | tr -d '"')
894 if [ "$status" == "valid" ] ; then
895 _info "Success"
896 _stopserver $serverproc
897 serverproc=""
898 _clearupwebbroot "$Le_Webroot" "$removelevel" "$token"
899 break;
900 fi
901
902 if [ "$status" == "invalid" ] ; then
903 error=$(echo $response | egrep -o '"error":{[^}]*}' | grep -o '"detail":"[^"]*"' | cut -d '"' -f 4)
904 _err "$d:Verify error:$error"
905 _clearupwebbroot "$Le_Webroot" "$removelevel" "$token"
906 _clearup
907 return 1;
908 fi
909
910 if [ "$status" == "pending" ] ; then
911 _info "Pending"
912 else
913 _err "$d:Verify error:$response"
914 _clearupwebbroot "$Le_Webroot" "$removelevel" "$token"
915 _clearup
916 return 1
917 fi
918
919 done
920
921 done
922
923 _clearup
924 _info "Verify finished, start to sign."
925 der="$(openssl req -in $CSR_PATH -outform DER | _base64 | _b64)"
926 _send_signed_request "$API/acme/new-cert" "{\"resource\": \"new-cert\", \"csr\": \"$der\"}" "needbase64"
927
928
929 Le_LinkCert="$(grep -i -o '^Location.*$' $CURL_HEADER | tr -d "\r\n" | cut -d " " -f 2)"
930 _setopt "$DOMAIN_CONF" "Le_LinkCert" "=" "$Le_LinkCert"
931
932 if [ "$Le_LinkCert" ] ; then
933 echo -----BEGIN CERTIFICATE----- > "$CERT_PATH"
934 curl --silent "$Le_LinkCert" | openssl base64 -e >> "$CERT_PATH"
935 echo -----END CERTIFICATE----- >> "$CERT_PATH"
936 _info "Cert success."
937 cat "$CERT_PATH"
938
939 _info "Your cert is in $CERT_PATH"
caf1fc10 940 cp "$CERT_PATH" "$CERT_FULLCHAIN_PATH"
4c3b3608 941 fi
942
943
944 if [ -z "$Le_LinkCert" ] ; then
945 response="$(echo $response | openssl base64 -d -A)"
946 _err "Sign failed: $(echo "$response" | grep -o '"detail":"[^"]*"')"
947 return 1
948 fi
949
950 _setopt "$DOMAIN_CONF" 'Le_Vlist' '=' "\"\""
951
952 Le_LinkIssuer=$(grep -i '^Link' $CURL_HEADER | cut -d " " -f 2| cut -d ';' -f 1 | tr -d '<>' )
953 _setopt "$DOMAIN_CONF" "Le_LinkIssuer" "=" "$Le_LinkIssuer"
954
955 if [ "$Le_LinkIssuer" ] ; then
956 echo -----BEGIN CERTIFICATE----- > "$CA_CERT_PATH"
957 curl --silent "$Le_LinkIssuer" | openssl base64 -e >> "$CA_CERT_PATH"
958 echo -----END CERTIFICATE----- >> "$CA_CERT_PATH"
959 _info "The intermediate CA cert is in $CA_CERT_PATH"
caf1fc10 960 cat "$CA_CERT_PATH" >> "$CERT_FULLCHAIN_PATH"
961 _info "And the full chain certs is there: $CERT_FULLCHAIN_PATH"
4c3b3608 962 fi
963
964 Le_CertCreateTime=$(date -u "+%s")
965 _setopt "$DOMAIN_CONF" "Le_CertCreateTime" "=" "$Le_CertCreateTime"
966
967 Le_CertCreateTimeStr=$(date -u )
968 _setopt "$DOMAIN_CONF" "Le_CertCreateTimeStr" "=" "\"$Le_CertCreateTimeStr\""
969
970 if [ ! "$Le_RenewalDays" ] ; then
971 Le_RenewalDays=80
972 fi
973
974 _setopt "$DOMAIN_CONF" "Le_RenewalDays" "=" "$Le_RenewalDays"
975
976 let "Le_NextRenewTime=Le_CertCreateTime+Le_RenewalDays*24*60*60"
977 _setopt "$DOMAIN_CONF" "Le_NextRenewTime" "=" "$Le_NextRenewTime"
978
979 Le_NextRenewTimeStr=$( _time2str $Le_NextRenewTime )
980 _setopt "$DOMAIN_CONF" "Le_NextRenewTimeStr" "=" "\"$Le_NextRenewTimeStr\""
981
982
983 installcert $Le_Domain "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd"
984
985}
986
987renew() {
988 Le_Domain="$1"
989 if [ -z "$Le_Domain" ] ; then
990 _err "Usage: $0 domain.com"
991 return 1
992 fi
993
994 _initpath $Le_Domain
995
996 if [ ! -f "$DOMAIN_CONF" ] ; then
997 _info "$Le_Domain is not a issued domain, skip."
998 return 0;
999 fi
1000
1001 source "$DOMAIN_CONF"
1002 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(date -u "+%s" )" -lt "$Le_NextRenewTime" ] ; then
1003 _info "Skip, Next renewal time is: $Le_NextRenewTimeStr"
1004 return 2
1005 fi
1006
1007 IS_RENEW="1"
1008 issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd"
1009 local res=$?
1010 IS_RENEW=""
1011
1012 return $res
1013}
1014
1015renewAll() {
1016 _initpath
1017 _info "renewAll"
1018
1019 for d in $(ls -F $LE_WORKING_DIR | grep [^.].*[.].*/$ ) ; do
1020 d=$(echo $d | cut -d '/' -f 1)
1021 _info "renew $d"
1022
1023 Le_LinkCert=""
1024 Le_Domain=""
1025 Le_Alt=""
1026 Le_Webroot=""
1027 Le_Keylength=""
1028 Le_LinkIssuer=""
1029
1030 Le_CertCreateTime=""
1031 Le_CertCreateTimeStr=""
1032 Le_RenewalDays=""
1033 Le_NextRenewTime=""
1034 Le_NextRenewTimeStr=""
1035
1036 Le_RealCertPath=""
1037 Le_RealKeyPath=""
1038
1039 Le_RealCACertPath=""
1040
1041 Le_ReloadCmd=""
1042
1043 DOMAIN_PATH=""
1044 DOMAIN_CONF=""
1045 DOMAIN_SSL_CONF=""
1046 CSR_PATH=""
1047 CERT_KEY_PATH=""
1048 CERT_PATH=""
1049 CA_CERT_PATH=""
caf1fc10 1050 CERT_FULLCHAIN_PATH=""
4c3b3608 1051 ACCOUNT_KEY_PATH=""
1052
1053 wellknown_path=""
1054
1055 renew "$d"
1056 done
1057
1058}
1059
1060installcert() {
1061 Le_Domain="$1"
1062 if [ -z "$Le_Domain" ] ; then
1063 _err "Usage: $0 domain.com [cert-file-path]|no [key-file-path]|no [ca-cert-file-path]|no [reloadCmd]|no"
1064 return 1
1065 fi
1066
1067 Le_RealCertPath="$2"
1068 Le_RealKeyPath="$3"
1069 Le_RealCACertPath="$4"
1070 Le_ReloadCmd="$5"
1071
1072 _initpath $Le_Domain
1073
1074 _setopt "$DOMAIN_CONF" "Le_RealCertPath" "=" "\"$Le_RealCertPath\""
1075 _setopt "$DOMAIN_CONF" "Le_RealCACertPath" "=" "\"$Le_RealCACertPath\""
1076 _setopt "$DOMAIN_CONF" "Le_RealKeyPath" "=" "\"$Le_RealKeyPath\""
1077 _setopt "$DOMAIN_CONF" "Le_ReloadCmd" "=" "\"$Le_ReloadCmd\""
1078
1079 if [ "$Le_RealCertPath" ] ; then
1080 if [ -f "$Le_RealCertPath" ] ; then
1081 cp -p "$Le_RealCertPath" "$Le_RealCertPath".bak
1082 fi
1083 cat "$CERT_PATH" > "$Le_RealCertPath"
1084 fi
1085
1086 if [ "$Le_RealCACertPath" ] ; then
1087 if [ -f "$Le_RealCACertPath" ] ; then
1088 cp -p "$Le_RealCACertPath" "$Le_RealCACertPath".bak
1089 fi
1090 if [ "$Le_RealCACertPath" == "$Le_RealCertPath" ] ; then
1091 echo "" >> "$Le_RealCACertPath"
1092 cat "$CA_CERT_PATH" >> "$Le_RealCACertPath"
1093 else
1094 cat "$CA_CERT_PATH" > "$Le_RealCACertPath"
1095 fi
1096 fi
1097
1098
1099 if [ "$Le_RealKeyPath" ] ; then
1100 if [ -f "$Le_RealKeyPath" ] ; then
1101 cp -p "$Le_RealKeyPath" "$Le_RealKeyPath".bak
1102 fi
1103 cat "$CERT_KEY_PATH" > "$Le_RealKeyPath"
1104 fi
1105
1106 if [ "$Le_ReloadCmd" ] ; then
1107 _info "Run Le_ReloadCmd: $Le_ReloadCmd"
1108 (cd "$DOMAIN_PATH" && eval "$Le_ReloadCmd")
1109 fi
1110
1111}
1112
1113installcronjob() {
1114 _initpath
1115 _info "Installing cron job"
1116 if ! crontab -l | grep 'le.sh cron' ; then
1117 if [ -f "$LE_WORKING_DIR/le.sh" ] ; then
1118 lesh="\"$LE_WORKING_DIR\"/le.sh"
1119 else
1120 _err "Can not install cronjob, le.sh not found."
1121 return 1
1122 fi
1123 crontab -l | { cat; echo "0 0 * * * LE_WORKING_DIR=\"$LE_WORKING_DIR\" $lesh cron > /dev/null"; } | crontab -
1124 fi
1125 if [ "$?" != "0" ] ; then
1126 _err "Install cron job failed. You need to manually renew your certs."
1127 _err "Or you can add cronjob by yourself:"
1128 _err "LE_WORKING_DIR=\"$LE_WORKING_DIR\" $lesh cron > /dev/null"
1129 return 1
1130 fi
1131}
1132
1133uninstallcronjob() {
1134 _info "Removing cron job"
1135 cr="$(crontab -l | grep 'le.sh cron')"
1136 if [ "$cr" ] ; then
1137 crontab -l | sed "/le.sh cron/d" | crontab -
1138 LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 6 | cut -d '=' -f 2 | tr -d '"')"
1139 _info LE_WORKING_DIR "$LE_WORKING_DIR"
1140 fi
1141 _initpath
1142
1143}
1144
1145
1146# Detect profile file if not specified as environment variable
1147_detect_profile() {
1148 if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
1149 echo "$PROFILE"
1150 return
1151 fi
1152
1153 local DETECTED_PROFILE
1154 DETECTED_PROFILE=''
1155 local SHELLTYPE
1156 SHELLTYPE="$(basename "/$SHELL")"
1157
1158 if [ "$SHELLTYPE" = "bash" ]; then
1159 if [ -f "$HOME/.bashrc" ]; then
1160 DETECTED_PROFILE="$HOME/.bashrc"
1161 elif [ -f "$HOME/.bash_profile" ]; then
1162 DETECTED_PROFILE="$HOME/.bash_profile"
1163 fi
1164 elif [ "$SHELLTYPE" = "zsh" ]; then
1165 DETECTED_PROFILE="$HOME/.zshrc"
1166 fi
1167
1168 if [ -z "$DETECTED_PROFILE" ]; then
1169 if [ -f "$HOME/.profile" ]; then
1170 DETECTED_PROFILE="$HOME/.profile"
1171 elif [ -f "$HOME/.bashrc" ]; then
1172 DETECTED_PROFILE="$HOME/.bashrc"
1173 elif [ -f "$HOME/.bash_profile" ]; then
1174 DETECTED_PROFILE="$HOME/.bash_profile"
1175 elif [ -f "$HOME/.zshrc" ]; then
1176 DETECTED_PROFILE="$HOME/.zshrc"
1177 fi
1178 fi
1179
1180 if [ ! -z "$DETECTED_PROFILE" ]; then
1181 echo "$DETECTED_PROFILE"
1182 fi
1183}
1184
1185_initconf() {
1186 _initpath
1187 if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then
1188 echo "#Account configurations:
1189#Here are the supported macros, uncomment them to make them take effect.
1190#ACCOUNT_EMAIL=aaa@aaa.com # the account email used to register account.
5fd3f21b 1191#ACCOUNT_KEY_PATH=\"/path/to/account.key\"
4c3b3608 1192
1193#STAGE=1 # Use the staging api
1194#FORCE=1 # Force to issue cert
1195#DEBUG=1 # Debug mode
1196
1197#dns api
1198#######################
1199#Cloudflare:
1200#api key
3d49985a 1201#CF_Key=\"sdfsdfsdfljlbjkljlkjsdfoiwje\"
4c3b3608 1202#account email
3d49985a 1203#CF_Email=\"xxxx@sss.com\"
4c3b3608 1204
1205#######################
1206#Dnspod.cn:
1207#api key id
3d49985a 1208#DP_Id=\"1234\"
4c3b3608 1209#api key
3d49985a 1210#DP_Key=\"sADDsdasdgdsf\"
4c3b3608 1211
1212#######################
1213#Cloudxns.com:
3d49985a 1214#CX_Key=\"1234\"
4c3b3608 1215#
3d49985a 1216#CX_Secret=\"sADDsdasdgdsf\"
4c3b3608 1217
1218 " > $ACCOUNT_CONF_PATH
1219 fi
1220}
1221
1222install() {
1223 if ! _initpath ; then
1224 _err "Install failed."
1225 return 1
1226 fi
1227
1228 #check if there is sudo installed, AND if the current user is a sudoer.
1229 if command -v sudo > /dev/null ; then
1230 if [ "$(sudo -n uptime 2>&1|grep "load"|wc -l)" != "0" ] ; then
1231 SUDO=sudo
1232 fi
1233 fi
1234
1235 if command -v yum > /dev/null ; then
1236 YUM="1"
1237 INSTALL="$SUDO yum install -y "
1238 elif command -v apt-get > /dev/null ; then
1239 INSTALL="$SUDO apt-get install -y "
1240 fi
1241
1242 if ! command -v "curl" > /dev/null ; then
1243 _err "Please install curl first."
1244 _err "$INSTALL curl"
1245 return 1
1246 fi
1247
1248 if ! command -v "crontab" > /dev/null ; then
1249 _err "Please install crontab first."
1250 if [ "$YUM" ] ; then
1251 _err "$INSTALL crontabs"
1252 else
1253 _err "$INSTALL crontab"
1254 fi
1255 return 1
1256 fi
1257
1258 if ! command -v "openssl" > /dev/null ; then
1259 _err "Please install openssl first."
1260 _err "$INSTALL openssl"
1261 return 1
1262 fi
1263
1264 _info "Installing to $LE_WORKING_DIR"
1265
1266 cp le.sh "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/le.sh"
1267
1268 if [ "$?" != "0" ] ; then
1269 _err "Install failed, can not copy le.sh"
1270 return 1
1271 fi
1272
1273 _info "Installed to $LE_WORKING_DIR/le.sh"
1274
1275 _profile="$(_detect_profile)"
1276 if [ "$_profile" ] ; then
1277 _debug "Found profile: $_profile"
1278
1279 echo "LE_WORKING_DIR=$LE_WORKING_DIR
1280alias le=\"$LE_WORKING_DIR/le.sh\"
1281alias le.sh=\"$LE_WORKING_DIR/le.sh\"
1282 " > "$LE_WORKING_DIR/le.env"
b86869a0 1283 echo "" >> "$_profile"
4c3b3608 1284 _setopt "$_profile" "source \"$LE_WORKING_DIR/le.env\""
1285 _info "OK, Close and reopen your terminal to start using le"
1286 else
1287 _info "No profile is found, you will need to go into $LE_WORKING_DIR to use le.sh"
1288 fi
1289
1290 mkdir -p $LE_WORKING_DIR/dnsapi
1291 cp dnsapi/* $LE_WORKING_DIR/dnsapi/
1292
1293 #to keep compatible mv the .acc file to .key file
1294 if [ -f "$LE_WORKING_DIR/account.acc" ] ; then
1295 mv "$LE_WORKING_DIR/account.acc" "$LE_WORKING_DIR/account.key"
1296 fi
1297
1298 installcronjob
1299
1300 if [ ! -f "$ACCOUNT_CONF_PATH" ] ; then
1301 _initconf
1302 fi
1303 _info OK
1304}
1305
1306uninstall() {
1307 uninstallcronjob
1308 _initpath
1309
1310 _profile="$(_detect_profile)"
1311 if [ "$_profile" ] ; then
7203a1c1 1312 text="$(cat $_profile)"
1313 echo "$text" | sed "s|^source.*le.env.*$||" > "$_profile"
4c3b3608 1314 fi
1315
1316 rm -f $LE_WORKING_DIR/le.sh
1317 _info "The keys and certs are in $LE_WORKING_DIR, you can remove them by yourself."
1318
1319}
1320
1321cron() {
1322 renewAll
1323}
1324
1325version() {
1326 _info "$PROJECT"
1327 _info "v$VER"
1328}
1329
1330showhelp() {
1331 version
1332 echo "Usage: le.sh [command] ...[args]....
1333Avalible commands:
1334
1335install:
1336 Install le.sh to your system.
1337issue:
1338 Issue a cert.
1339installcert:
1340 Install the issued cert to apache/nginx or any other server.
1341renew:
1342 Renew a cert.
1343renewAll:
1344 Renew all the certs.
1345uninstall:
1346 Uninstall le.sh, and uninstall the cron job.
1347version:
1348 Show version info.
1349installcronjob:
1350 Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
1351uninstallcronjob:
1352 Uninstall the cron job. The 'uninstall' command can do this automatically.
1353createAccountKey:
1354 Create an account private key, professional use.
1355createDomainKey:
1356 Create an domain private key, professional use.
1357createCSR:
1358 Create CSR , professional use.
1359 "
1360}
1361
1362
1363if [ -z "$1" ] ; then
1364 showhelp
1365else
1366 "$@"
1367fi