在新的Ubuntu 16.04服务器上用SSL编写新的nginx实例的正确方法是什么?

在新的Ubuntu 16.04服务器上用SSL编写新的nginx实例的正确方法是什么?

问题描述:

我有这个到目前为止,但我错过了几个像获取cron作业脚本的东西。不想以root身份执行此操作。所以我假设可以做更多的事情来同时设置第一个用户。该脚本需要是幂等的(如果以前使用相同的参数运行,可以反复运行而不会冒险改变任何内容)。在新的Ubuntu 16.04服务器上用SSL编写新的nginx实例的正确方法是什么?

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 [email protected] [email protected] 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" 
+3

为什么不使用Ansible? –

+1

看起来不错,问题在哪里? – aggsol

+0

除了在here-doc里面缺少'fi'外,看起来不错。也许和你的''$ 1'''dbl-quoting一致?要真正防患于未然,可能需要添加一些dbl-检查每个步骤的工作。你可以将所有'apt-get's和'&&'s(实际上所有的步骤)(是的,疯狂的)和/或检查日志文件确实发生,或者捕获Std-err并确保它是空的等等,或者你可以从事情的“完成的结局”来看它,并添加一个测试来证明你的“使用SSL的nginx实例”按需要工作。 (以上所有有效Q值)。祝你好运! – shellter

有多种方法可以做到这一点,他们可以根据情况被认为是“正确的”。

一种方式做到这一点在开机时可以使用AWS的情况下创建实例,你可以添加自定义的脚本时使用cloud-init,来进行测试:

enter image description here

这将使running commands on launch of your instance,如果你想这个过程自动化(基础设施比如代码),如果由于某种原因你已经有实例和运行,只是要按需更新,但不使用SSH,你可以使用例如terraform

,你腠ld使用saltstack

谈到“幂等” Ansible可能也这样做的一个很好的工具,从ansible glossary

的操作是幂等,如果一旦执行它的结果是完全一样的结果无需任何干预行动即可重复执行。

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

您正在寻找这样的事情:在结束

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 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' 

如果你用sudo做这个,你以root身份做这个

这是imple事情在ansible做,做到最好有

做cron作业做这样的:

CRON_FILE = “/等/ cron.d/certbot”

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

呼应'15 3 * * *的/ usr/bin中/ certbot更新--quiet”> $ CRON_FILE

网络

我有这到目前为止,但我错过了几个像获得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 

这里的另一种方式,我喜欢,因为它并不需要知道的crontab的路径:

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来进行更新。 某些服务以专用用户身份运行,而不是根用户, ,但通过documentation of certbot查看,我还没有看到类似的东西。 因此,似乎通常的做法是使用root进行续订, 因此将更新命令添加到root的crontab对我来说似乎很好。

我会提高几件事情在脚本,使其更加强劲:

  • 的位置参数$1$2等散落很容易丢失的轨道,这可能导致错误。我会给他们适当的名字。

  • 命令行参数验证if [ -z "$3" ]很弱,我会让它更加严格,如if [ $# != 3 ]

  • 一旦生成了远程脚本,就可以用bash -e来调用它,这对维护起到了很好的作用。但是如果脚本被其他没有-e的东西调用,那么保护就不会在那里。与set -e一起构建脚本本身会更好。我会走得更远,并使用更严格的set -euo pipefail。我也会把它放在外部脚本中。

  • 远程脚本中的大多数命令都需要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 [email protected] [email protected] 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"