Compare commits

..

2 Commits

Author SHA1 Message Date
2598532761 Add it for real 2020-08-01 20:44:52 -04:00
c7eb44ae5f Combine scripts 2020-08-01 20:44:22 -04:00
3 changed files with 63 additions and 146 deletions

View File

@@ -1,16 +1,12 @@
# WIP # WIP
This project contains two files: `acme-cpanel.sh` reads in a list of domains from one or more files. These files may only contain domains and empty lines (see `domains.txt` for example format).
`acme-cpanel-webroot.sh` (for webroot challenges) "*www.*" subdomains will be added automatically (do not add them to the domains file list).
`acme-cpanel-dns.sh` (for dns challenges, legacy script)
Both of these scripts read in a list of domains from one or more files. These files may only contain domains and empty lines (see `domains.txt`).
## Notes ## Notes
`acme-cpanel-webroot.sh` may require the following additions to .htaccess so that challenges are not automatically redirected to https: The `--method webroot` may require the following additions to .htaccess so that challenges are not automatically redirected to https:
```text ```text
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
@@ -23,32 +19,33 @@ Command-line (Linux):
* Move script to user home directory on the server: `scp ./* username@ip:port:~` * Move script to user home directory on the server: `scp ./* username@ip:port:~`
* Login to server: `ssh user@ip -p port` * Login to server: `ssh user@ip -p port`
* Make script executable: `chmod +x $HOME/acme-cpanel-webroot.s` * Make script executable: `chmod +x $HOME/acme-cpanel.sh`
* Run script (ex. `$HOME/acme-cpanel-webroot.sh -s multisites`) * Run script (ex. `$HOME/acme-cpanel.sh -s multisites`)
* Follow prompts to enter credentials, issue certificates, and deploy them * Follow prompts to enter credentials, issue certificates, and deploy them
* Double-check that the acme cron job is enabled: `crontab -l` * Double-check that the acme cron job is enabled: `crontab -l`
cPanel: cPanel:
* Use File Manager to upload files to the home directory (/home/username/) * Use File Manager to upload files to the home directory (/home/username/)
* You may need to make file executable in Terminal: `chmod +x $HOME/acme-cpanel-webroot.sh` * You may need to make file executable in Terminal: `chmod +x $HOME/acme-cpanel.sh`
* Use Terminal to run the script (ex. `$HOME/acme-cpanel-webroot.sh -s multisites`) * Use Terminal to run the script (ex. `$HOME/acme-cpanel.sh -s multisites`)
* Follow prompts to enter credentials, issue certificates, and deploy them * Follow prompts to enter credentials, issue certificates, and deploy them
* Use Cron Jobs app to double-check that the acme cron job is present * Use Cron Jobs app to double-check that the acme cron job is present
## Usage ## Usage
### `./acme-cpanel-webroot.sh [OPTIONS] [FILES...]` ### `./acme-cpanel.sh [OPTIONS] [FILES...]`
#### Options #### Options
```text ```text
--method, -m webroot,dns
Choose the authentication method (default: dns)
--email, -e EMAIL --email, -e EMAIL
E-mail not be notified of certificate renewal failures E-mail not be notified of certificate renewal failures
--keep-grouping, -k --group-by-file, -g
Issue multidomain certificates based on grouping by input file Issue multidomain certificates for all domains with the same webroot, grouped by input file
The first domain in each file will be used to determine the shared webroot The first domain in each file will be used to determine the shared webroot
Default: issue certificates by independent domain
--sites-dir, -s DIR --sites-dir, -s DIR
Load domain list files from this directory Load domain list files from this directory
--force, -f --force, -f
@@ -59,18 +56,14 @@ cPanel:
#### Examples #### Examples
`./acme-cpanel-webroot.sh --force` `./acme-cpanel.sh --force`
Load sites from domains.txt, issue and deploy certificates Load sites from domains.txt, issue and deploy certificates using the webroot method
`./acme-cpanel-webroot.sh --force -s multisites` `./acme-cpanel.sh --method dns --force -s multisites`
Load sites from multisites directory, issue and deploy certificates Load sites from multisites directory, issue and deploy certificates using the dns method
`./acme-cpanel-webroot.sh --force -k multisites/flatwhitedesign.pw multisites/greengingerdesign.pw` `./acme-cpanel.sh --force -g multisites/flatwhitedesign.pw multisites/greengingerdesign.pw`
Load sites from multisites directory, issue and deploy multidomain certificates based on the grouping in the file. Load sites from multisites directory, issue and deploy multidomain certificates with same webroot based on the grouping in the file using the webroot method
### `./acme_cpanel_dns.sh`
This is a legacy script that takes no arguments. By default it will read all domain lists in a top-level "multisites" directory.

