Appearance
Local HTTPS setup (mkcert)
Последнее обновление: 2026-04-07 (DEV-305 side-quest)
TL;DR
Локальный dev-сервер фронта работает на https://localhost:3000 через mkcert. Это обязательный onboarding-шаг на каждой машине — иначе npm run dev упадёт с «file not found» на сертификатах, а без HTTPS в Safari перестаёт работать авторизация (PHP-сессия теряется между запросами, CSRF ротируется на каждую перезагрузку).
Установка (один раз на машину)
bash
brew install mkcert nss
mkcert -install # добавит локальный CA в system keychain (спросит пароль)
cd path/to/partizap-frontend
mkcert localhost 127.0.0.1 ::1 # создаст localhost+2.pem и localhost+2-key.pemПроверка:
bash
ls localhost+2*.pem
# localhost+2-key.pem localhost+2.pem
npm run dev
# ➜ Local: https://localhost:3000/Файлы сертификатов уже в .gitignore (*.pem). Коммитить их нельзя — они привязаны к локальному CA каждого разработчика.
Почему это обязательно
Симптомы без HTTPS
- Safari: после логина страница выглядит как авторизованная, но при любом reload авторизация «забывается». В DevTools → Storage → Cookies нет
PARTIZAP_SESSION.CSRF_TOKENменяется на каждый запросGET /health. - Chrome / Firefox: работает (до поры до времени), поэтому баг не виден пока не откроешь сайт в Safari.
Root cause
- Фронт на
http://localhost:3000проксирует/api/*наhttps://dev.partizap.ru/api/*черезnitro.devProxy(см.nuxt.config.ts). - PHP-бэкенд выставляет
PARTIZAP_SESSIONcookie с атрибутамиHttpOnly; Secure; SameSite=Lax(session.cookie_secure=1в проде). cookieDomainRewriteв devProxy убираетDomain=dev.partizap.ru, чтобы кука легла на host-onlylocalhost. Но атрибутSecureостаётся.- Chrome 89+ трактует
http://localhostкак secure context и принимаетSecure-куки на HTTP. - Safari этого не делает (либо делает с оговорками, меняющимися от версии и настроек «Prevent cross-site tracking»). Кука отбрасывается сразу при получении.
- На следующем запросе
GET /healthизapp/plugins/auth.ts → authStore.initSession()бэкенд не видитPARTIZAP_SESSIONв Cookie-хедере, стартует новую PHP-сессию и выдаёт новый CSRF-токен. - Пользователь видит «ротацию» CSRF и разлогинивание.
Переключение локалки на HTTPS делает localhost secure-контекстом со всех сторон — Safari перестаёт выкидывать Secure-куки, сессия живёт между reload'ами.
Конфигурация в коде
nuxt.config.ts
ts
devServer: {
https: {
key: './localhost+2-key.pem',
cert: './localhost+2.pem',
},
},Имена файлов фиксированы под вывод mkcert localhost 127.0.0.1 ::1 (суффикс +2 = два дополнительных SAN). Если генерируешь через mkcert localhost (один host), файлы будут localhost.pem / localhost-key.pem — тогда поправь пути в nuxt.config.ts.
.gitignore
# Local HTTPS certificates (mkcert)
*.pemTroubleshooting
npm run dev падает с ENOENT: localhost+2.pem
Не сделан onboarding-шаг. Прогони блок из раздела «Установка».
Safari показывает «Не удаётся установить защищённое соединение»
mkcert -install не прошёл или CA был удалён из keychain. Перезапусти:
bash
mkcert -installЕсли Firefox всё ещё ругается, нужен nss:
bash
brew install nss
mkcert -installПорт 3000 занят, Nuxt поднимается на 3001
Проверь, что не осталось зависшего nuxt dev от прошлой сессии:
bash
lsof -iTCP:3000 -sTCP:LISTEN
kill <PID>NODE_TLS_REJECT_UNAUTHORIZED=0 warning в логах Nuxt
Это общий Nuxt-ворнинг про devProxy-target (HTTPS-upstream на dev.partizap.ru), не про наш локальный cert. Игнорировать — у dev-стенда нормальный публичный сертификат.
Баг воспроизводится на проде (dev.partizap.ru / partizap.ru)
Это уже не local-HTTPS проблема — фронт и бэк там на одном HTTPS-домене, куки работают нативно. Если CSRF ротируется или сессия теряется на проде в Safari, смотреть в сторону:
- Настроек
session.cookie_samesiteв PHP - ITP (Safari удаляет first-party cookies после 7 дней неактивности)
- Конфликтов с
SameSite=None/Partitioned(CHIPS)
Удаление / откат
Если нужно удалить локальный CA и вернуть macOS в исходное состояние:
bash
mkcert -uninstall # снимает CA из keychain и NSS
rm localhost+2*.pem # в проектеПосле этого надо вернуть devServer.https в nuxt.config.ts или откатить коммит.
Связанные артефакты
- Коммит:
27d5bcb—chore: enable local HTTPS dev server via mkcert(веткаchore/local-https-mkcert) - Проект:
partizap-frontend - Конфиг:
nuxt.config.ts → devServer.https - Игнор:
.gitignore → *.pem - Плагин, зависящий от стабильной сессии:
app/plugins/auth.ts(дёргаетGET /healthиGET /auth/meпри старте) - Клиент, читающий
CSRF_TOKENиз cookie:app/shared/api/client.ts