Docker-образи serversideup/php, що розробляються в репозиторії serversideup/docker-php, отримали версію v4.6.0-beta1 зі змінною CADDY_ACME_PROFILE, яка дозволяє вибрати профіль shortlived (короткотривалий) від Let's Encrypt. Це єдиний профіль, під яким Let's Encrypt видає сертифікати для IP-адрес, тому FrankenPHP-контейнер, доступний лише по IP, тепер може обслуговувати справжній HTTPS без жодного DNS.
Jay Rogers із Server Side Up анонсував цю можливість разом із бета-версією:
Я працював над цим досить довго і нарешті налаштував:
🔐 HTTPS для IP-адрес
Це величезний прорив для тих, хто розгортає власні сервери. Не потрібен DNS. Все працює на Let's Encrypt + FrankenPHP.
Для кого це корисно
Ті, хто розгортає власні сервери (self-hosters), - найочевидніший випадок використання, але та сама проблема зустрічається в багатьох командних сетапах: staging-сервер, піднятий на тиждень; внутрішнє API за VPN; демонстраційний сервер для клієнта; дашборд черг на droplet. Усі вони можуть бути доступні по IP задовго до того, як хтось вирішить питання з hostname. До цього моменту це означало самопідписаний сертифікат із попередженням браузера або reverse proxy з реальним сертифікатом.
Let's Encrypt зробив загальнодоступними 6-денні сертифікати та сертифікати для IP-адрес у січні. Caddy реалізує вибір профілю сертифікатів та ідентифікатори IP, а FrankenPHP вбудовує Caddy (наразі v2.11.4). Ця бета-версія додає змінну оточення та Caddyfile-сніпети, які Caddy імпортує залежно від її значення.
Як працює короткотривалий профіль
CADDY_ACME_PROFILE за замовчуванням має значення off і приймає shortlived, tlsserver або classic. Встановіть значення shortlived, і Caddy запитуватиме сертифікати терміном дії 160 годин (трохи менше семи днів), оновлюючи їх кожні два дні.
Такий термін дії відповідає визначенню Short-Lived Subscriber Certificate від CA/Browser Forum. Згідно з документацією профілів Let's Encrypt, такі сертифікати «не повинні містити інформацію про відкликання». Однак профіль shortlived все ще вказує на certificate revocation list (CRL) - опублікований запис сертифікатів, які центр сертифікації анулював достроково, і це може змінитися. За такого терміну дії відкликання має менше значення, оскільки скомпрометований ключ перестає бути корисним через дні, а не місяці.
Встановлення змінної записує невеликий Caddyfile-сніпет у конфігурацію:
cert_issuer acme {
profile shortlived
}
Let's Encrypt вимагає той самий профіль для сертифікатів IP-адрес, тому обидві функції з'явилися в одній змінній. Встановлення будь-якого профілю для Let's Encrypt прибирає резервний варіант ZeroSSL, який образи інакше зберігають. Оновлення кожні два дні також залишає менше запасу, якщо контейнер втратить вихідний доступ до ACME API Let's Encrypt - інтерфейсу, який Caddy використовує для запиту та оновлення сертифікатів. Після зміни файрволу, яка блокує egress, у вас є чотири з половиною дні, щоб помітити проблему до закінчення терміну дії сертифіката, тоді як 90-денний сертифікат залишив би вам тижні.
Налаштування
Функція доступна лише в бета-тегах, тому закріпіть образ на бета-версії, а не на стабільному тезі 8.4-frankenphp. Документація пропонує Docker Compose конфігурацію, близьку до цієї:
services:
php:
image: serversideup/php:8.4-frankenphp-v4.6.0-beta1
ports:
- "80:8080"
- "443:8443"
volumes:
- caddy-config:/config
- caddy-data:/data
environment:
SSL_MODE: "full"
CADDY_AUTO_HTTPS: "on"
CADDY_ACME_PROFILE: "shortlived"
CADDY_HTTPS_SERVER_ADDRESS: "https://203.0.113.10"
CADDY_GLOBAL_OPTIONS: "default_sni example.com"
volumes:
caddy-config:
caddy-data:
CADDY_AUTO_HTTPS вмикає автоматичний HTTPS у Caddy; за замовчуванням він вимкнений. SSL_MODE: "full" обслуговує застосунок через HTTPS і надсилає HTTP-трафік туди з кодом 308. CADDY_HTTPS_SERVER_ADDRESS - сюди вказується IP-адреса. Контейнер слухає на портах 8080 і 8443, оскільки працює без привілеїв; звідси маппінг портів, і обидва мають бути доступні з інтернету, щоб ACME-челендж пройшов успішно.
Браузер, відкриваючи TLS-з'єднання, зазвичай оголошує hostname, який він запитує - поле під назвою Server Name Indication (SNI), і саме так сервер із кількома сертифікатами вибирає потрібний. Клієнт, що підключається до IP-адреси, не надсилає SNI, оскільки немає імені для відправки, тому Caddy нічого не має для зіставлення з сертифікатом. CADDY_GLOBAL_OPTIONS: "default_sni example.com" надає резервну ідентичність для таких з'єднань.
Підтримка IPv6 та обережності
Якщо вам потрібно це через IPv6, протестуйте перед покладанням на це. Caddy виправив обробку IPv6 для IP-сертифікатів пізніше за підтримку IPv4, у issue #7399, який закрили в квітні. Caddy v2.11.4 вийшов після цього виправлення, тому поточні образи мають його, але IPv4 працює довше.
Також змонтуйте /config і /data на volumes. Сертифікати та стан ACME-акаунта зберігаються там, і контейнер, що втрачає їх при кожному перезапуску, запитуватиме нові сертифікати при кожному перезапуску. Let's Encrypt дозволяє п'ять сертифікатів для ідентичного набору ідентифікаторів кожні сім днів, поповнюючи один кожні 34 години, тому кілька редеплоїв можуть вичерпати тиждень.
Інші можливості v4.6.0-beta1
В інших частинах v4.6.0-beta1 змінна TRUSTED_PROXY тепер поводиться однаково для FrankenPHP, NGINX та Apache, тому request()->ip() повертає відвідувача, а не проксі, незалежно від варіанта, на якому працює застосунок. Вона приймає cloudflare (за замовчуванням), sucuri, local або off, і кожне значення, крім off, довіряє внутрішнім діапазонам Docker поряд із CDN, тому робота за Cloudflare та Traefik-контейнером одночасно не потребує додаткової конфігурації. FrankenPHP також постачається з директорією caddyfile-global.d, куди ви можете додавати власну глобальну конфігурацію.
Laravel Nightwatch включає скрипт healthcheck-nightwatch, що виконує php artisan nightwatch:status, тому ви можете направити HEALTHCHECK контейнера на агента. А AUTORUN_LARAVEL_SKIP_IF_NOT_FOUND дозволяє контейнеру з AUTORUN_ENABLED=true коректно завершитися, коли Laravel ще немає, наприклад, перед першим composer install, замість помилки.
v4.6.0-beta1 позначено як prerelease, тому тримайте його подалі від того, що ви не можете дозволити собі зламати, поки пробуєте IP-сертифікати. Повні примітки - на сторінці релізу v4.6.0-beta1, а налаштування задокументовано в розділі configuring SSL документації Server Side Up. Якщо ви давно не дивилися на сам FrankenPHP, ми раніше цього року писали про FrankenPHP v1.11.2, а ще раніше - про підтримку FrankenPHP у Laravel Octane.