diff --git a/le b/le
index fc08e1e..26ff0c6 100755
--- a/le
+++ b/le
@@ -1,159 +1,5 @@
#!/usr/bin/env bash
-err() {
- printf '%s\n' "$*" >&2
-}
+subcommand=$1; shift
-msg() {
- printf '%s\n' "$*"
-}
-
-set_default() {
- declare -n _vref=$1
-
- if ! [[ "$_vref" ]]; then
- _vref=$2
- fi
-}
-
-gen_san_string() {
- declare d
- declare -a argv
-
- argv=( "$@" )
-
- printf '[SAN]\nsubjectAltName='
-
- for d in "${argv[@]}"; do
- printf 'DNS:%s' "$d"
- if ! [[ "$d" == "${argv[-1]}" ]]; then
- printf ','
- fi
- done
-}
-
-gen_renew_config() {
- declare d
-
- printf 'domains=(\n'
- for d in "$@"; do
- printf " %s\n" "$d"
- done
- printf ')\n'
-}
-
-usage() {
- while read -r line; do printf '%s\n' "$line"; done <<- EOF
- Usage: le [options] <-d domain> [-d domain] ...
- Options:
- -c
# Configuration directory. Default: \$HOME/.acme
- -a # A dir to put challenges in. Default: /tmp/acme/challenges
- -d # Domain to issue the certificate for.
- # Can be specified multiple time for multi-domain certs.
- -h # Show this message.
- EOF
-}
-
-main() {
- declare cfg_dir
- declare -a domains
-
- while (( $# )); do
- case $1 in
- -c)
- cfg_dir=$2
- shift;;
-
- -a)
- challenge_dir=$2
- shift;;
-
- -d)
- domains+=( "$2" )
- shift;;
-
- -h)
- usage
- return 0;;
-
- --)
- shift
- break;;
-
- *) break;;
- esac
-
- shift
- done
-
- if ! (( ${#domains[@]} )); then
- err "Use -d, luke"
- return 1
- fi
-
- set_default cfg_dir "$HOME/.acme"
- set_default challenge_dir '/tmp/acme/challenges'
-
- if ! [[ -d "$cfg_dir" ]]; then
- err "Config dir ($cfg_dir) not found, creating."
- if ! mkdir -m700 "$cfg_dir"; then
- err "Can't create config dir: $cfg_dir"
- return 1
- fi
- fi
-
- if ! [[ -f "$cfg_dir/account.key" ]]; then
- err "Account key not found, generating a new one."
- openssl genrsa 4096 > "$cfg_dir/account.key"
- fi
-
- if ! [[ -d "$cfg_dir/domains/${domains[0]}" ]]; then
- mkdir -p "$cfg_dir/domains/${domains[0]}"
- fi
-
- if ! [[ -f "$cfg_dir/domains/${domains[0]}/privkey.pem" ]]; then
- err "Generating a new key for ${domains[0]}."
- openssl genrsa 4096 > "$cfg_dir/domains/${domains[0]}/privkey.pem"
- fi
-
- if ! [[ -d "$challenge_dir" ]]; then
- err "Challenge dir does not exist: $challenge_dir"
- return 1
- fi
-
- err "Generating a certificate request for: ${domains[@]}."
- if (( ${#domains[@]} > 1 )); then
- openssl req -new -sha256 \
- -key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
- -subj "/" \
- -reqexts SAN \
- -config <(cat /etc/ssl/openssl.cnf <(gen_san_string "${domains[@]}")) > "$cfg_dir/domains/${domains[0]}/request.csr"
- else
- openssl req -new -sha256 \
- -key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
- -subj "/CN=${domains[0]}" > "$cfg_dir/domains/${domains[0]}/request.csr"
- fi
-
- err "Getting a signed certificate."
- acme-tiny \
- --account-key "$cfg_dir/account.key" \
- --csr "$cfg_dir/domains/${domains[0]}/request.csr" \
- --acme-dir "$challenge_dir" > "$cfg_dir/domains/${domains[0]}/certificate.pem"
-
- if (( $? )); then
- return 1
- fi
-
- gen_renew_config "${domains[@]}" > "$cfg_dir/domains/${domains[0]}/renew.cfg"
-
- if ! [[ -f "$cfg_dir/chain.pem" ]]; then
- err "Intermediate certificate not found, downloading."
- curl "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" > "$cfg_dir/letsencrypt.pem"
- fi
-
- cat "$cfg_dir/domains/${domains[0]}/certificate.pem" "$cfg_dir/letsencrypt.pem" > "$cfg_dir/domains/${domains[0]}/fullchain.pem"
-
- err "Your certificate is available at $cfg_dir/domains/${domains[0]}/fullchain.pem"
-}
-
-main "$@"
+source "sub/$subcommand" "$@"
diff --git a/sub/issue b/sub/issue
new file mode 100755
index 0000000..e1ff8e5
--- /dev/null
+++ b/sub/issue
@@ -0,0 +1,154 @@
+#!/usr/bin/env bash
+
+err() {
+ printf '%s\n' "$*" >&2
+}
+
+msg() {
+ printf '%s\n' "$*"
+}
+
+set_default() {
+ declare -n _vref=$1
+
+ if ! [[ "$_vref" ]]; then
+ _vref=$2
+ fi
+}
+
+gen_san_string() {
+ declare d
+ declare -a argv
+
+ argv=( "$@" )
+
+ printf '[SAN]\nsubjectAltName='
+
+ for d in "${argv[@]}"; do
+ printf 'DNS:%s' "$d"
+ if ! [[ "$d" == "${argv[-1]}" ]]; then
+ printf ','
+ fi
+ done
+}
+
+gen_renew_config() {
+ declare d
+
+ printf 'domains=(\n'
+ for d in "$@"; do
+ printf " %s\n" "$d"
+ done
+ printf ')\n'
+}
+
+usage() {
+ while read -r line; do printf '%s\n' "$line"; done <<- EOF
+ Usage: le [options] [domain ...]
+ Options:
+ -c # Configuration directory. Default: \$HOME/.acme
+ -a # A dir to put challenges in. Default: /var/www/acme
+ -h # Show this message.
+ EOF
+}
+
+main() {
+ declare cfg_dir
+ declare -a domains
+
+ while (( $# )); do
+ case $1 in
+ -c)
+ cfg_dir=$2
+ shift;;
+
+ -a)
+ challenge_dir=$2
+ shift;;
+
+ -h)
+ usage
+ return 0;;
+
+ --)
+ shift
+ break;;
+
+ *) break;;
+ esac
+
+ shift
+ done
+
+ domains=( "$@" )
+
+ (( ${#domains[@]} )) || {
+ usage; return 1
+ }
+
+ set_default cfg_dir "$HOME/.acme"
+ set_default challenge_dir '/var/www/acme'
+
+ if ! [[ -d "$cfg_dir" ]]; then
+ err "Config dir ($cfg_dir) not found, creating."
+ if ! mkdir -m700 "$cfg_dir"; then
+ err "Can't create config dir: $cfg_dir"
+ return 1
+ fi
+ fi
+
+ if ! [[ -f "$cfg_dir/account.key" ]]; then
+ err "Account key not found, generating a new one."
+ openssl genrsa 4096 > "$cfg_dir/account.key"
+ fi
+
+ if ! [[ -d "$cfg_dir/domains/${domains[0]}" ]]; then
+ mkdir -p "$cfg_dir/domains/${domains[0]}"
+ fi
+
+ if ! [[ -f "$cfg_dir/domains/${domains[0]}/privkey.pem" ]]; then
+ err "Generating a new key for ${domains[0]}."
+ openssl genrsa 4096 > "$cfg_dir/domains/${domains[0]}/privkey.pem"
+ fi
+
+ if ! [[ -d "$challenge_dir" ]]; then
+ err "Challenge dir does not exist: $challenge_dir"
+ return 1
+ fi
+
+ err "Generating a certificate request for: ${domains[@]}."
+ if (( ${#domains[@]} > 1 )); then
+ openssl req -new -sha256 \
+ -key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
+ -subj "/" \
+ -reqexts SAN \
+ -config <(cat /etc/ssl/openssl.cnf <(gen_san_string "${domains[@]}")) > "$cfg_dir/domains/${domains[0]}/request.csr"
+ else
+ openssl req -new -sha256 \
+ -key "$cfg_dir/domains/${domains[0]}/privkey.pem" \
+ -subj "/CN=${domains[0]}" > "$cfg_dir/domains/${domains[0]}/request.csr"
+ fi
+
+ err "Getting a signed certificate."
+ acme-tiny \
+ --account-key "$cfg_dir/account.key" \
+ --csr "$cfg_dir/domains/${domains[0]}/request.csr" \
+ --acme-dir "$challenge_dir" > "$cfg_dir/domains/${domains[0]}/certificate.pem"
+
+ if (( $? )); then
+ return 1
+ fi
+
+ gen_renew_config "${domains[@]}" > "$cfg_dir/domains/${domains[0]}/renew.cfg"
+
+ if ! [[ -f "$cfg_dir/chain.pem" ]]; then
+ err "Intermediate certificate not found, downloading."
+ curl "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" > "$cfg_dir/letsencrypt.pem"
+ fi
+
+ cat "$cfg_dir/domains/${domains[0]}/certificate.pem" "$cfg_dir/letsencrypt.pem" > "$cfg_dir/domains/${domains[0]}/fullchain.pem"
+
+ err "Your certificate is available at $cfg_dir/domains/${domains[0]}/fullchain.pem"
+}
+
+main "$@"
diff --git a/le-renew b/sub/renew
similarity index 100%
rename from le-renew
rename to sub/renew