在新的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"
有多种方法可以做到这一点,他们可以根据情况被认为是“正确的”。
一种方式做到这一点在开机时可以使用AWS的情况下创建实例,你可以添加自定义的脚本时使用cloud-init,来进行测试:
这将使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"
为什么不使用Ansible? –
看起来不错,问题在哪里? – aggsol
除了在here-doc里面缺少'fi'外,看起来不错。也许和你的''$ 1'''dbl-quoting一致?要真正防患于未然,可能需要添加一些dbl-检查每个步骤的工作。你可以将所有'apt-get's和'&&'s(实际上所有的步骤)(是的,疯狂的)和/或检查日志文件确实发生,或者捕获Std-err并确保它是空的等等,或者你可以从事情的“完成的结局”来看它,并添加一个测试来证明你的“使用SSL的nginx实例”按需要工作。 (以上所有有效Q值)。祝你好运! – shellter