Skip to content

Instantly share code, notes, and snippets.

@llcawc
Created June 30, 2025 19:30
Show Gist options
  • Save llcawc/4509e8ab44a73160620a0a936e2f62d9 to your computer and use it in GitHub Desktop.
Save llcawc/4509e8ab44a73160620a0a936e2f62d9 to your computer and use it in GitHub Desktop.
Настройка SSL в Angie

Настройка SSL в Angie

Вариант 1: Автоматическое получение сертификата

Получение сертификата LetsEncrypt на сервере Angie начиная с версии 1.5.0 с помощью модуля Acme. Обеспечивает автоматическое получение сертификатов с использованием протокола ACME По умолчанию этот модуль не собирается; его сборку необходимо включить с помощью параметра конфигурации --with-http_acme_module.

В пакетах из наших репозиториев модуль уже включен в сборку.

Шаги для включения запроса сертификатов в конфигурации:

  1. Настройте клиент ACME в блоке http с помощью директивы acme_client, задающей уникальное имя клиента и другие параметры; можно настроить несколько клиентов ACME.

  2. Укажите домены, для которых обновляются сертификаты: для доменных имен, перечисленных во всех директивах server_name всех блоков server с директивами acme, указывающими на один и тот же клиент ACME, будет выдан единый сертификат.

  3. Убедитесь, что принимаются вызовы ACME: сейчас Angie поддерживает только проверку доменных имен по HTTP, что требует ответа на специальный запрос на порту 80 от удостоверяющего центра (CA); это так называемый вызов ACME.

  4. Настройте SSL с использованием полученного сертификата и ключа: Модуль делает сертификаты и ключи доступными в виде встроенных переменных, которые можно использовать в конфигурации для заполнения ssl_certificate и ssl_certificate_key.

Ключи и сертификаты клиентов хранятся в кодировке PEM в соответствующих подкаталогах каталога, заданного с помощью параметра конфигурации --http-acme-client-path:

ls /var/lib/angie/acme_client/example

  account.key  certificate.pem  private.key

Клиенту ACME требуется учетная запись на сервере CA. Для ее создания и управления ею клиент использует закрытый ключ (account.key); если ключа у него еще нет, ключ создается при запуске. Затем клиент использует его для регистрации учетной записи на сервере.

Примечание Если у вас уже есть ключ учетной записи, поместите его в подкаталог клиента перед запуском для повторного использования учетной записи.

Клиент ACME также использует отдельный ключ (private.key) для запросов на подпись сертификата (CSR); если нужно, этот ключ сертификата также создается автоматически при запуске.

При запуске клиент запрашивает сертификат, если его еще нет, подписывая и отправляя CSR для всех доменов, которыми он управляет, серверу CA. Сервер проверяет владение доменом по HTTP и выдает сертификат, который клиент сохраняет локально (certificate.pem).

Когда приближается завершение срока действия сертификата или изменяется список доменов, клиент подписывает и отправляет еще один CSR на сервер CA. Сервер снова проверяет владение и выдает новый сертификат, который клиент устанавливает локально, заменяя предыдущий.

Здесь клиент ACME с именем example управляет доменами example.com и www.example.com. Сертификат и его ключ доступны через префиксные переменные $acme_cert_<name> и $acme_cert_key_<name>. Они содержат соответствующие файлы, которые используются с ssl_certificate и ssl_certificate_key:

server {
    listen 443 ssl;
    http2 on;

    server_name example.ru;
    root /var/www/example.ru/html;
    index index.html index.php index.xml;

    acme example;
    ssl_certificate $acme_cert_example;
    ssl_certificate_key $acme_cert_key_example;

    # pass the PHP scripts to FastCGI server listening on UNIX sock
    #
    location ~ \.php$ {
        fastcgi_pass   unix:/run/php/php8.2-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        /etc/angie/fastcgi_params;
    }

    location / {
        try_files $uri $uri/ =404;
    }
    #
    # redirect server error pages to the static page /404.html
    error_page 404    /404.html;
    location = /404.html {
        root /var/www/example.ru/html;
    }
    #
    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root /var/www/example.ru/html;
    }
    # deny access to .htaccess files, if Apache's document root concurs with angie's one
    location ~ /\.ht {
        deny  all;
    }
}
server {
    listen 443 ssl;
    http2 on;

    server_name www.example.ru;
    return 301 https://example.ru$request_uri;

    acme example;
    ssl_certificate $acme_cert_example;
    ssl_certificate_key $acme_cert_key_example;
}
server {
    listen 80;
    listen [::]:80;

    server_name example.ru www.example.ru;
    return 301 https://example.ru$request_uri;
}