View File

@@ -1,87 +0,0 @@
#!/usr/bin/env bash
# This program will install and configure acme, request SSL certificates from Let's Encrypt, and enable them using the cPanel API
# Comment the following line to skip issuing a test certificate
test="true"
unset err
get_acme() {
curl https://get.acme.sh | sh
curl -o "$HOME/.acme.sh/dnsapi/dns_cpaneldns.sh" https://raw.githubusercontent.com/cryobry/dns_cpaneldns/master/dns_cpaneldns.sh
"$HOME/.acme.sh/acme.sh" --upgrade --auto-upgrade
}
run_config() {
if [[ -f "$HOME/.acme.sh/account.conf" ]]; then
if grep -q "CPANELDNS_AUTH_PASSWORD" "$HOME/.acme.sh/account.conf"; then
echo "cPanel credentials already present, skipping configuration..."
echo "To rerun the configuration, first run 'rm \$HOME/.acme.sh/account.conf'"
return 0
else
# Set contact e-mail for ACME failure
read -rp 'Enter the e-mail address to contact in case of acme failure: ' EMAIL
echo
"$HOME/.acme.sh/acme.sh" --update-account --accountemail "$EMAIL"
# Read in Namecheap API variables from user for acme
read -rp 'Enter your cPanel username: ' CPANELDNS_AUTH_ID
echo
export CPANELDNS_AUTH_ID
read -rp 'Enter your cPanel password: ' CPANELDNS_AUTH_PASSWORD
echo
export CPANELDNS_AUTH_PASSWORD
read -rp 'Enter your cPanel address and port number (example: "https://www.example.com:2083/"): ' CPANELDNS_API
echo
export CPANELDNS_API
fi
else
touch "$HOME/.acme.sh/account.conf"
run_config
fi
}
# Issue certificates
issue_cert() {
local multisite_file
for multisite_file in ./multisites/*; do
echo "Attempting to issue certificates for ${multisite_file##*/} and its multisites..."
unset sites issue_cmd deploy_cmd
declare -al sites issue_cmd deploy_cmd
readarray -t sites < "${multisite_file}"
issue_cmd=("$HOME/.acme.sh/acme.sh" "--issue" "--dns" "dns_cpaneldns")
deploy_cmd=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi")
for site in "${sites[@]}"; do
[[ "$site" != "" ]] && issue_cmd+=("-d" "$site")
done
# if test enabled, issue test certificate first
if [[ "${test:-x}" == "true" ]]; then
"${issue_cmd[@]}" --staging
read -rp -n 1 "Was the certificate correctly issued without errors? [y/N]: "
echo
[[ ! "$REPLY" =~ ^[Yy]$ ]] && err=1 && return 1
fi
echo "Running:" "${issue_cmd[@]}"
if "${issue_cmd[@]}" --force; then
echo "Running:" "${deploy_cmd[@]}"
! "${deploy_cmd[@]}" && \
echo "Could not deploy" && \
err=1
else
echo "Could not issue"
err=1
fi
done
}
main() {
get_acme
run_config
issue_cert
}
main "$@"
exit "${err:-0}"

View File

