12

到目前为止我有这个,但我错过了一些事情,比如让 cron 作业编写脚本。不想以 root 身份执行此操作。所以我假设可以做更多的工作来同时设置第一个用户。该脚本需要是幂等的(如果之前使用相同的参数运行,则可以一遍又一遍地运行而不会冒险更改任何内容)。

singledomaincertnginx.sh:

#!/bin/bash
if [ -z "$3" ]; then
        echo use is "singledomaincertnginx.sh <server-ssh-address> <ssl-admin-email> <ssl-domain>"
        echo example: "singledomaincertnginx.sh user@mydomain.com admin@mydomain.com some-sub-domain.mydomain.com"
        exit
fi
ssh $1 "cat > ~/wks" << 'EOF'
#!/bin/bash
echo email: $1
echo domain: $2
sudo add-apt-repository -y ppa:certbot/certbot
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y software-properties-common
sudo apt-get install -y python-certbot-nginx
sudo apt-get install -y nginx
sudo sed -i "s/server_name .*;/server_name $2;/" /etc/nginx/sites-available/default
sudo systemctl restart nginx.service
if [[ -e /etc/letsencrypt/live/$2/fullchain.pem ]]; then
  sudo certbot -n --nginx --agree-tos -m "$1" -d "$2"
fi
if [[ ! sudo crontab -l | grep certbot ]]; then
  # todo: add cron job to renew: 15 3 * * * /usr/bin/certbot renew --quiet
EOF
ssh $1 "chmod +x ~/wks"
ssh -t $1 "bash -x -e ~/wks $2 $3"
4

5 回答 5

4

到目前为止我有这个,但我错过了一些事情,比如让 cron 作业编写脚本。

这是完成(和更正)您开始的内容的一种方法:

if ! sudo crontab -l | grep certbot; then
    echo "15 3 * * * /usr/bin/certbot renew --quiet" | sudo tee -a  /var/spool/cron/crontabs/root >/dev/null
fi

这是我更喜欢的另一种方式,因为它不需要知道 crontabs 的路径:

if ! sudo crontab -l | grep certbot; then
    sudo crontab -l | { cat; echo "15 3 * * * /usr/bin/certbot renew --quiet"; } | sudo crontab -
fi

我看到缺少的是证书文件/etc/letsencrypt/live/$domain/fullchain.pem的创建方式。你是通过其他方式提供的,还是需要这部分的帮助?

不想以 root 身份执行此操作。

大多数步骤都涉及运行apt-get,为此您已经需要 root。也许您的意思是您不想使用 root 进行续订。一些服务以专用用户而不是 root 身份运行,但查看certbot 的文档我没有看到类似的东西。因此,使用 root 进行更新似乎是一种常见的做法,因此将更新命令添加到 root 的 crontab 对我来说似乎很好。

