Каким образом можно использовать script новый экземпляр nginx с SSL на новом сервере Ubuntu 16.04?

У меня есть это до сих пор, но я пропускаю пару вещей, таких как получение задания на работу cron. Не хотите делать это как root. Поэтому я предполагаю, что можно было бы еще сделать, чтобы настроить первого пользователя одновременно. script должен быть идемпотентным (может быть запущен снова и снова, не рискуя что-либо изменить, если он был запущен с теми же аргументами раньше).

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"

Ответ 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

Здесь другой способ, который я предпочитаю, потому что ему не нужно знать путь 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, поэтому добавление команды обновления корневому crontab кажется мне прекрасным.

Я бы улучшил пару вещей в script, чтобы сделать его более надежным:

  • Позиционные параметры $1, $2 и т.д., рассеянные вокруг, легко потерять, что может привести к ошибкам. Я бы назвал их именами.

  • Проверка аргумента командной строки if [ -z "$3" ] слаба, я бы сделал более строгим, чем if [ $# != 3 ].

  • Как только удаленный script сгенерирован, вы вызываете его с помощью bash -e, что полезно для защиты. Но если script вызывается чем-то другим без -e, то защита там не будет. Было бы лучше создать эту гарантию в самой script с помощью set -e. Я бы пошел дальше и использовал set -euo pipefail, который еще более строгий. И я бы добавил это во внешний script.

  • Для большинства команд в удаленном script требуется sudo. С одной стороны утомительно писать. Для другого, если одна команда закончила длительное время, так что сеанс sudo истечет, вам, возможно, придется повторно ввести пароль root, что будет раздражать, особенно если вы вышли на кофе-брейк. Было бы лучше потребовать, чтобы всегда выполнялся как root, добавив проверку на uid исполняемого пользователя.

  • Поскольку вы запускаете удаленный script с 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"

Ответ 2

Существует несколько способов сделать это, и их можно считать "правильными" в зависимости от сценария.

Один из способов сделать это во время загрузки можно использовать cloud-init, для тестирования в случае использования AWS при создании экземпляра вы можете добавить свой собственный script:

введите описание изображения здесь

Это позволит запускать команды при запуске вашего экземпляра. Если вы хотите автоматизировать этот процесс (инфраструктуру, такую ​​как код), вы можете используйте terraform

Если по какой-то причине у вас уже есть экземпляр с запуском и просто хотите обновить его по требованию, но не используя ssh, вы можете использовать saltstack.

Говоря об "Idempotency", Ansible может быть также очень хорошим инструментом для этого, из доступного глоссария:

Операция является идемпотентной, если результат ее выполнения один раз совпадает с результатом ее повторения без каких-либо промежуточных действий.

Есть много инструментов, которые могут помочь вам в этом, только нужно найти инструмент, который лучше адаптируется к вашим потребностям/сценарию.

Ответ 3

Вы ищете что-то вроде этого:

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'

Ответ 4

Если вы делаете это с помощью sudo, вы делаете это как root

это простая вещь, которую можно сделать в недоступном, лучше всего там

выполнить задание cron:

CRON_FILE = "/и т.д. /cron.d/certbot"

если [! -f $CRON_FILE]; затем

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

ц