@@ -1,11 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# This script uses acme.sh to issue and deploy SSL certificates from Let's Encrypt for a list of domains using the webroot method # This script uses acme.sh to issue and deploy SSL certificates from Let's Encrypt for a list of domains
# See README for more details # using the webroot or dns methods
#
# See README.md for more details
# #
# Copyright 2020 Bryan Roessler <bryanroessler@gmail.com> # Copyright 2020 Bryan Roessler <bryanroessler@gmail.com>
# #
# USAGE # USAGE
# ./acme-cpanel-webroot.sh [OPTIONS] [FILES...] # ./acme-cpanel.sh [OPTIONS] [FILES...]
# #
# EXAMPLES # EXAMPLES
# TESTING: ./acme-cpanel-webroot.sh --debug -e me@gmail.com multisites/flatwhitedesign.pw multisites/greengingermultisite.website # TESTING: ./acme-cpanel-webroot.sh --debug -e me@gmail.com multisites/flatwhitedesign.pw multisites/greengingermultisite.website
@@ -20,9 +22,12 @@
# NOTE: The webroot method does NOT support wildcard domains, Let's Encrypt requires wildcard domains to # NOTE: The webroot method does NOT support wildcard domains, Let's Encrypt requires wildcard domains to
# use DNS challenges, which the CPANEL uapi does not support (use dns_cpaneldns plugin instead) # use DNS challenges, which the CPANEL uapi does not support (use dns_cpaneldns plugin instead)
source functions.sh
unset SITES_DIR USEREMAIL DOMAIN_FILES DOMAIN_GROUPS DEPLOY_CMD_PREFIX ISSUE_CMD_PREFIX DEBUG GROUP unset SITES_DIR USEREMAIL DOMAIN_FILES DOMAIN_GROUPS DEPLOY_CMD_PREFIX ISSUE_CMD_PREFIX DEBUG GROUP
DEBUG="true" # quote this line to stop DEBUG mode and issue certificates for real, or use --force in user options DEBUG="true" # quote this line to stop DEBUG mode and issue certificates for real, or use --force in user options
METHOD="dns" # set the default method
parse_input() { parse_input() {
@@ -30,10 +35,14 @@ parse_input() {
declare -g USEREMAIL declare -g USEREMAIL
declare -ag DOMAIN_FILES declare -ag DOMAIN_FILES
if input=$(getopt -o +e:fks:d -l email:,force,keep-grouping,sites-dir:,debug -- "$@"); then if input=$(getopt -o +m:e:fgs:d -l method:,email:,force,group-by-file,sites-dir:,debug -- "$@"); then
eval set -- "$input" eval set -- "$input"
while true; do while true; do
case "$1" in case "$1" in
--method|-m)
shift
METHOD="${1,,}"
;;
--email|-e) --email|-e)
shift shift
USEREMAIL="$1" USEREMAIL="$1"
@@ -41,7 +50,7 @@ parse_input() {
--force|-f) --force|-f)
unset DEBUG unset DEBUG
;; ;;
--keep-grouping|-k) --group-by-file|-g)
GROUP="true" GROUP="true"
;; ;;
--sites-dir|-s) --sites-dir|-s)
@@ -91,10 +100,27 @@ update_email() { [[ -v USEREMAIL ]] && "$HOME/.acme.sh/acme.sh" --update-account
command_prefixes() { command_prefixes() {
declare -ag ISSUE_CMD_PREFIX DEPLOY_CMD_PREFIX declare -ag ISSUE_CMD_PREFIX DEPLOY_CMD_PREFIX
ISSUE_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--issue" "--force") ISSUE_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--issue")
[[ -v DEBUG ]] && ISSUE_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--issue" "--staging") [[ "$METHOD" == "dns" ]] && ISSUE_CMD_PREFIX=("${ISSUE_CMD_PREFIX[@]}" "--dns" "dns_cpaneldns")
[[ -v DEBUG ]] && ISSUE_CMD_PREFIX=("${ISSUE_CMD_PREFIX[@]}" "--staging") || ISSUE_CMD_PREFIX=("${ISSUE_CMD_PREFIX[@]}" "--force")
DEPLOY_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi") DEPLOY_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi")
[[ -v DEBUG ]] && DEPLOY_CMD_PREFIX=("$HOME/.acme.sh/acme.sh" "--deploy" "--deploy-hook" "cpanel_uapi") }
get_webroot() {
local webroot
if ! webroot=$(uapi DomainInfo single_domain_data domain="$1" | grep documentroot); then
echo "UAPI call failed" >&2
fi
if [[ ! -v webroot || "$webroot" == "" ]]; then
if [[ -v DEBUG ]]; then
webroot="/tmp" # set missing webroot in DEBUG mode for testing
else
echo "Could not find $1's webroot" >&2
exit 1
fi
fi
echo "$webroot"
} }
@@ -117,23 +143,6 @@ load_domains() {
} }
get_webroot() {
local webroot
if ! webroot=$(uapi DomainInfo single_domain_data domain="$1" | grep documentroot); then
echo "UAPI call failed" >&2
fi
if [[ ! -v webroot || "$webroot" == "" ]]; then
if [[ -v DEBUG ]]; then
webroot="/tmp" # set missing webroot in DEBUG mode for testing
else
echo "Could not find $1's webroot" >&2
exit 1
fi
fi
echo "$webroot"
}
issue_and_deploy_certs() { issue_and_deploy_certs() {
local domain_root domain domain_group local domain_root domain domain_group
@@ -156,7 +165,8 @@ issue_and_deploy_certs() {
# Issue certificate for entire domain group # Issue certificate for entire domain group
echo "Running:" "${issue_cmd[@]}" echo "Running:" "${issue_cmd[@]}"
"${issue_cmd[@]}" if ! "${issue_cmd[@]}"; then
echo "Failed to issue certificate"
# Deploy certificates one by one # Deploy certificates one by one
for domain in $domain_group; do for domain in $domain_group; do
deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain") deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain")
@@ -168,18 +178,19 @@ issue_and_deploy_certs() {
for domain_group in "${DOMAIN_GROUPS[@]}"; do for domain_group in "${DOMAIN_GROUPS[@]}"; do
# Issue and deploy certificates one by one # Issue and deploy certificates one by one
for domain in $domain_group; do # we want to split on whitespace for domain in $domain_group; do # we want to split on whitespace
domain_root=$(get_webroot "$domain") issue_cmd=("${ISSUE_CMD_PREFIX[@]}" "-d" "$domain" "-d" "www.$domain")
issue_cmd=("${ISSUE_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain" "-d" "www.$domain") [[ "$METHOD" == "webroot" ]] && domain_root=$(get_webroot "$domain") && issue_cmd=("${issue_cmd[@]}" "-w" "$domain_root")
deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-w" "$domain_root" "-d" "$domain") # I think we only need to deploy to the domain, not subdomains deploy_cmd=("${DEPLOY_CMD_PREFIX[@]}" "-d" "$domain") # I think we only need to deploy to the domain, not subdomains
[[ "$METHOD" == "webroot" ]] && deploy_cmd=("${deploy_cmd[@]}" "-w" "$domain_root")
echo "Running:" "${issue_cmd[@]}" echo "Running:" "${issue_cmd[@]}"
if ! "${issue_cmd[@]}"; then if ! "${issue_cmd[@]}"; then
echo "Certificate issue failed for $domain" echo "Failed to issue certificate for $domain"
exit_err=1 err=1
fi fi
echo "Running:" "${deploy_cmd[@]}" echo "Running:" "${deploy_cmd[@]}"
if ! "${deploy_cmd[@]}"; then if ! "${deploy_cmd[@]}"; then
echo "Certificate deployment failed for $domain" echo "Failed to deploy certificate for $domain"
exit_err=1 err=1
fi fi
done done
done done
@@ -198,4 +209,4 @@ main() {
main "$@" main "$@"
exit "${exit_err:-0}" exit "${err:-0}"