544eda2640
Made-with: Cursor
176 lines
7.4 KiB
Markdown
176 lines
7.4 KiB
Markdown
# Nginx и HTTPS на сервере с Gitea (kalinamall.ru)
|
||
|
||
В схеме **[`docs/haproxy-kalinamall.cfg`](haproxy-kalinamall.cfg)** и **[`docs/haproxy-kalinamall.md`](haproxy-kalinamall.md)** периметровый HAProxy пересылает TCP **`:443`** на узел Gitea (**`192.168.160.129:443`**). Контейнер Gitea по умолчанию слушает только **HTTP `:3000`**, поэтому на самом сервере нужен **TLS-терминатор на `:443`** — здесь описан **nginx** перед контейнером.
|
||
|
||
Цепочка:
|
||
|
||
```text
|
||
Клиент → (опционально HAProxy TCP+SNI) → nginx :443 (TLS, wildcard) → HTTP → 127.0.0.1:3000 → Gitea
|
||
```
|
||
|
||
## 1. Предварительные условия
|
||
|
||
- Gitea в Docker уже слушает **`127.0.0.1:3000`** (или `0.0.0.0:3000`).
|
||
- Есть файлы сертификата **wildcard `*.kalinamall.ru`** (цепочка + ключ), выданные GlobalSign или экспортированные в PEM.
|
||
|
||
На Ubuntu 24.04:
|
||
|
||
```bash
|
||
sudo apt-get update
|
||
sudo apt-get install -y nginx
|
||
```
|
||
|
||
## 2. Каталог для сертификатов и права
|
||
|
||
Создайте каталог и положите туда **fullchain** (или сертификат + цепочка в одном PEM) и **приватный ключ**. Имена файлов могут быть любыми — ниже они должны совпасть с путями в конфиге nginx.
|
||
|
||
Пример:
|
||
|
||
```bash
|
||
sudo mkdir -p /etc/nginx/ssl/kalinamall
|
||
sudo install -m 0644 /путь/к/fullchain.pem /etc/nginx/ssl/kalinamall/git.kalinamall.ru-fullchain.pem
|
||
sudo install -m 0600 /путь/к/privkey.pem /etc/nginx/ssl/kalinamall/git.kalinamall.ru.key
|
||
sudo chown root:root /etc/nginx/ssl/kalinamall/*
|
||
```
|
||
|
||
### Сертификат в формате PFX (`.pfx` / `.p12`)
|
||
|
||
Nginx **не** читает PFX напрямую в `ssl_certificate` / `ssl_certificate_key` — нужны **PEM**: отдельно **цепочка** (сервер + промежуточные CA) и **закрытый ключ**. PFX — контейнер, из него извлекают OpenSSL (пароль к PFX введёте по запросу):
|
||
|
||
```bash
|
||
# Закрытый ключ (права только root)
|
||
openssl pkcs12 -in wildcard.pfx -nocerts -nodes -out git.kalinamall.ru.key
|
||
|
||
# Сертификаты из контейнера (серверный + при необходимости цепочку соберите в один fullchain ниже)
|
||
openssl pkcs12 -in wildcard.pfx -clcerts -nokeys -out cert.pem
|
||
openssl pkcs12 -in wildcard.pfx -cacerts -nokeys -out chain.pem 2>/dev/null || true
|
||
```
|
||
|
||
Часто для **`ssl_certificate`** нужен один файл «сервер + промежуточные»:
|
||
|
||
```bash
|
||
cat cert.pem chain.pem > git.kalinamall.ru-fullchain.pem
|
||
sudo chmod 0600 git.kalinamall.ru.key
|
||
sudo chmod 0644 git.kalinamall.ru-fullchain.pem
|
||
```
|
||
|
||
На OpenSSL 3 старые PFX иногда требуют флаг **`-legacy`** к `pkcs12`. При ошибках расшифровки проверьте пароль и точное имя алиаса в PFX (`openssl pkcs12 -in wildcard.pfx -info -noout`).
|
||
|
||
Пути к получившимся **`…-fullchain.pem`** и **`…key`** подставьте в конфиг nginx.
|
||
|
||
## 3. Map для WebSocket
|
||
|
||
Gitea в браузере использует WebSocket. Директива **`map`** должна быть в контексте **`http {}`** один раз на весь nginx.
|
||
|
||
Скопируйте пример из репозитория:
|
||
|
||
- [`nginx/conf.d-map-websocket.conf.example`](../nginx/conf.d-map-websocket.conf.example)
|
||
|
||
```bash
|
||
sudo cp /opt/owngit/nginx/conf.d-map-websocket.conf.example /etc/nginx/conf.d/zz-map-websocket.conf
|
||
```
|
||
|
||
(Путь `/opt/owngit` замените на каталог вашего клона `owngit`.)
|
||
|
||
Либо вставьте содержимое файла вручную в `/etc/nginx/nginx.conf` внутрь блока `http { … }`.
|
||
|
||
## 4. Виртуальный хост
|
||
|
||
Скопируйте и отредактируйте пути к PEM:
|
||
|
||
- [`nginx/git.kalinamall.ru.conf.example`](../nginx/git.kalinamall.ru.conf.example)
|
||
|
||
```bash
|
||
sudo cp /opt/owngit/nginx/git.kalinamall.ru.conf.example /etc/nginx/sites-available/git.kalinamall.ru
|
||
sudo nano /etc/nginx/sites-available/git.kalinamall.ru # ssl_certificate / ssl_certificate_key
|
||
sudo ln -sf /etc/nginx/sites-available/git.kalinamall.ru /etc/nginx/sites-enabled/
|
||
```
|
||
|
||
Уберите или отключите дефолтный сайт, если он мешает:
|
||
|
||
```bash
|
||
sudo rm -f /etc/nginx/sites-enabled/default
|
||
```
|
||
|
||
Проверка и перезагрузка:
|
||
|
||
```bash
|
||
sudo nginx -t
|
||
sudo systemctl reload nginx
|
||
sudo ss -tlnp | grep ':443'
|
||
```
|
||
|
||
Должен появиться **`LISTEN`** на **`0.0.0.0:443`** (nginx).
|
||
|
||
## 5. Фаервол
|
||
|
||
При использовании UFW:
|
||
|
||
```bash
|
||
sudo ufw allow 443/tcp comment 'nginx Gitea HTTPS'
|
||
sudo ufw status verbose
|
||
```
|
||
|
||
(Порт **2222** для Git по SSH открывайте по вашей политике — на периметре его обычно публикует HAProxy.)
|
||
|
||
## 6. Gitea: `app.ini`
|
||
|
||
Контейнер по-прежнему отдаёт **HTTP** на `:3000`. Снаружи пользователи ходят по **HTTPS**, поэтому:
|
||
|
||
```ini
|
||
[server]
|
||
ROOT_URL = https://git.kalinamall.ru/
|
||
PROTOCOL = http
|
||
DOMAIN = git.kalinamall.ru
|
||
```
|
||
|
||
Убедитесь, что в **`[server]`** не задан лишний порт в URL, если публикуете стандартный **443**. После правок:
|
||
|
||
```bash
|
||
cd /opt/gitea && sudo docker compose restart gitea
|
||
```
|
||
|
||
Подробнее про секреты — в [README](../README.md) и в `gitea/app.ini.example`.
|
||
|
||
## 7. Проверки
|
||
|
||
На сервере Gitea:
|
||
|
||
```bash
|
||
curl -sS -o /dev/null -w "%{http_code}\n" https://git.kalinamall.ru/api/healthz
|
||
```
|
||
|
||
Ожидается **200**. Локально без nginx (только контейнер):
|
||
|
||
```bash
|
||
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/api/healthz
|
||
```
|
||
|
||
С другой машины в LAN (DNS на **192.168.160.129** или через HAProxy):
|
||
|
||
```bash
|
||
curl -v https://git.kalinamall.ru/api/healthz
|
||
```
|
||
|
||
## 8. Связка с периметровым HAProxy
|
||
|
||
- DNS **`git.kalinamall.ru`** снаружи → публичный IP **HAProxy**; HAProxy по SNI шлёт TCP на **`192.168.160.129:443`** → **nginx** завершает TLS и шлёт HTTP на **3000**.
|
||
- Внутри LAN можно использовать **Split DNS**: то же имя → **192.168.160.129** или → LAN IP HAProxy — согласуйте с тем, где должен приниматься первый TLS-hop.
|
||
|
||
Если nginx и Gitea стоят корректно, ошибка **`connection refused` на :443** до nginx исчезнет.
|
||
|
||
## 9. Опционально: редирект HTTP → HTTPS
|
||
|
||
Если нужен отдельный сервер на порту **80** только для редиректа:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
listen [::]:80;
|
||
server_name git.kalinamall.ru;
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
```
|
||
|
||
На периметре **80** может занимать другой сервис — включайте только если не конфликтует.
|