- Home »

Создание самоподписанного SSL-сертификата для Nginx на последний CentOS
Даёшь безопасность локальным проектам! Если тебе нужно поднять HTTPS на тестовом сервере, локальном стенде или просто хочешь зашифровать трафик без покупки коммерческого сертификата, самоподписанный SSL-сертификат — это то, что доктор прописал. Да, браузер будет ворчать про “небезопасное соединение”, но для разработки, тестирования и внутренних сервисов это идеальное решение.
Сегодня разберём, как создать самоподписанный SSL-сертификат для Nginx на CentOS и настроить всё так, чтобы работало из коробки. Покажу не только базовую настройку, но и несколько трюков, которые сэкономят время и нервы.
Зачем нужен самоподписанный сертификат?
Самоподписанные сертификаты — это как временные номера на машине. Они работают, но все понимают, что это не окончательное решение. Основные сценарии использования:
- Разработка и тестирование — когда нужно проверить работу HTTPS без лишних телодвижений
- Внутренние сервисы — админки, мониторинг, CI/CD системы внутри сети
- Прототипирование — быстро поднять защищённое соединение для демо
- Обучение — понять, как работает SSL/TLS без финансовых вложений
Как это работает изнутри
Самоподписанный сертификат — это обычный X.509 сертификат, который подписан не центром сертификации (CA), а самим собой. Технически он ничем не отличается от “настоящего” сертификата, только браузеры не доверяют такому издателю.
Процесс создания включает:
- Генерацию приватного ключа (RSA/ECDSA)
- Создание запроса на сертификат (CSR)
- Подписание CSR собственным ключом
- Получение готового сертификата
Пошаговая настройка на CentOS
Шаг 1: Подготовка системы
Начнём с обновления системы и установки необходимых пакетов:
# Обновляем систему
dnf update -y
# Устанавливаем OpenSSL и Nginx
dnf install -y openssl nginx
# Создаём директории для сертификатов
mkdir -p /etc/nginx/ssl
chmod 700 /etc/nginx/ssl
Шаг 2: Создание приватного ключа
Генерируем приватный ключ. Тут есть два варианта — RSA и ECDSA. RSA более совместим, ECDSA — быстрее и современнее:
# RSA ключ (классика)
openssl genrsa -out /etc/nginx/ssl/server.key 2048
# Или ECDSA (современный подход)
openssl ecparam -genkey -name prime256v1 -out /etc/nginx/ssl/server.key
# Защищаем ключ
chmod 600 /etc/nginx/ssl/server.key
Шаг 3: Создание сертификата
Теперь создаём сам сертификат. Можно сделать это одной командой:
# Создаём самоподписанный сертификат на 365 дней
openssl req -new -x509 -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -days 365 -subj "/C=RU/ST=Moscow/L=Moscow/O=MyCompany/CN=localhost"
# Или с интерактивным вводом данных
openssl req -new -x509 -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -days 365
Если выбираешь интерактивный режим, система спросит:
- Country Name — код страны (RU)
- State — область/регион
- City — город
- Organization — название организации
- Common Name — ВАЖНО! Здесь указывай домен или IP
Шаг 4: Создание сертификата с SAN
Для продакшн-подобной настройки лучше создать сертификат с Subject Alternative Names (SAN). Это позволит использовать один сертификат для нескольких доменов:
# Создаём конфигурационный файл
cat > /tmp/server.conf << EOF
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = RU
ST = Moscow
L = Moscow
O = MyCompany
CN = localhost
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = *.localhost
DNS.3 = mysite.local
IP.1 = 127.0.0.1
IP.2 = 192.168.1.100
EOF
# Создаём сертификат с SAN
openssl req -new -x509 -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -days 365 -config /tmp/server.conf -extensions v3_req
Шаг 5: Настройка Nginx
Создаём конфигурацию виртуального хоста:
# Создаём конфиг для HTTPS сайта
cat > /etc/nginx/conf.d/ssl-site.conf << 'EOF'
server {
listen 80;
server_name localhost;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name localhost;
# SSL конфигурация
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# Улучшенная SSL конфигурация
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS заголовок
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Корневая директория
root /usr/share/nginx/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
# Логи
access_log /var/log/nginx/ssl-access.log;
error_log /var/log/nginx/ssl-error.log;
}
EOF
Шаг 6: Тестирование и запуск
# Проверяем конфигурацию
nginx -t
# Запускаем и включаем автозагрузку
systemctl enable nginx
systemctl start nginx
# Проверяем статус
systemctl status nginx
# Открываем порты в firewall
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Практические примеры и кейсы
Кейс 1: Разработка с Docker
Часто нужно поднять HTTPS для контейнеризированного приложения:
# Создаём сертификат для Docker окружения
openssl req -new -x509 -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -days 365 -subj "/CN=app.docker.local"
# Добавляем в /etc/hosts
echo "127.0.0.1 app.docker.local" >> /etc/hosts
Кейс 2: API для мобильного приложения
Мобильные приложения часто требуют HTTPS даже для тестовых API:
# Конфигурация для API
cat > /etc/nginx/conf.d/api-ssl.conf << 'EOF'
server {
listen 443 ssl http2;
server_name api.local;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
Сравнение подходов
Критерий | Самоподписанный | Let's Encrypt | Коммерческий |
---|---|---|---|
Стоимость | Бесплатно | Бесплатно | Платно |
Время создания | 5 минут | 10-15 минут | От часа до дней |
Доверие браузеров | Нет | Да | Да |
Автоматическое обновление | Нет | Да (через certbot) | Нет |
Подходит для продакшена | Нет | Да | Да |
Продвинутые техники
Создание собственного CA
Для корпоративного использования можно создать собственный центр сертификации:
# Создаём корневой CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -key ca.key -sha256 -subj "/C=RU/ST=Moscow/L=Moscow/O=MyCA/CN=MyCA" -days 3650 -out ca.crt
# Создаём серверный ключ
openssl genrsa -out server.key 4096
# Создаём запрос на сертификат
openssl req -new -key server.key -out server.csr -subj "/C=RU/ST=Moscow/L=Moscow/O=MyCompany/CN=localhost"
# Подписываем сертификат своим CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256
Автоматизация через скрипт
#!/bin/bash
# Скрипт для автоматического создания SSL сертификата
DOMAIN=${1:-localhost}
SSL_DIR="/etc/nginx/ssl"
DAYS=365
echo "Создаём SSL сертификат для домена: $DOMAIN"
# Создаём директорию
mkdir -p $SSL_DIR
# Генерируем ключ
openssl genrsa -out $SSL_DIR/$DOMAIN.key 2048
# Создаём сертификат
openssl req -new -x509 -key $SSL_DIR/$DOMAIN.key -out $SSL_DIR/$DOMAIN.crt -days $DAYS -subj "/C=RU/ST=Moscow/L=Moscow/O=AutoSSL/CN=$DOMAIN"
# Устанавливаем права
chmod 600 $SSL_DIR/$DOMAIN.key
chmod 644 $SSL_DIR/$DOMAIN.crt
echo "Сертификат создан: $SSL_DIR/$DOMAIN.crt"
echo "Ключ создан: $SSL_DIR/$DOMAIN.key"
Интеграция с другими инструментами
Ansible playbook
Для автоматизации развёртывания:
---
- name: Setup SSL certificate
hosts: servers
tasks:
- name: Create SSL directory
file:
path: /etc/nginx/ssl
state: directory
mode: '0700'
- name: Generate private key
openssl_privatekey:
path: /etc/nginx/ssl/server.key
size: 2048
- name: Generate certificate
openssl_certificate:
path: /etc/nginx/ssl/server.crt
privatekey_path: /etc/nginx/ssl/server.key
provider: selfsigned
common_name: "{{ ansible_hostname }}"
Docker Compose
Для контейнеризированных окружений:
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./ssl:/etc/nginx/ssl:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
command: >
sh -c "
if [ ! -f /etc/nginx/ssl/server.crt ]; then
openssl req -x509 -newkey rsa:2048 -keyout /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt -days 365 -nodes -subj '/CN=localhost';
fi &&
nginx -g 'daemon off;'"
Мониторинг и обслуживание
Проверка срока действия
# Проверяем срок действия сертификата
openssl x509 -in /etc/nginx/ssl/server.crt -text -noout | grep "Not After"
# Или более читаемый вариант
openssl x509 -in /etc/nginx/ssl/server.crt -enddate -noout
# Скрипт для мониторинга
#!/bin/bash
CERT_FILE="/etc/nginx/ssl/server.crt"
EXPIRE_DATE=$(openssl x509 -in $CERT_FILE -enddate -noout | cut -d= -f2)
EXPIRE_TIMESTAMP=$(date -d "$EXPIRE_DATE" +%s)
NOW_TIMESTAMP=$(date +%s)
DAYS_LEFT=$(( ($EXPIRE_TIMESTAMP - $NOW_TIMESTAMP) / 86400 ))
echo "Сертификат истекает через: $DAYS_LEFT дней"
if [ $DAYS_LEFT -lt 30 ]; then
echo "ВНИМАНИЕ: Сертификат скоро истечёт!"
fi
Возможности автоматизации
Интеграция с CI/CD
Самоподписанные сертификаты отлично подходят для автоматических тестов:
# GitLab CI пример
test_ssl:
script:
- openssl req -x509 -newkey rsa:2048 -keyout test.key -out test.crt -days 1 -nodes -subj '/CN=test.local'
- curl -k https://test.local/api/health
Автоматическое обновление
Cron задача для обновления сертификата:
# Добавляем в crontab
0 0 1 * * /usr/local/bin/renew-ssl.sh
# Скрипт обновления
#!/bin/bash
SSL_DIR="/etc/nginx/ssl"
BACKUP_DIR="/etc/nginx/ssl/backup"
# Создаём резервную копию
mkdir -p $BACKUP_DIR
cp $SSL_DIR/server.* $BACKUP_DIR/
# Создаём новый сертификат
openssl req -new -x509 -key $SSL_DIR/server.key -out $SSL_DIR/server.crt -days 365 -subj "/C=RU/ST=Moscow/L=Moscow/O=AutoSSL/CN=localhost"
# Перезагружаем nginx
nginx -s reload
Типичные проблемы и решения
Проблема: "SSL certificate problem: self signed certificate"
Решение: Для curl используй флаг -k
или добавь сертификат в доверенные.
Проблема: "Common Name mismatch"
Решение: Убедись, что CN в сертификате совпадает с доменом в браузере.
Проблема: "Permission denied" при чтении ключа
Решение: Проверь права доступа и SELinux:
# Проверяем права
ls -la /etc/nginx/ssl/
# Исправляем права
chown nginx:nginx /etc/nginx/ssl/server.*
chmod 600 /etc/nginx/ssl/server.key
chmod 644 /etc/nginx/ssl/server.crt
# Проверяем SELinux
setsebool -P httpd_can_network_connect 1
restorecon -R /etc/nginx/ssl/
Альтернативные решения
Кроме OpenSSL есть и другие инструменты:
- mkcert — удобная утилита для создания локальных сертификатов https://github.com/FiloSottile/mkcert
- step-ca — полноценный CA для команды https://smallstep.com/docs/step-ca
- cfssl — инструмент от CloudFlare https://github.com/cloudflare/cfssl
Если планируешь серьёзную работу с SSL, рекомендую изучить эти инструменты.
Интересные факты
- Самоподписанные сертификаты используют ту же криптографию, что и коммерческие — разница только в цепочке доверия
- Chrome планирует полностью заблокировать HTTP к 2024 году
- ECDSA сертификаты в 10 раз быстрее RSA при той же степени защиты
- Можно создать сертификат со сроком действия 100 лет, но браузеры не будут ему доверять
Когда переходить на "настоящие" сертификаты
Если проект растёт и требуется продакшен-готовое решение, рекомендую Let's Encrypt или коммерческие сертификаты. Для хостинга можешь использовать VPS или выделенный сервер с поддержкой автоматической установки сертификатов.
Заключение
Самоподписанные SSL-сертификаты — это простой и быстрый способ добавить HTTPS в разработку и тестирование. Они не подходят для продакшена, но отлично справляются со своими задачами в контролируемых окружениях.
Основные преимущества:
- Быстрота создания и настройки
- Полный контроль над сертификатом
- Нет зависимости от внешних сервисов
- Бесплатность
Используй самоподписанные сертификаты для:
- Локальной разработки
- Тестирования HTTPS функциональности
- Внутренних сервисов
- Обучения и экспериментов
Помни: безопасность — это не только сертификаты, но и правильная настройка SSL/TLS, обновление системы и мониторинг. Самоподписанный сертификат — это первый шаг к безопасному соединению, но не последний.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.