How-to: получить доверенный HTTPS на
*.localhostбез запуска тяжелых прокси в каждом проекте и без изменения скриптов разработки.
В современной веб-разработке многие API и возможности браузера требуют безопасного контекста (HTTPS) даже при локальной разработке:
- Безопасные Cookie (с атрибутами
Secure; SameSite=None) - WebCrypto API, Service Workers, WebAuthn/Passkeys, Geolocation
- Мультидоменная маршрутизация (например,
app.localhostиapi.localhostс разделением кук) - Внешние OAuth-интеграции (Telegram WebApp, Google OAuth, VK ID), требующие HTTPS redirect URL
Pegas решает эту задачу с помощью единого общего Docker Gateway (pegas-gateway) и прозрачной привязки хостовых портов (pegas connect).
- Не туннель наружу.
*.localhostрезолвится только на вашей машине: ни публичного адреса, ни внешнего трафика. Если нужен URL из интернета (https://xyz.ngrok.io,*.ts.net) — это задача ngrok / cloudflared / Tailscale Funnel, и Pegas их не заменяет (но и не мешает). - Не прокси внутри проекта. Ничего не запускается per-project: один gateway на машину обслуживает все домены.
- Не правка dev-скриптов. Ни
--httpsфлагов, ни конфигов vite/webpack: приложение слушает обычный HTTP, TLS терминируется снаружи. - Не root. Caddy user-space, порты
:80/:443без sudo (см.docs/explanation/architecture.md).
| Подход | Доверенный сертификат | URL из интернета | Налог на проект |
|---|---|---|---|
vite --https, node --experimental-https |
самоподписанный → предупреждение браузера | нет | флаг/конфиг в каждом проекте |
| mkcert | да (локальный CA) | нет | сертификаты вручную на каждый домен, прокси поднимать самому |
| Traefik + Docker socket | да | нет | /var/run/docker.sock внутри прокси = root-эквивалент |
| nginx + свои конфиги | вручную | нет | шаблон на сайт, reload при изменениях |
| ngrok / cloudflared / tailscale funnel | да (публичный CA) | да | внешний сервис, аккаунт, трафик через чужую сеть |
Pegas (up / serve / connect) |
да (локальный Root CA, один раз) | нет — по дизайну | ноль: один бинарник, один общий gateway |
Для того чтобы браузеры и системные утилиты отображали валидный зеленый замок и доверяли локальным сертификатам без предупреждений, достаточно один раз выполнить на машине:
npx pegas ca installКоманда генерирует локальный Root CA Pegas (~/.pegas/ca/root.crt), регистрирует его в системном хранилище доверия ОС и браузеров. Удалить Root CA можно в любой момент командой npx pegas ca remove.
| Платформа | Хранилище | Что получает доверие |
|---|---|---|
| Linux (Debian/Ubuntu/Alpine) | /usr/local/share/ca-certificates/pegas-root-ca.crt + update-ca-certificates |
curl, git, openssl, системные утилиты, Chrome/Chromium |
| Linux (RHEL/Fedora/CentOS) | /etc/pki/ca-trust/source/anchors/pegas-root-ca.crt + update-ca-trust |
то же |
| macOS | System.keychain (security add-trusted-cert) |
Safari, Chrome, системные фреймворки |
| Windows | User Root Store (certutil -user, без UAC) |
Edge, Chrome, системные API |
| WSL | Обе системы: Windows user store + Linux bundle | Браузеры в Windows + curl/node/git внутри WSL |
Некоторые среды используют собственные списки доверенных сертификатов:
- Firefox на Linux: использует собственный профиль NSS. Сертификат можно добавить через настройки браузера (Настройки → Приватность → Сертификаты → Импорт) или утилитой
certutil:certutil -A -t "C,," -n pegas -i ~/.pegas/ca/root.crt -d ~/.pki/nssdb
- Node.js / Bun: используют встроенный список CA. Для межсервисных запросов по HTTPS передайте переменную окружения:
export NODE_EXTRA_CA_CERTS="$HOME/.pegas/ca/root.crt"
- Python (requests / httpx):
export REQUESTS_CA_BUNDLE="$HOME/.pegas/ca/root.crt"
Вместо запуска изолированного Caddy-прокси в каждом проекте, Pegas использует один глобальный Gateway-контейнер (pegas-gateway), который слушает порты 80 и 443 на машине разработчика.
flowchart TD
Browser["Браузер / curl (https://web.my-app.localhost)"]
Gateway["Общий Docker Gateway (pegas-gateway на портах 80 / 443)"]
HostServer["Локальный dev-сервер на хосте (например, localhost:3000)"]
DockerServices["Контейнеры БД / Redis (опционально)"]
Browser -->|HTTPS :443| Gateway
Gateway -->|reverse_proxy| HostServer
HostServer -.->|TCP| DockerServices
pegas connectсчитывает маршруты сценарияdevelopmentиз файлаpegas.json.- Если общий Gateway ещё не запущен, Pegas поднимает его в Docker.
connectрегистрирует маршруты всех сервисов сценария: host-сервисы — наhost.docker.internal:<порт>, docker-сервисы — на scoped-алиас вpegas-network. Контейнеры он не запускает.- Docker-сервисы сценария поднимает
pegas deploy -s development; разработчик запускает host-сервисы любимым нативным инструментом (bun run dev,npm run dev,cargo runи т.д.). - Браузер открывает
https://web.my-app.localhostс валидным сертификатом без указания портов. pegas disconnect -s developmentудаляет маршруты сценария из Gateway при завершении работы;downостанавливает контейнеры, но маршруты не снимает.
В каталоге проекта выполните:
npx pegas connectКоманда автоматически:
- Проверит наличие
pegas.jsonи сценарияdevelopment - Поднимет или обновит общий Gateway-контейнер
- Зарегистрирует домены (например,
web.my-app.localhost) на соответствующий локальный порт
Запустите dev-сервер стандартной командой проекта:
npm run dev
# или
bun run dev
# или
pnpm devDev-сервер работает нативно на хосте со стандартным Hot Module Replacement (HMR) и доступом к IDE отладчикам.
Когда разработка завершена или вы переключаетесь на другую задачу:
npx pegas disconnectGateway освободит маршруты текущего проекта, не затрагивая маршруты других активных проектов.
Маршруты локальной разработки настраиваются в сценарии development:
{
"name": "my-project",
"scenarios": {
"development": {
"routes": [
{
"host": "web.my-app.localhost",
"to": "host.docker.internal:3000"
},
{
"host": "api.my-app.localhost",
"to": "host.docker.internal:4000"
}
]
}
}
}- Зона
*.localhostпо стандарту RFC 6761 автоматически резолвится всеми современными ОС и браузерами в127.0.0.1без необходимости редактировать/etc/hosts. - Директива
toуказывает наhost.docker.internal:<порт>, благодаря чему контейнер Caddy перенаправляет запросы обратно на хост разработчика.