Как настроить HTTPS на nginx в 2015 году: от покупки сертификата до A+ на SSL Labs
Коротко: купите сертификат (NameCheap/Comodo, ~$10/год), сформируйте CSR через OpenSSL, получите .crt + ca-bundle.crt, склейте в цепочку, пропишите в nginx. Let's Encrypt появился только в декабре 2015 — до этого HTTPS требовал денег.
Шаг 1: Генерация CSR
# На сервере (Ubuntu 14.04)
openssl genrsa -out /etc/ssl/private/mysite.key 2048
chmod 600 /etc/ssl/private/mysite.key
openssl req -new -key /etc/ssl/private/mysite.key -out /tmp/mysite.csr
# Заполняем поля:
# Country Name: KG
# State or Province: Chuy
# Locality: Bishkek
# Organization Name: ТОО Моя Компания
# Common Name: mysite.kg ← ВАЖНО: точно соответствует домену
# Email: admin@mysite.kg
cat /tmp/mysite.csr
# Отправляем этот CSR в NameCheap/Comodo при покупке сертификата
Шаг 2: Получение и сборка цепочки сертификатов
После покупки приходит архив с файлами:
mysite_kg.crt— ваш сертификатmysite_kg.ca-bundle— промежуточные сертификаты
# Склеить в одну цепочку — ПОРЯДОК ВАЖЕН
cat /tmp/mysite_kg.crt /tmp/mysite_kg.ca-bundle > /etc/ssl/certs/mysite.crt
# Проверить цепочку
openssl verify -CAfile /tmp/mysite_kg.ca-bundle /tmp/mysite_kg.crt
# Должно быть: mysite_kg.crt: OK
Шаг 3: Конфигурация nginx
# /etc/nginx/sites-available/mysite
# Перенаправление HTTP → HTTPS
server {
listen 80;
server_name mysite.kg www.mysite.kg;
return 301 https://mysite.kg$request_uri;
}
# Перенаправление www → без www (для SEO)
server {
listen 443 ssl;
server_name www.mysite.kg;
ssl_certificate /etc/ssl/certs/mysite.crt;
ssl_certificate_key /etc/ssl/private/mysite.key;
return 301 https://mysite.kg$request_uri;
}
# Основной HTTPS сервер
server {
listen 443 ssl;
server_name mysite.kg;
ssl_certificate /etc/ssl/certs/mysite.crt;
ssl_certificate_key /etc/ssl/private/mysite.key;
# Протоколы: SSLv3 уязвим (POODLE, октябрь 2014)
# TLSv1 оставляем для совместимости с Android 4.x
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# Набор шифров: Mozilla Intermediate (2015)
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
ssl_prefer_server_ciphers on;
# DH параметры для Forward Secrecy
ssl_dhparam /etc/ssl/dhparam.pem; # Генерируем ниже
# Session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS: браузер будет обращаться только по HTTPS в течение 1 года
# ВНИМАНИЕ: после добавления отменить нельзя в течение max-age секунд
add_header Strict-Transport-Security "max-age=31536000" always;
# OCSP Stapling — ускоряет SSL handshake
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
root /var/www/mysite;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param HTTPS on; # Сообщаем PHP что используется HTTPS
}
}
Генерация DH параметров
# Долго (5-20 минут), но обязательно для Forward Secrecy
openssl dhparam -out /etc/ssl/dhparam.pem 2048
# Проверяем и перезапускаем nginx
sudo nginx -t
sudo service nginx reload
Проверка SSL рейтинга
# Проверить на SSL Labs (онлайн):
# https://www.ssllabs.com/ssltest/analyze.html?d=mysite.kg
# Или локально через openssl
openssl s_client -connect mysite.kg:443 -tls1_2
# Проверка HSTS
curl -I https://mysite.kg | grep Strict-Transport-Security
# Strict-Transport-Security: max-age=31536000
С этой конфигурацией получали A+ на SSL Labs. Минус — TLSv1 для старых Android 4.0 устройств, которых в Кыргызстане в 2015 году ещё было ~15% от Android аудитории.
PHP: определение HTTPS в коде
<?php
// После настройки nginx с fastcgi_param HTTPS on
function isHttps(): bool {
return
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https' ||
($_SERVER['SERVER_PORT'] ?? 80) == 443;
}
// Принудительный редирект в PHP (резервный, основной — в nginx)
if (!isHttps() && $_SERVER['HTTP_HOST'] !== 'localhost') {
$redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
header("HTTP/1.1 301 Moved Permanently");
header("Location: $redirect");
exit();
}
Что изменил Let's Encrypt (декабрь 2015)
С декабря 2015 года Certbot автоматизировал всё:
# После December 2015:
sudo certbot --nginx -d mysite.kg -d www.mysite.kg
# Автоматически: получение сертификата, настройка nginx, автообновление
До этого — каждый год вручную покупать и переустанавливать. Для 20+ клиентских сайтов это было ощутимой работой. Let's Encrypt убрал и стоимость ($10/домен/год), и ручной труд.