1314eb8010
Убраны упоминания GitHub; ссылка только на git.kalinamall.ru. Добавлены docs/git.md, docs/haproxy-install.md, docs/letsencrypt-acme.md.
193 lines
12 KiB
Markdown
193 lines
12 KiB
Markdown
# Порт 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`.
|