Let's Encrypt с несколькими доменами не работал для ECC-сертификатов

Как мне инициировать обновление сертификата — просто удалить старый из /shared/ssl?

Думаю, это происходит всегда при пересборке, поэтому удалять ничего не нужно.

Сертификат был выпущен вчера, поэтому обычно в скриптах LE требуется флаг --force. Я переименовал старые сертификаты и сейчас тестирую повторную сборку.

Похоже, это не работает: я не вижу вторую доменную зону, которую ввел: https://ssl-tools.net/webservers/rpg-foren.com

Кроме того, кажется, что замена выполнена некорректно: в файле ECC отсутствует поддомен:

cat /etc/runit/1.d/letsencrypt
#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf

issue_cert() {
  LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d rpg-foren.com -d www.rpg-foren.com --keylength $1 -w /var/www/discourse/public
}

cert_exists() {
  [[ "$(cd /shared/letsencrypt/rpg-foren.com$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")" ]]
}

########################################################
# RSA cert
########################################################
issue_cert "4096"

if ! cert_exists ""; then
  # Try to issue the cert again if something goes wrong
  issue_cert "4096" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert \
  -d rpg-foren.com \
  -d www.rpg-foren.com --fullchainpath /shared/ssl/rpg-foren.com.cer \
  --keypath /shared/ssl/rpg-foren.com.key \
  --reloadcmd "sv reload nginx"

########################################################
# ECDSA cert
########################################################
issue_cert "ec-256"

if ! cert_exists "_ecc"; then
  # Try to issue the cert again if something goes wrong
  issue_cert "ec-256" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert --ecc \
  -d rpg-foren.com \
  --fullchainpath /shared/ssl/rpg-foren.com_ecc.cer \
  --keypath /shared/ssl/rpg-foren.com_ecc.key \
  --reloadcmd "sv reload nginx"

if cert_exists "" || cert_exists "_ecc"; then
  grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi

/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop

Я только что выполнил следующие команды вручную, и теперь сертификаты подходят:

/shared/letsencrypt/acme.sh --issue --force -d rpg-foren.com -d www.rpg-foren.com --keylength 4096 -w /var/www/discourse/public --server letsencrypt
/shared/letsencrypt/acme.sh --issue --force -d rpg-foren.com -d www.rpg-foren.com --keylength ec-256 -w /var/www/discourse/public --server letsencrypt

/shared/letsencrypt/acme.sh --installcert -d rpg-foren.com -d www.rpg-foren.com --fullchainpath /shared/ssl/rpg-foren.com.cer --keypath /shared/ssl/rpg-foren.com.key --reloadcmd "sv reload nginx"
/shared/letsencrypt/acme.sh --installcert -d rpg-foren.com -d www.rpg-foren.com --fullchainpath /shared/ssl/rpg-foren.com_ecc.cer --keypath /shared/ssl/rpg-foren.com_ecc.key --reloadcmd "sv reload nginx"

Вот мой вариант переписывания для перенаправления:

   # tell letsencrypt what additional certs to get
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d www.rpg-foren.com --keylength"
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--fullchainpath/
        to: "-d www.rpg-foren.com --fullchainpath"
    - file:
        path: /etc/nginx/conf.d/discourse_redirect.conf
        contents: |
          server {
            listen 80;
            listen 443 ssl;
            server_name www.rpg-foren.com;
            return 301 $scheme://rpg-foren.com$request_uri;

            ssl_protocols TLSv1.2 TLSv1.3;
            ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
            ssl_prefer_server_ciphers off;

            ssl_certificate /shared/ssl/rpg-foren.com.cer;
            ssl_certificate /shared/ssl/rpg-foren.com_ecc.cer;

            ssl_certificate_key /shared/ssl/rpg-foren.com.key;
            ssl_certificate_key /shared/ssl/rpg-foren.com_ecc.key;

            ssl_session_tickets off;
            ssl_session_timeout 1d;
            ssl_session_cache shared:SSL:1m;
          }

Возможно ли, что команда replace выполняется только один раз?

Похоже, сертификат теперь действителен?

Я почти уверен, что перенаправления обрабатываются где-то ещё в цепочке, и вам не нужно ничего делать, чтобы это работало. Я бы, вероятно, удалил эту часть из вашего файла yml.

Похоже, сейчас всё работает как ожидалось.

Да, но я настроил его вручную, а не через хук, потому что хук не сработал корректно.

Вы имеете в виду перенаправление с поддомена www. на основной домен? По крайней мере, не через nginx. Там не определено ни одного URL, чтобы веб-сервер отвечал на все входящие домены.

.
У меня всё работает (см. ниже).

Я имею в виду, что любой адрес, указывающий на сайт, перенаправляется на имя хоста. Для стандартной установки вы можете ввести IP-адрес, и он перенаправит вас на https://hostname. (См. ниже)

Я только что настроил это, создав новую стандартную установку с адресом https://dashboard.literatecomputing.com/, а также добавив extrahostname.myforum.us в поле domain2 выше и скопировав полученный хук after_ssl сразу после строки hooks: в файле web_only.yml (причём сделал это во время сборки контейнера данных скриптом, так что мне не пришлось пересобирать его после завершения первого запуска!).

Все следующие адреса работают как ожидается:

Означает ли это, что поддомен сохраняется в /etc/runit/1.d/letsencrypt как для скрипта установки RSA, так и для скрипта установки ECC?
Как видно выше, хук сохранил поддомен только в части RSA, но не в части ECC.

  --installcert \
  -d rpg-foren.com \
  -d www.rpg-foren.com
  --installcert --ecc \
  -d rpg-foren.com \
  --fullchainpath

Вот файл /etc/runit/1.d/letsencrypt

#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf

issue_cert() {
  LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d test.myforum.us -d extrahostname.myforum.us --keylength $1 -w /var/www/discourse/public
}

cert_exists() {
  [[ "$(cd /shared/letsencrypt/test.myforum.us$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")" ]]
}

########################################################
# RSA сертификат
########################################################
issue_cert "4096"

if ! cert_exists ""; then
  # Попытка выдать сертификат снова, если что-то пошло не так
  issue_cert "4096" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert \
  -d test.myforum.us \
  -d extrahostname.myforum.us  --fullchainpath /shared/ssl/test.myforum.us.cer \
  --keypath /shared/ssl/test.myforum.us.key \
  --reloadcmd "sv reload nginx"

########################################################
# ECDSA сертификат
########################################################
issue_cert "ec-256"

if ! cert_exists "_ecc"; then
  # Попытка выдать сертификат снова, если что-то пошло не так
  issue_cert "ec-256" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert --ecc \
  -d test.myforum.us \
  --fullchainpath /shared/ssl/test.myforum.us_ecc.cer \
  --keypath /shared/ssl/test.myforum.us_ecc.key \
  --reloadcmd "sv reload nginx"

if cert_exists "" || cert_exists "_ecc"; then
  grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi

/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop

А, понял. Вижу, что это в RSA-сертификате (плохой), но не в ECC-сертификате (хороший).

Хорошо, теперь я понял. В этом блоке --fullcert необходимо указать global: true. Я сейчас тестирую это.

ОК. Вот новый файл ‘/etc/runit/1.d/letsencrypt’

#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf

issue_cert() {
  LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh --issue $2 -d test.myforum.us -d extrahostname.myforum.us --keylength $1 -w /var/www/discourse/public
}

cert_exists() {
  [[ "$(cd /shared/letsencrypt/test.myforum.us$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")" ]]
}

########################################################
# RSA сертификат
########################################################
issue_cert "4096"

if ! cert_exists ""; then
  # Попробовать выдать сертификат снова, если что-то пошло не так
  issue_cert "4096" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert \
  -d test.myforum.us \
  -d extrahostname.myforum.us  --fullchainpath /shared/ssl/test.myforum.us.cer \
  --keypath /shared/ssl/test.myforum.us.key \
  --reloadcmd "sv reload nginx"

########################################################
# ECDSA сертификат
########################################################
issue_cert "ec-256"

if ! cert_exists "_ecc"; then
  # Попробовать выдать сертификат снова, если что-то пошло не так
  issue_cert "ec-256" "--force"
fi

LE_WORKING_DIR="${LETSENCRYPT_DIR}" /shared/letsencrypt/acme.sh \
  --installcert --ecc \
  -d test.myforum.us \
  -d extrahostname.myforum.us  --fullchainpath /shared/ssl/test.myforum.us_ecc.cer \
  --keypath /shared/ssl/test.myforum.us_ecc.key \
  --reloadcmd "sv reload nginx"

if cert_exists "" || cert_exists "_ecc"; then
  grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi

/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
~
~

Теперь у меня есть это, что выглядит хорошо? https://ssl-tools.net/webservers/extrahostname.myforum.us

Выглядит ли это правильно? Если да, я отредактирую первое сообщение, чтобы включить директиву global.

Моя идея:

    # сообщите letsencrypt, какие дополнительные сертификаты нужно получить
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d www.rpg-foren.com --keylength"
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--installcert \/
        to:  |
          --installcert \
          -d www.rpg-foren.com
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--installcert --ecc \/
        to:  |
          --installcert --ecc \
          -d www.rpg-foren.com

У меня разве не работает? В моём коде на одну треть меньше строк.

Я не вижу от вас переписанного текста? Или я что-то упустил?
Я просто хотел сделать красивую правку, чтобы файл в итоге выглядел хорошо^^

Я ещё этого не сделал. Я ждал, чтобы убедиться, что вы считаете, будто это работает.

Вот изменение: просто добавлено global: true в конец второго replace:

    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--fullchainpath/
        to: "-d =domain2=  --fullchainpath"
        global: true

А вот полный вариант:

  after_ssl:
   # сообщить letsencrypt, какие дополнительные сертификаты нужно получить
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--keylength/
        to: "-d extrahostname.myforum.us --keylength"
    - replace:
        filename: "/etc/runit/1.d/letsencrypt"
        from: /--fullchainpath/
        to: "-d extrahostname.myforum.us  --fullchainpath"
        global: true


ok, так что global — это параметр, который вам нужен для множественных замен.

Выглядит всё хорошо по присланным файлам, я пока не пробовал.

Да. Извините, что раньше я не уделял достаточно внимания, чтобы понять, о чём вы говорите. По результатам моего (плохого) теста всё «сработало», но я этого не заметил и не знаю, как проверить, действительно ли там есть сертификат ec-что-там. Спасибо за настойчивость.

Делает ли https://ssl-tools.net/webservers/extrahostname.myforum.us вид, будто там есть всё необходимое?

Я теперь отредактировал первое сообщение, так что вы можете попробовать и скопировать/вставить данные из формы выше.

Если вы хотите протестировать это на тестовом сайте и можете отправить мне SSH-ключ, я предоставлю вам доступ к только что созданному мной. Тогда вы сможете выполнить чистую установку там с вашим собственным тестовым доменом. Или же вы можете просто сделать это на своём рабочем сайте и надеяться на лучшее. :person_shrugging:

Вы можете найти его здесь:

ls -la /var/discourse/shared/standalone/ssl/
total 24
drwxr-xr-x  2 root root 4096 Sep 24 13:02 .
drwxr-xr-x 15 root root 4096 Sep 23 18:31 ..
-rw-r--r--  1 root root 3941 Sep 25 07:43 rpg-foren.com.cer
-rw-r--r--  1 root root 3941 Sep 25 07:43 rpg-foren.com_ecc.cer
-rw-------  1 root root 3243 Sep 25 07:43 rpg-foren.com_ecc.key
-rw-------  1 root root 3243 Sep 25 07:43 rpg-foren.com.key

проблема в том, что я не знаю, как тестировать ECC и RSA по отдельности.
поскольку файл создания теперь подходит, дальнейшие тесты не требуются.

root@test-web-only:/shared/ssl# ls -l
всего 16
-rw-r--r-- 1 root root 3953 25 сен 16:41 test.myforum.us.cer
-rw-r--r-- 1 root root 2877 25 сен 16:41 test.myforum.us_ecc.cer
-rw------- 1 root root  227 25 сен 16:41 test.myforum.us_ecc.key
-rw------- 1 root root 3247 25 сен 16:41 test.myforum.us.key

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

Вы можете проверить сертификат следующим образом:

openssl x509 -in /var/discourse/shared/standalone/ssl/test.myforum.us.cer -noout -text
Затем домены должны быть перечислены в разделе dns:
DNS:rpg-foren.com, DNS:www.rpg-foren.com

root@test:/var/discourse# openssl x509 -in /var/discourse/shared/web-only/ssl/test.myforum.us.cer -noout -text                       
Сертификат:                                                                                                                         
    Данные:                                                                                                                            
        Версия: 3 (0x2)                                                                                                             
        Серийный номер:                                                                                                               
            03:f8:b5:6a:e0:97:53:7f:22:33:81:22:35:b4:3f:73:75:7f 
        Алгоритм подписи: sha256WithRSAEncryption                                                                                 
        Издатель: C = US, O = Let's Encrypt, CN = R10                                                                                  
        Срок действия                                                                                                                     
            Действителен с: Sep 25 14:57:13 2024 GMT                  
            Действителен до: Dec 24 14:57:12 2024 GMT                                                                                     
        Субъект: CN = test.myforum.us                            
        Информация об открытом ключе субъекта:                                  
            Алгоритм открытого ключа: rsaEncryption                   
                Открытый ключ: (4096 бит)                                                                                                                     
                Модуль:                                                                                                             
                    00:be:a3:9b:79:78:dd:8f:e2:8f:28:f0:d9:6c:74: 
...                    b0:84:33                                                                                                                               
                Экспонента: 65537 (0x10001)                                                                                                                  
        Расширения X509v3:                                                                                                                                                                
            X509v3 Key Usage: критическое                           
                Цифровая подпись, Шифрование ключа               
            X509v3 Extended Key Usage:                           
                Аутентификация веб-сервера TLS, Аутентификация веб-клиента TLS                                                                                                              
            X509v3 Basic Constraints: критическое                                                                                                                                            
                CA:FALSE                                                                                                                                                                  
            X509v3 Subject Key Identifier:                                                                                                                                                
                43:55:B7:D6:54:03:CE:B0:FB:C8:D1:2A:42:F5:B7:C5:60:C7:D8:48                                                                                                                                                              
            X509v3 Authority Key Identifier:                                 
                BB:BC:C3:47:A5:E4:BC:A9:C6:C3:A4:72:0C:10:8D:A2:35:E1:C8:E8                                                                                
            Информация об авторитете:                                    
                OCSP - URI:http://r10.o.lencr.org                                                                                                                                                                                        
                CA Issuers - URI:http://r10.i.lencr.org/                                                                                                                                                                                 
            X509v3 Subject Alternative Name:                                                                                                                                                                                             
                DNS:extrahostname.myforum.us, DNS:test.myforum.us                                                                                                                                                                        
            X509v3 Certificate Policies:                                     
                Политика: 2.23.140.1.2.1                                                       
            CT Precertificate SCTs:                                                          
                Подписанная метка времени сертификата:                                                                                                                                                                                            
                    Версия   : v1 (0x0)                                                                                                                                                                                                 
                    Log ID    : DF:E1:56:EB:AA:05:AF:B5:9C:0F:86:71:8D:A8:C0:32:                                                                           
                                4E:AE:56:D9:6E:A7:F5:A5:6A:01:D1:C1:3B:BE:52:5C                                                                            
                    Метка времени : Sep 25 15:55:44.143 2024 GMT                                 
                    Расширения: нет                                                                                                                                                                                                     
                    Подпись : ecdsa-with-SHA256                                                                                                                                                                                        
                    Подписанная метка времени сертификата:                                                                       
                    Версия   : v1 (0x0)                                                                            
                    Log ID    : A2:E3:0A:E4:45:EF:BD:AD:9B:7E:38:ED:47:67:77:53:                                                                           
                                D7:82:5B:84:94:D7:2B:5E:1B:2C:C4:B9:50:A4:47:E7                                                                            
                    Метка времени : Sep 25 15:55:45.945 2024 GMT                                                        
                    Расширения: нет                                                                                
                    Подпись : ecdsa-with-SHA256                                                                   
    Алгоритм подписи: sha256WithRSAEncryption                                                                    
    Значение подписи:                                                                                                
        cf:c6:59:d8                                  

и это включает:

            X509v3 Subject Alternative Name:                                                 
                DNS:extrahostname.myforum.us, DNS:test.myforum.us  

Ах. Хорошо.

openssl x509 -in /var/discourse/shared/web-only/ssl/test.myforum.us_ecc.cer -noout -text 

содержит:

            X509v3 Subject Alternative Name: 
                DNS:extrahostname.myforum.us, DNS:test.myforum.us