【问题标题】:What is the proper way to script a new nginx instance with SSL on a new Ubuntu 16.04 server?在新的 Ubuntu 16.04 服务器上使用 SSL 编写新 nginx 实例的正确方法是什么?
【发布时间】:2018-03-29 23:40:27
【问题描述】:

到目前为止,我有这个,但我错过了一些事情,比如让 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"

【问题讨论】:

  • 为什么不使用 Ansible?
  • 看起来不错,问题出在哪里?
  • 除了 here-doc 中缺少 fi 之外,看起来不错。也许与您对 "$1" 的 dbl 引用一致?为了真正防弹,也许添加一些 dbl 检查每个步骤是否有效。您可以将所有apt-gets 与&amp;&amp;s 链接在一起(实际上是所有步骤)(是的,疯狂)和/或检查日志文件是否确实发生了事情,或者捕获 Std-err 并确保它是空的等。或者您可以从事物的“完成端”查看它并添加一个测试来证明您的“带有 SSL 的 nginx 实例”正在按要求工作。 (以上所有有效问题)。祝你好运!
  • 您的 Q 不“只是”如何添加自动 cron 条目是吗?更多的是不以root身份运行,对吗?只要系统的 cron 允许通过 crontab &lt;myCrontab 进行非 root 访问(管理员可以通过多种安全功能阻止),看起来你就可以开始了。推翻在您的服务器上设置的任何故意的 crontab 安全功能将需要至少一次 root 访问或其他管理员干预(至少在我工作过的行业中)。 :-) 。祝你好运。

标签: bash ssl nginx ssh certbot


【解决方案1】:

到目前为止我已经有了这个,但我错过了一些事情,比如让 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。 也许您的意思是您不想使用 root 进行续订。 某些服务以专用用户而不是 root 用户身份运行, 但是通过documentation of 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"

【讨论】:

    【解决方案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'
    

    【讨论】:

      【解决方案3】:

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

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

      要执行 cron 任务,请执行以下操作:

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

      如果 [ ! -f $CRON_FILE ] ;那么

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

      fi

      【讨论】:

        【解决方案4】:

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

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

        这将允许running commands on launch of your instance,如果您想自动化此过程(基础设施如代码),您可以使用例如terraform

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

        谈论“幂等性”Ansible 也可能是一个非常好的工具,来自ansible glossary

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

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

        【讨论】:

          【解决方案5】:

          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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-08-12
            • 2017-10-25
            • 1970-01-01
            • 2020-10-16
            • 1970-01-01
            相关资源
            最近更新 更多