Files
reverse-proxy/docs/letsencrypt-acme.md
PTah 1314eb8010 README: сократить до заголовка и таблицы, вынести инструкции в docs/
Убраны упоминания GitHub; ссылка только на git.kalinamall.ru. Добавлены docs/git.md, docs/haproxy-install.md, docs/letsencrypt-acme.md.
2026-06-01 11:45:01 +10:00

193 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Порт 80 и Let's Encrypt / ACME
Сейчас в `haproxy.cfg` **порт 80 не используется**. Ниже — что иметь в виду, если появится, например, **Ubuntu** во внутренней сети, на которую нужно выпускать сертификаты **Let's Encrypt** с автообновлением.
## Нужен ли для ACME именно порт 80?
**Не всегда.** У Let's Encrypt (протокол **ACME**) есть несколько типов проверки владения доменом:
| Тип | Порт | Комментарий |
|-----|------|-------------|
| **HTTP-01** | **80** (HTTP) | Центр сертификации делает запрос вида `http://ваш-домен/.well-known/acme-challenge/...`. С **интернета** до отвечающего хоста порт **80** должен быть **доступен** (напрямую или через проброс на HAProxy). |
| **DNS-01** | не нужен 80/443 | Запись в DNS; удобно, когда **80 снаружи открывать нельзя** или сертификат для внутреннего имени. |
| **TLS-ALPN-01** | **443** | Проверка по TLS; порт 80 не обязателен. |
Итого: при классическом **Certbot + webroot/standalone** с проверкой **HTTP-01** порт **80** действительно участвует. При **DNS-01** отдельный HTTP на 80 для выпуска не нужен.
Автообновление обычно делают **`certbot renew`** по **systemd timer** или cron — это на стороне машины с Certbot, не в HAProxy.
## Если понадобится HTTP на 80 через этот HAProxy (например, HTTP-01)
1. На **пограничном роутере** разрешить с интернета **TCP 80** на IP хоста с HAProxy (или на тот хост, где будет отвечать ACME).
2. В **`haproxy.cfg`** добавить отдельный **HTTP**-фронтенд на **80** и отправлять только путь проверки на бэкенд с ответом ACME (остальное — редирект на HTTPS, пустой ответ или отказ — по политике).
## Пример: два Ubuntu в LAN и HTTP-01 через один периметровый HAProxy
Допустим, во внутренней сети два сервера **Ubuntu**, для обоих нужны публичные имена и периодическое обновление сертификатов Let's Encrypt по **HTTP-01**:
| Имя (снаружи) | Внутренний IP |
|----------------|-----------------|
| **ubuntu1.kalinamall.ru** | **192.168.160.90** |
| **ubuntu2.kalinamall.ru** | **192.168.160.60** |
**DNS:** записи **A** для `ubuntu1.kalinamall.ru` и `ubuntu2.kalinamall.ru` должны указывать на **тот же публичный IP**, что и для остальных сервисов за HAProxy (чтобы запросы Let's Encrypt пришли на **порт 80** этого хоста).
**На каждой Ubuntu:** нужен **HTTP на порту 80** и каталог под **webroot** Certbot (`/.well-known/acme-challenge/…`). Ниже — пошагово для **nginx** (типичный вариант); в конце — кратко про **Apache**. Если открывать 80 не хотите, используйте **DNS-01** на той же машине (без этого блока).
### Пошагово: nginx + Certbot webroot на Ubuntu
Выполняйте **на каждой** Ubuntu отдельно; подставляйте своё имя (`ubuntu1.kalinamall.ru` или `ubuntu2.kalinamall.ru`).
1. **Установите nginx и certbot**
```bash
sudo apt update
sudo apt install -y nginx certbot
```
2. **Каталог для challenge** (Certbot будет писать сюда файлы, nginx — отдавать):
```bash
sudo mkdir -p /var/www/certbot/.well-known/acme-challenge
sudo chown -R www-data:www-data /var/www/certbot
```
3. **Виртуальный хост только под ACME и имя сервера**
Создайте файл, например `/etc/nginx/sites-available/acme-le.conf` (на одной машине в `server_name` — `ubuntu1.kalinamall.ru`, на другой — `ubuntu2.kalinamall.ru`):
```nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name ubuntu1.kalinamall.ru;
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
default_type "text/plain";
}
location / {
return 404;
}
}
```
4. **Включите сайт и перезапустите nginx**
```bash
sudo ln -sf /etc/nginx/sites-available/acme-le.conf /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
```
Убедитесь, что снаружи (через HAProxy и открытый WAN **80**) до этой машины доходит запрос с правильным **Host** — иначе Let's Encrypt не пройдёт проверку.
5. **Первый выпуск сертификата (webroot)**
Подставьте свой домен и e-mail:
```bash
sudo certbot certonly --webroot -w /var/www/certbot \
-d ubuntu1.kalinamall.ru \
--email admin@example.com --agree-tos --non-interactive
```
При первом запуске можно убрать `--non-interactive`, чтобы согласиться с условиями в диалоге.
**Где лежат файлы и что с ними делать (HTTPS в nginx)**
После успешного `certbot certonly` каталог (симлинки) будет таким:
- **`/etc/letsencrypt/live/ubuntu1.kalinamall.ru/`** — имя совпадает с **первым** `-d` в команде certbot (на второй машине — `ubuntu2...`).
- **`fullchain.pem`** — ваш сертификат **и** цепочка до Let's Encrypt; его указывают в **`ssl_certificate`** (так браузеры доверяют сайту).
- **`privkey.pem`** — закрытый ключ; в **`ssl_certificate_key`**. Файлы в `archive/`, в `live/` — только ссылки; при **`certbot renew`** обновляются именно они, пути в nginx **менять не нужно**.
Добавьте **второй** `server` для **HTTPS** (отдельный файл или тот же `acme-le.conf` ниже блока `:80`), подставив своё имя и корень сайта:
```nginx
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ubuntu1.kalinamall.ru;
ssl_certificate /etc/letsencrypt/live/ubuntu1.kalinamall.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ubuntu1.kalinamall.ru/privkey.pem;
# Рекомендуемые параметры TLS (если пакет certbot их положил):
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
```
Проверка и применение:
```bash
sudo nginx -t && sudo systemctl reload nginx
```
Если **443** с интернета идёт **на эту же** Ubuntu (напрямую или отдельным пробросом с маршрутизатора), снаружи откройте **TCP 443** до неё. Если HTTPS терминирует только **HAProxy**, а до Ubuntu — снова прокси, то сертификат Let's Encrypt на Ubuntu нужен **той службе**, которая реально открывает **TLS** на этой машине (или выпускайте сертификат на том узле, где крутится HTTPS).
**Редирект HTTP → HTTPS на :80 (по желанию, после того как HTTPS завёлся):** в блоке `server` на **порту 80** оставьте **`location ^~ /.well-known/acme-challenge/`** как есть, а вместо `return 404` для **`location /`** поставьте **`return 301 https://$host$request_uri;`** — обновление сертификата по-прежнему идёт по **HTTP** на путь **`.well-known`**, остальное уходит на **https://**.
6. **Проверка автообновления**
```bash
sudo systemctl enable --now certbot.timer
sudo certbot renew --dry-run
```
7. **Перезагрузка nginx после успешного renew**
Создайте скрипт и сделайте его исполняемым:
```bash
sudo install -d /etc/letsencrypt/renewal-hooks/deploy
echo 'systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx.sh
```
Таймер **`certbot.timer`** по расписанию вызывает `certbot renew`; при обновлении сертификата выполняются hook'и из `renewal-hooks/deploy`.
### Кратко: Apache вместо nginx
1. `sudo apt install -y apache2 certbot python3-certbot-apache` (или только `certbot` и webroot без плагина apache).
2. Корень для challenge: например `sudo mkdir -p /var/www/certbot/.well-known/acme-challenge` и в виртуальном хосте на **:80** для вашего `ServerName` — `Alias /.well-known/acme-challenge /var/www/certbot/.well-known/acme-challenge` и доступ `Require all granted` для этого каталога.
3. `sudo apachectl configtest && sudo systemctl reload apache2`
4. `sudo certbot certonly --webroot -w /var/www/certbot -d ubuntu1.kalinamall.ru` (и аналогично для второго имени на второй машине).
5. Таймер **`certbot.timer`** и при необходимости hook с `systemctl reload apache2`.
## Конфигурация HAProxy для маршрутизации ACME
На HAProxy — один фронтенд на **80**, маршрутизация по заголовку **Host** + путь ACME на разные бэкенды:
```text
frontend fe_http
bind *:80
mode http
option httplog
acl path_acme path_beg /.well-known/acme-challenge/
acl host_u1 hdr(host) -i ubuntu1.kalinamall.ru
acl host_u2 hdr(host) -i ubuntu2.kalinamall.ru
use_backend be_acme_u1 if path_acme host_u1
use_backend be_acme_u2 if path_acme host_u2
http-request deny if !path_acme
backend be_acme_u1
mode http
server u1 192.168.160.90:80 check
backend be_acme_u2
mode http
server u2 192.168.160.60:80 check
```
Let's Encrypt при проверке обращается к **`http://ubuntu1.kalinamall.ru/.well-known/...`** или **`http://ubuntu2...`** — HAProxy по **Host** пересылает запрос на нужный внутренний **:80**, где локальный веб-сервер отдаёт файлы challenge.
Варианты без проброса HTTP на две машины: на каждой Ubuntu **DNS-01** (порт 80 на периметре тогда не обязателен для этих сертификатов); либо **TLS-ALPN-01** по **443** (потребуется уже другая схема на HAProxy, не этот пример).
После добавления `bind :80` откройте **TCP 80** на фаерволе (см. [haproxy-install.md](haproxy-install.md)) и выполните `sudo haproxy -c -f /etc/haproxy/haproxy.cfg`.