Предусловия

Нужен сервер с Ubuntu/Debian, доменное имя, DNS A-запись которого уже смотрит на IP сервера. Без последнего certbot не получит сертификат — проверка идёт по HTTP на 80-м порту. Если DNS ещё не обновился, подождите — смысла идти дальше нет.

Установка nginx и certbot

apt update && apt install -y nginx certbot python3-certbot-nginx

После установки nginx автоматически запускается. Проверяем:

systemctl status nginx
# Должно быть: active (running)

# Если не запущен:
systemctl start nginx
systemctl enable nginx

Конфиг для статического сайта

Создаём конфиг в /etc/nginx/sites-available/example.com:

server {
    listen 80;
    server_name example.com www.example.com;

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

    # Статические файлы
    location / {
        try_files $uri $uri/ $uri.html =404;
    }

    # Кэширование статики
    location ~* \.(css|js|png|jpg|jpeg|svg|ico|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Запрет лишнего
    location ~ /\. { deny all; }

    # Gzip
    gzip on;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1024;
}

Включаем сайт и проверяем конфиг:

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t
# nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx

Получение SSL-сертификата

certbot --nginx -d example.com -d www.example.com

Certbot сам найдёт конфиг, проверит домен, получит сертификат и пропишет HTTPS-блок. Единственный вопрос — нужно ли перенаправлять HTTP на HTTPS (выбираем «да»). После этого конфиг выглядит примерно так:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

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

    location / {
        try_files $uri $uri/ $uri.html =404;
    }
    # ... остальные location
}

Конфиг для reverse proxy

Если за nginx стоит приложение (FastAPI, Node, Gunicorn и т.д.) на каком-то порту:

upstream app {
    server 127.0.0.1:8000;
    # Можно добавить несколько серверов для балансировки
}

server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;

    location / {
        proxy_pass http://app;
        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;

        # Для WebSocket:
        # proxy_http_version 1.1;
        # proxy_set_header Upgrade $http_upgrade;
        # proxy_set_header Connection "upgrade";

        # Таймауты
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Автообновление сертификата

Certbot при установке добавляет systemd timer или cron задачу автоматически. Проверяем:

# Проверить таймер systemd
systemctl status certbot.timer

# Или проверить cron
cat /etc/cron.d/certbot

# Тест обновления (без реального обновления)
certbot renew --dry-run

Если dry-run прошёл без ошибок — всё настроено. Сертификаты обновляются автоматически за 30 дней до истечения. Следить не нужно.

Полезные команды

# Список сертификатов
certbot certificates

# Принудительное обновление
certbot renew --force-renewal

# Проверить конфиг nginx
nginx -t

# Перезагрузить nginx без прерывания соединений
nginx -s reload
# или
systemctl reload nginx

# Посмотреть ошибки
tail -n 50 /var/log/nginx/error.log

# Посмотреть access log
tail -f /var/log/nginx/access.log

Быстрый security-минимум

Что стоит добавить в конфиг для базовой безопасности:

server {
    # ...

    # Скрыть версию nginx
    server_tokens off;

    # Security headers
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "geolocation=(), microphone=()" always;

    # Ограничение размера тела запроса
    client_max_body_size 10M;

    # Rate limiting (определить в http блоке)
    # limit_req zone=one burst=10 nodelay;
}

Rate limiting определяется в /etc/nginx/nginx.conf внутри блока http:

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    # ...
}

Итог

Весь процесс с чистого сервера до работающего HTTPS занимает 10–15 минут, если DNS уже настроен. Certbot берёт на себя всё, что связано с сертификатами и их обновлением. Nginx конфиг для большинства задач не нужно усложнять — показанные блоки покрывают 95% случаев.