我会改进脚本中的一些内容以使其更加健壮:

  • 散落在各处的位置参数等容易丢失$1$2从而导致错误。我会给他们正确的名字。

  • 命令行参数验证if [ -z "$3" ]很弱,我会使其更加严格,因为if [ $# != 3 ].

  • 远程脚本生成后,用 调用,有bash -e利于维护。但是,如果脚本被其他没有 的东西调用-e,则安全措施将不存在。最好在脚本本身中使用set -e. 我会走得更远,使用set -euo pipefail更严格的。我也会把它放在外部脚本中。

  • 远程脚本中的大多数命令都需要sudo. 一方面写起来很乏味。另一方面,如果一个命令最终花费了很长时间以致sudo会话过期,您可能不得不再次重新输入 root 密码,这会很烦人,尤其是当您出去喝咖啡时。通过添加对执行用户的 uid 的检查,要求始终以 root 身份运行会更好。

  • 由于您使用bash -x ~/wks ...而不是仅运行远程脚本~/wks,因此无需使用 使其可执行chmod,因此可以删除该步骤。

把上面的东西放在一起(然后是一些),我会这样写:

#!/bin/bash

set -euo pipefail

if [ $# != 3 ]; then
    echo "Usage: $0 <server-ssh-address> <ssl-admin-email> <ssl-domain>"
    echo "Example: singledomaincertnginx.sh user@mydomain.com admin@mydomain.com some-sub-domain.mydomain.com"
    exit 1
fi

remote=$1
email=$2
domain=$3

remote_script_path=./wks

ssh $remote "cat > $remote_script_path" << 'EOF'
#!/bin/bash

set -euo pipefail

if [[ "$(id -u)" != 0 ]]; then
    echo "This script must be run as root. (sudo $0)"
    exit 1
fi

email=$1
domain=$2

echo email: $email
echo domain: $domain

add-apt-repository -y ppa:certbot/certbot
apt-get update
apt-get upgrade -y
apt-get install -y software-properties-common
apt-get install -y python-certbot-nginx
apt-get install -y nginx
sed -i "s/server_name .*;/server_name $domain;/" /etc/nginx/sites-available/default
systemctl restart nginx.service
#service nginx restart

if [[ -e /etc/letsencrypt/live/$domain/fullchain.pem ]]; then
    certbot -n --nginx --agree-tos -m $email -d $domain
fi

if ! crontab -l | grep -q certbot; then
    crontab -l | {
        cat
        echo
        echo "15 3 * * * /usr/bin/certbot renew --quiet"
        echo
    } | crontab -
fi
EOF

ssh -t $remote "sudo bash -x $remote_script_path $email $domain"
于 2017-10-28T14:52:45.080 回答
2

如果您使用 sudo 执行此操作,则您是以 root 身份执行此操作

这是在ansible中做的一件简单的事情,最好在那里做

要完成 cron 工作,请执行以下操作:

CRON_FILE="/etc/cron.d/certbot"

如果 [ !-f $CRON_FILE ] ; 然后

echo '15 3 * * * /usr/bin/certbot renew --quiet' > $CRON_FILE

于 2017-10-28T10:00:32.920 回答
2

您是否正在寻找这样的东西:

if [[ "$(grep '/usr/bin/certbot' /var/spool/cron/crontabs/$(whoami))" = "" ]]
then
    echo "15 3 * * * /usr/bin/certbot renew --quiet" >> /var/spool/cron/crontabs/$(whoami)
fi

和最后的fi

您还可以通过连接它们来避免做那么多 sudo ,如下所示:

sudo bash -c 'add-apt-repository -y ppa:certbot/certbot;apt-get update;apt-get upgrade -y;apt-get install -y software-properties-common python-certbot-nginx nginx;sed -i "s/server_name .*;/server_name $2;/" /etc/nginx/sites-available/default;systemctl restart nginx.service'
于 2017-10-26T01:22:02.957 回答
1

有多种方法可以做到这一点,根据场景,它们可以被认为是“适当的”。

在启动时执行此操作的一种方法是使用cloud-init,为了在创建实例时使用 AWS 进行测试,您可以添加自定义脚本:

在此处输入图像描述

这将允许在您的实例启动时运行命令,如果您想自动化此过程(如代码的基础设施),您可以使用例如terraform

如果由于某种原因您已经启动并运行了实例并且只想按需更新但不使用 ssh,则可以使用saltstack

从ansible 词汇表中谈论“幂等性”Ansible 也可能是一个非常好的工具:

一个操作是幂等的,如果执行一次的结果与重复执行的结果完全相同,没有任何干预动作。

有很多工具可以帮助您实现这一目标,唯一的事情就是找到更适合您的需求/场景的工具。

于 2017-10-25T11:45:16.963 回答
1

nginx + Ubuntu的复制粘贴解决方案

安装依赖项

sudo apt-get install nginx -y
sudo apt-get install software-properties-common -y
sudo add-apt-repository universe -y
sudo add-apt-repository ppa:certbot/certbot -y
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx -y

获取 SSL 证书并将所有流量从 http 重定向到 https

certbot --nginx --agree-tos --redirect --noninteractive \
        --email YOUR@EMAIL.COM \
        --domain YOUR.DOMAIN.COM

测试更新

certbot renew --dry-run

文档

https://certbot.eff.org/lets-encrypt/ubuntuxenial-nginx

于 2019-03-20T14:39:54.997 回答