Как уже отмечалось, порт 80 должен быть открыт для вызовов ACME по HTTP. Однако, как указывает предыдущий пример, директива listen для этого порта может стоять в отдельном блоке server. Если существующего блока с такой директивой у вас нет, вы можете ограничить его только вызовами ACME:

server {
    listen 80;
    return 444; # Нет ответа, соединение закрыто
}

Оптимизация HTTPS-сервера

документация Angie

sudo nano /etc/angie/angie.conf

Вариант настройки angie.conf:

# Load Brotli module
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

user angie;
worker_processes auto;
worker_rlimit_nofile 65536;

error_log  /var/log/angie/error.log notice;
pid        /var/run/angie.pid;

events {
    worker_connections      65536;
}

http {

    # Basic
    sendfile                  on;
    tcp_nopush                on;
    tcp_nodelay               on;
    types_hash_max_size       2048;
    server_tokens             off;
    ignore_invalid_headers    on;

    # Decrease default timeouts to drop slow clients
    keepalive_timeout         40s;
    send_timeout              20s;
    client_header_timeout     20s;
    client_body_timeout       20s;
    reset_timedout_connection on;

    # Hash sizes
    server_names_hash_bucket_size 64;

    # Acme Let's Encrypt certificate enable
    resolver 127.0.0.53;
    acme_client example https://acme-v02.api.letsencrypt.org/directory;

    ssl_session_cache         shared:SSL:10m;
    ssl_session_timeout       10m;

    # Mime types
    include       /etc/angie/mime.types;
    default_type  application/octet-stream;

    # Logs
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format extended '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" rt="$request_time" '
                        '"$http_user_agent" "$http_x_forwarded_for" '
                        'h="$host" sn="$server_name" ru="$request_uri" u="$uri" '
                        'ucs="$upstream_cache_status" ua="$upstream_addr" us="$upstream_status" '
                        'uct="$upstream_connect_time" urt="$upstream_response_time"';

    access_log  /var/log/angie/access.log  main;

    # Dynamic gzip:
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    #text/html is always included by default, no need to include explicitely
    gzip_types  text/plain text/xml text/css
                application/x-javascript application/javascript application/ecmascript text/javascript application/json
                application/rss+xml
                application/xml
                image/svg+xml
                application/x-font-ttf application/vnd.ms-fontobject image/x-icon;

    # Dynamic brotli:
    brotli on;
    brotli_comp_level 6;
    #text/html is always included by default, no need to include explicitely
    brotli_types  text/plain text/xml text/css
                  application/x-javascript application/javascript application/ecmascript text/javascript application/json
                  application/rss+xml
                  application/xml
                  image/svg+xml
                  application/x-font-ttf application/vnd.ms-fontobject image/x-icon;

    # Virtual Hosts
    include /etc/angie/sites-enabled/*;

    # Configs
    # include /etc/angie/http.d/*.conf;
}

Браузеры обычно сохраняют полученные промежуточные сертификаты, подписанные доверенными центрами сертификации, поэтому активно используемые браузеры уже могут иметь требуемые промежуточные сертификаты и не выдать предупреждение о сертификате, присланном без связанной с ним цепочки сертификатов. Убедиться в том, что сервер присылает полную цепочку сертификатов, можно при помощи утилиты командной строки openssl, например:

openssl s_client -connect www.godaddy.com:443

Certificate chain
 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
     /OU=MIS Department/CN=www.GoDaddy.com
     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
   i:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
     /OU=ValiCert Class 2 Policy Validation Authority
     /CN=http://www.valicert.com//[email protected]

Настройка сертификата SSL - вариант 2

используем ACME клиент - certbot

Генерирует ключ

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Создаёт папку для снипетов

sudo mkdir -p /etc/angie/snippets/

Создаёт снипет для SSL

sudo nano /etc/angie/snippets/ssl-params.conf
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

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;

add_header Strict-Transport-Security "max-age=63072000" always;

Получение сертификата Let's Encrypt с помощью certbot

Сайт: Let's Encrypt

Let’s Encrypt использует ACME-протокол для подтверждения ваших прав на данное доменное имя, а также для выпуска сертификата для него. Чтобы получить сертификат Let’s Encrypt, вам необходимо использовать ACME-клиент.

Представленные ниже ACME-клиенты разрабатываются сторонними организациями. Let’s Encrypt не управляет их разработкой, не проверяет их код и не предоставляет гарантий их безопасности и надёжности.

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

Рекомендуемый клиент: Certbot

Установка certbot:

Если нет менеджера пакетов snap, устанавливаем:

sudo apt update
sudo apt install snapd

Если команда sudo не установлена (обычно из-за того, что во время установки был предоставлен пароль root), вы можете установить snap, сначала переключившись на учетную запись root:

sudo su root
sudo apt update
sudo apt install snapd

Либо выйдите из системы и снова войдите в нее, либо перезапустите систему, чтобы убедиться, что пути snap обновлены правильно.

После этого установите core snap, чтобы получить последнюю версию snapd.

sudo snap install core
  core 16-2.45.2 from Canonical✓ installed

Удалите certbot-auto и все пакеты Certbot OS Если у вас установлены какие-либо пакеты Certbot с помощью диспетчера пакетов ОС, такого как aptdnf или yum, вам следует удалить их перед установкой Certbot snap, чтобы убедиться, что при выполнении команды certbot используется привязка, а не установка из диспетчера пакетов вашей ОС. Точная команда для этого зависит от вашей операционной системы, но распространенными примерами являются sudo apt-get remove certbotsudo dnf remove certbot или sudo yum remove certbot.

sudo apt remove certbot
sudo apt autoclean

Устанавливает certbot:

sudo snap install --classic certbot

Подготовка команды certbot

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Подтвердите уровень защиты плагина

sudo snap set certbot trust-plugin-with-root=ok

Для доступа к сайту при обновлении сертификата необходимо внести дополнения в файл конфига сайта под управлением WinterCMS:

sudo nano /etc/angie/sites-available/example.com.conf

Добавить в секцию server разрешение на доступ:

# Block access to all dot files and folders except .well-known
location ~ /\.(?!well-known).* { deny all; }
location ~ ^/.well-known/acme-challenge { try_files $uri 404; }

Выпускает сертификат

sudo certbot certonly --webroot -w /var/www/example.com/html -d example.com -d www.example.com

Ответ сервера:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem

This certificate expires on 2023-11-24.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   <https://letsencrypt.org/donate>
 * Donating to EFF:                    <https://eff.org/donate-le>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Меняет конфиг сайта

sudo nano /etc/angie/sites-available/example.com.conf
server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name www.example.com;
    return 301 https://example.com$request_uri;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    include snippets/ssl-params.conf;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name example.com;
    root /var/www/example.com/html;
    index index.html index.xml;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    include snippets/ssl-params.conf;

    location / {
        try_files $uri $uri/ =404;
    }
    #
    # redirect server error pages to the static page /404.html
    error_page 404    /404.html;
    location = /404.html {
        root /var/www/example.com/html;
    }
    #
    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root /var/www/example.com/html;
    }
}

Проверяет конфиг и перезагружает сервер angie:

sudo angie -t && sudo service angie reload

Проверяет домен

  • curl <http://example.com> — редирект
  • curl <https://example.com> — сайт

как проверить возможность автоматического обновления сертификатов:

sudo certbot renew --dry-run

# или для nodejs сервера:

sudo /usr/bin/certbot certonly --webroot -w /var/www/example.com/app/public -d example.com -d www.example.com --dry-run

Установка cron:

sudo crontab -e

С новой строки написать команду (каждый вторник в 0:30):

30 0 * * 2 /usr/bin/certbot certonly -n --webroot -w /var/www/example.com/html -d example.com -d www.example.com

или лучше сразу для всех серверов (каждый вторник в 0:30):

30 0 * * 2 /usr/bin/certbot renew

Let's Encrypt разрешает и рекомендует производить обновление за 30 дней до окончания действующего сертификата.

Посмотреть cron:

sudo crontab -l

Подробнее о обновлении сертификата SSL смотри здесь:

Как получить сертификат Let's Encrypt - Losst

И здесь:

Как установить бесплатный SSL-сертификат от Let's Encrypt на VPS – Beget


END

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment