В смысле без этих ваших проксей - а то ишь, чего удумали! Если серьезно, основная проблема здесь с TLS, и даже не столько TLS, сколько с автоматизацией получения и обновления сертификатов Let's Encrypt. Вооружившись моим образом Lighttpd для Docker в варианте с s6-overlay, настроим все в лучшем виде. Останется, как говорится, просто добавить воды.

Воду я не просто так упомянул: вместо certbot мы воспользуемся скриптом dehydrated. Причина? TLS-ALPN-01 похоже ботом до сих пор не поддерживается, а HTTP-01 настраивать как-то не очень интересно – я бы сделал безусловный редирект http → https.

Контекст

Изначально я предполагал использовать мои образы в паре с Traefik, но недостатком такого варианта можно считать некоторую громоздкость программы, да и если изолировать сокет Докера, получается не самая простая конфигурация. Затем я попытался переложить вопрос сертификации на HAProxy, но и там в версии 3.2 не все гладко: для полной автоматизации пришлось прибегнуть к s6-overlay. Почему бы в таком случае не решить задачу с его помощью целиком, учитывая способность работы Lighttpd по протоколу HTTP/2? Справедливости ради, на момент публикации HTTP/3 в веб-сервер так и не завезли, что все же может повлиять на выбор схемы с обратным прокси с поддержкой такового.

Итак, у нас есть образ веб-сервера Lighttpd поверх PHP-FPM, и все это приправлено «слоеной» системой инициализации. Я специально решил разработать пример уже после внедрения этого самого оверлея, чтобы получилось законченное решение в рамках одного контейнера: нам потребуется и «снайпер» (oneshot) на этапе инициализации, и длительный процесс (longrun) для перевыпуска (продления) сертификатов.

Примечание. Еще я ждал выхода очередного релиза PHP, чтобы перекомпилировать Lighttpd с поддержкой OpenSSL. Минимальный тег – 8.4.14-lighttpd-1.4.82-s6-trixie.

Для успешного преодоления испытания TLS-ALPN-01 сайт должен быть доступен по https. Здесь возникает фундаментальная проблема курицы и яйца – вовсе без сертификата Lighttpd (как и HAProxy) не запустится, а без веб-сервера некому слушать 443-й порт. Следовательно, на этапе инициализации контейнера, если у нас нет никакого сертификата, нужно сгенерировать самоподписанный и затем на его основании получить нормальный. Второе следствие – на локальной виртуалке уже особо не поработаешь, нужен VPS/VDS с указывающим на него доменом.

Для продления сертификатов скрипт не только должен вызываться периодически, но и посылать SIGUSR1 процессу lighttpd для обновления конфигурации (то есть чтобы загрузить новые сертификаты). Кто-то может возразить, что Lighttpd версии 1.4.78 и выше может сам перечитывать сертификаты благодаря флагу "ssl.refresh-certs" => "enable". На мой взгляд недостаток метода в том, что он делает это слишком часто, а это некая лишняя нагрузка.

Также настоятельно рекомендуется (читай обязательно) вносить случайную задержку между запросами на обновление для более равномерного распределения нагрузки на сервера Let’s Encrypt.

Помимо редиректа http → https, я хочу сделать www → без www. Мне кажется сейчас субдомен www уже не очень популярен, при этом в отличие от обратного перенаправления его можно сделать не зависящим от конкретного имени. Как следствие, нам нужно получать или два отдельных сертификата (без www и c www), или один (без www), но с альтернативным именем (www). На мой взгляд, второй вариант проще и логичнее. Если же веб-сервер в контейнере обслуживает несколько сайтов, то ни один мандолорец такое не одобрит. no

Всякого рода масштабирование мы сегодня тоже не рассматриваем. Если оно нужно, предоставьте решать вопрос сертификации Traefik и спите спокойно. pardon

Настройки Lighttpd

Общие

По аналогии с jitesoft/lighttpd предлагаю ввести переменную окружения SERVER_NAME, в которую передадим основной домен (без www), а затем будем использовать чуть менее чем везде. Еще на всякий случай предлагаю включить логи доступа, правда придется задействовать обычный файл – к сожалению stderr для этих целей в образе s6 недоступен.

server.name = env.SERVER_NAME

# regular file as of s6 variant
accesslog.filename = "/var/log/lighttpd/access.log"

Редиректы

В документации есть примеры как перенаправлений с http на https, так и различных вариантов с www. В любом случае сначала включим модуль:

server.modules += ("mod_redirect")

Самый простой безусловный редирект схемы выглядит так:

$HTTP["scheme"] == "http" {
    url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
}

В нем используются практически все возможные шаблоны для подстановки:

  • url.authority – хост (example.com);
  • url.path – путь (например /robots.txt);
  • qsa – параметры запроса, интеллектуально подставляемые после ? или &.

Редирект с www на без www может быть либо универсальным:

$HTTP["host"] =~ "^www\.(.*)$" {
    url.redirect = ( "" => "https://%1${url.path}${qsa}" )
}

Либо, зная домен, можно написать специализированный:

$HTTP["host"] == "www." + server.name {
    url.redirect  = ( "" => "https://" + server.name + "${url.path}${qsa}" )
}

Недостаток первого метода – использование регулярного выражения, что якобы не очень хорошо с точки зрения микрооптимизаций.

Забегая вперед и если верить curl, то когда обращаемся по http на www, два потенциальных редиректа объединяются в один (сокращенный вывод):

curl -kvL www.http2.lighttpd.local
* Connected to www.http2.lighttpd.local (192.168.56.103) port 80
> GET / HTTP/1.1
> Host: www.http2.lighttpd.local
> User-Agent: curl/8.13.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Location: https://http2.lighttpd.local/

Здесь я еще отлаживался на виртуалке с самоподписанным сертификатом.

SSL (TLS)

Для настройки https требуется подключить mod_openssl. Теоретически можно воспользоваться некоторыми другими реализациями (Mbed TLS, wolfSSL или GnuTLS), но это требует соответствующих флагов компиляции и библиотек. Вряд ли вы такое встретите в контейнерах, поэтому будем работать с обычным OpenSSL.

Фрагмент конфигурации Lighttpd для нашего случая прост:

server.modules += ("mod_openssl")

ssl.privkey= "/etc/lighttpd/certs/" + server.name + "/privkey.pem"
ssl.pemfile = "/etc/lighttpd/certs/" + server.name + "/fullchain.pem"
ssl.acme-tls-1 = "/usr/local/etc/dehydrated/alpn-certs"

$SERVER["socket"] == ":9443" { ssl.engine = "enable" }

Хотя и не без нюансов. Размещать сертификаты будем по аналогии с официальным примером (из которого я и узнал про dehydrated) – в подкаталоге /etc/lighttpd/certs по имени домена без www. Применительно к контейнерам необходимо будет обеспечить сохранение состояния, то есть так или иначе пробросить эту директорию, а заодно обеспечить доступ как для Lighttpd, так и dehydrated. Проще всего – если владельцем будет www-data (пользователь, под которым запущен веб-сервер).

Временный каталог для проведения испытания, в отличие от примера, я решил не менять, то есть оставить в недрах локальной директории настроек «высушенного» скрипта. Кстати эту директорию мы тоже пробросим – нужно будет сохранять аккаунт(ы) Let’s Encrypt.

SSL включается довольно странным образом – через условный оператор, но аналогично настраивается прослушивание по IPv6 (не актуальное в контейнере). Или можно было бы разные сайты обслуживать по разным портам. Раз мы слушаем http по нестандартному порту (9000 взамен PHP-FPM), то и для https пусть будет из этого же диапазона (и заведомо без проблем с правами доступа к «низким» портам). Позволю себе не заводить очередную переменную окружения.

Как-то специально включать HTTP/2 и TLS в актуальных версиях Lighttpd по большому счету не нужно – все уже украдено настроено до нас. Разве что рекомендуют отключить поддержку HTTP/2 без шифрования, которая в данном случае не нужна:

# disable h2c support to disable inadvertent h2c smuggling (security) if h2c is not expected
server.feature-flags += ( "server.h2c" => "disable" )

Подготовка Docker

Как обычно, начнем с compose.yaml:

services:
  web:
    build: .
    environment:
      SERVER_NAME: ${SERVER_NAME}
    ports:
      - "80:9000"
      - "443:9443"
    volumes:
      - ./certs:/etc/lighttpd/certs
      - ./config:/usr/local/etc/lighttpd/conf.d
      - ./dehydrated:/usr/local/etc/dehydrated
      - ./src:/var/www/html

С помощью Dockerfile установим dehydrated и необходимые зависимости (hexdump из bsdextrautils):

FROM dmkos/php:lighttpd-s6

# Install dehydrated
ADD --chmod=755 https://raw.githubusercontent.com/dehydrated-io/dehydrated/master/dehydrated /usr/local/bin/
RUN set -eux; \
        apt-get update; \
        apt-get install -y --no-install-recommends \
            bsdextrautils; \
        apt-get dist-clean

В связи с запланированным редиректом на https возникает нюанс, связанный с особенностью реализации проверки состояния контейнера (HEALTHCHECK) в моем образе. Если установить произвольный путь (хоть даже /), то сработает перенаправление и проверка сломается из-за попытки обратиться по https на 9000-й порт (значение LIGHTTPD_PORT по умолчанию):

(curl -fksIL http://127.0.0.1:${LIGHTTPD_PORT}${HEALTHCHECK_PATH}) || exit 1

Для простоты предлагаю sed’ом заменить http://127.0.0.1:${LIGHTTPD_PORT} на https://127.0.0.1:9443, где 9443 – порт, который мы настроили для SSL:

# Fix healthcheck
RUN sed -i 's#http://127.0.0.1:${LIGHTTPD_PORT}#https://127.0.0.1:9443#g' /usr/local/bin/healthcheck

Хотя возможно вы захотите отключить ее вовсе:

HEALTHCHECK NONE

Понятно, что проброс порта через compose.yaml сработает и так, но ради приличия укажем, что у нас открыт 9443 порт для https:

EXPOSE 9443

Настраивать приложение будем через .env-файл, укажем в нем домен (без www):

SERVER_NAME=example.com

Прокидываем директории. certs – для сертификатов. В config я поместил описанные выше настройки Lighttpd – общие (common.conf), редиректов (redirect.conf) и ssl.conf.

Директория dehydrated содержит файл config:

# Below is the minimal configuration, see full example at:
# https://github.com/dehydrated-io/dehydrated/blob/master/docs/examples/config

# URL to certificate authority or internal preset
# Presets: letsencrypt, letsencrypt-test, zerossl, google, google-test
# default: letsencrypt
CA="letsencrypt-test"

# Which challenge should be used? Currently http-01, dns-01 and tls-alpn-01 are supported
CHALLENGETYPE="tls-alpn-01"

# Output directory for generated certificates
CERTDIR="/etc/lighttpd/certs"

# E-mail to use during the registration (default: <unset>)
#CONTACT_EMAIL=

Я решил от греха подальше сразу же выставить тестовый (staging) сервер Let’s Encrypt (а в случае чего будет нетрудно поменять на основной). Минимально (а максимально настройки весьма гибкие) задал тип испытания и директорию сертификатов. На практике желательно указать контактный e-mail, но в принципе можно работать и без него. Служебные данные (в частности сведения об аккаунтах) будут сохранятся в подкаталогах рядом с файлом конфигурации.

Домены для сертификации перечисляются в той же директории, файле domains.txt. Поддерживаются различные варианты, в нашем случае достаточно написать:

example.com www.example.com

То есть в одной строке общее (без www) и альтернативное (с www) имена домена.

В каталог src поместим простейший index.php:

<?php
phpinfo();

Прежде чем что-либо автоматизировать, разберемся, как вообще проходит обряд посвящения.

Сертификация вручную

Для начала необходимо выпустить самоподписанный сертификат. Для этого, на основе примера, я набросал скрипт certs/selfsigned:

#!/usr/bin/bash
if [ -z "${SERVER_NAME}" ]; then
    echo 'Error: SERVER_NAME is empty or not set'
    exit 1
fi
if [ -z "${WWW_USER}" ]; then
    echo 'Error: WWW_USER is empty or not set'
    exit 1
fi
mkdir $SERVER_NAME
openssl req -new -x509 \
    -extensions req_ext \
    -keyout "${SERVER_NAME}/privkey.pem" \
    -out "${SERVER_NAME}/fullchain.pem" \
    -days 3 -nodes -config <(cat <<-EOF
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
CN = $SERVER_NAME
[ req_ext ]
subjectAltName = @san
[ san ]
DNS.1 = $SERVER_NAME
DNS.2 = www.${SERVER_NAME}
EOF
)
chown -R ${WWW_USER}:${WWW_USER} $SERVER_NAME

Хотя переменные можно передать в командной строке, запускать этот скрипт лучше из контейнера, в немалой степени из-за пользователя WWW_USER (вдруг на хосте другие uid:gid или вообще такого нет). Напомню, что эта переменная объявлена в базовом образе. Итак:

docker compose run -it --rm web bash

В контейнере:

cd /etc/lighttpd/certs
with-contenv ./selfsigned

Нюанс в том, что при запуска контейнера через docker run в оболочке недоступны переменные окружения контейнера. Именно поэтому заворачиваем вызов скрипта в with-contenv. В свою очередь, в начале скрипт для очистки совести проверяет наличие переменных и создает соответствующий подкаталог (если таковой существует, будет выдано предупреждение, но работа скрипта продолжится).

Далее как раз заклинаем генерируем сертификат, причем ключ помещаем в отдельный файл. Помимо обычных для этого дела параметров воспользуемся «файлом» настроек, чтобы скрипт не задавал вопросов (prompt = no). Предоставим минимально необходимую информацию: CN и subjectAltName. Последних будет два (DNS.1 и DNS.2), то есть домен без www и с таковым. В отличие от примера, где зачем-то поставили срок в 365 дней, на мой взгляд достаточно и трех.

Наконец, устанавливаем владельца субдиректории сертификата. Также владельца надо поменять и у всей директории dehydrated:

chown -R www-data:www-data /usr/local/etc/dehydrated

Дело в том, что скрипт устанавливает файловые права 600, то есть доступ только владельцу. Поэтому, чтобы веб-сервер смог прочитать сертификат и временные файлы при проверке, dehydrated должен работать под www-data, а значит и самому скрипту нужен доступ к директории конфигурации.

Выходим из контейнера (exit) и запускаем приложение по-человечески:

docker copmpose up -d

Желательно проверить работу сервера (редиректы и https), хотя антивирус и/или браузер будут отчаянно сопротивляться.

Далее заходим в контейнер:

docker compose exec -it web bash

Поскольку аккаунт www-data отключен (точнее имеет оболочку /usr/sbin/nologin), то чтобы от его имени запускать команды, придется явно указывать bash в параметрах su. Для начала зарегистрируемся и примем условия использования:

su -s /usr/bin/bash www-data -c "dehydrated --register --accept-terms"

На самом деле какого-то интерактива тут нет – вызов команды и есть акцепт публичной оферты. crazy

Для проверки и продления сертификатов служит команда dehydrated -c, или в нашем случае:

su -s /usr/bin/bash www-data -c "dehydrated -c"

Поскольку срок нашей филькиной грамоты всего три дня, команда подходит и для первоначального выпуска нормального сертификата (хотя в случае staging это замена шила на мыло, но главное отработать процесс).

В исходном примере вы могли видеть больше параметров у dehydrated, но в нашем случае благодаря файлам config и domains.txt необходимости в каких-то дополнительных параметрах нет.

Осталось обновить конфигурацию Lighttpd путем отправки SIGUSR1. В общем случае для этого надо бы знать PID, но благодаря s6-overlay мы можем поступить проще:

s6-svc -1 /var/run/service/lighttpd

При инициализации контейнера определения сервисов копируются из /etc/s6-overlay/s6-rc.d в /var/run/service, поэтому вот так слегка неочевидно. Справедливости ради, веб-сервер перезапускается (то есть в логах сначала graceful shutdown started, а потом вновь server started), поэтому я бы все-таки предположил вероятность микропаузы. С этой точки зрения возможно ежеминутный опрос сертификатов лучше.

Автоматизация

Исходя из ручного процесса, при запуске контейнера нам нужно делать следующее:

  • если директории сертификата не существует, сделать свой;
  • если нет списка доменов, сформировать на основании SERVER_NAME;
  • если нет аккаунта Let’s Encrypt, зарегистрироваться.

Поскольку у нас пример, а не полноценное промышленного решение, то последнюю проверку упростим до наличия или отсутствия каталога accounts в /usr/local/etc/dehydrated. На самом деле там могут существовать отключенные аккаунты и/или от другого сервера, что в общем случае исказило бы картину. Поэтому если от экспериментов вдруг остались какие-то следы, то нужно будет их замести. А может быть и вообще стоило бы оставить регистрацию на откуп пользователю.

Длительный сервис (эмуляция cron) первоначально должен запуститься после Lighttpd, попытаться продлить сертификат (dehydrated -c) и уснуть на ± определенное время. Затем продлить, уснуть и так до бесконечности (остановки контейнера).

Подготовка

Напишем «краткосрочный» сервис prepare. На хосте подготовим структуру файлов:

  • s6-rc.d/prepare/dependencies.d/base – пустой файл, объявляет зависимость от базовых сервисов;
  • s6-rc.d/prepare/type – тип сервиса – oneshot;
  • s6-rc.d/prepare/up – скрипт, выполняемый при инициализации – with-contenv /usr/local/sbin/prepare ;
  • s6-rc.d/lighttpd/dependencies.d/prepare – пустой файл, объявляет зависимость Lighttpd от подготовки контейнера (помимо php-fpm);
  • s6-rc.d/user/contents.d/prepare – пустой файл – ставит сервис в «автозагрузку».

Вместо run в «одноразовых» сервисах применяется up при запуске и down при остановке контейнера. В данном случае каких-то завершающих действий не требуется. Также стоит заметить, что скрипты up и down уже «завернуты» в execlineb, поэтому в них как правило просто пишется команда вызова полноценного скрипта. В частности мы вызываем скрипт prepare с переменными окружения контейнера.

Сам sbin/prepare реализует последовательность проверок и выполнение необходимых действий, как мы обсудили выше:

#!/usr/bin/bash
if [ -z "${SERVER_NAME}" ]; then
    echo 'Error: SERVER_NAME is empty or not set'
    exit 1
fi
if [ -z "${WWW_USER}" ]; then
    echo 'Error: WWW_USER is empty or not set'
    exit 1
fi

if [ ! -d "/etc/lighttpd/certs/$SERVER_NAME" ]; then
    echo "Issue self-signed certficate"
    cd /etc/lighttpd/certs
    ./selfsigned
fi

domains_txt=/usr/local/etc/dehydrated/domains.txt
if [ ! -s "$domains_txt" ]; then
    echo "Create domains.txt:"
    echo "$SERVER_NAME www.${SERVER_NAME}"
    echo "$SERVER_NAME www.${SERVER_NAME}" > $domains_txt
fi

if [ ! -d "/usr/local/etc/dehydrated/accounts" ]; then
    echo "Register CA account"
    chown -R ${WWW_USER}:${WWW_USER} /usr/local/etc/dehydrated
    su -s /usr/bin/bash $WWW_USER -c "dehydrated --register --accept-terms"
fi

if [ ! -d "/var/log/lighttpd" ]; then
    mkdir /var/log/lighttpd
    touch /var/log/lighttpd/access.log
    chown -R ${WWW_USER}:${WWW_USER} /var/log/lighttpd
fi

В дополнение к тому, что выше не обсуждали – подготовка журнала доступа веб-сервера, иначе даже в обычный файл ничего нельзя будет писать.

Небольшой недостаток в том, что переменные окружения проверяются и здесь, и в скрипте selfsigned. Как вариант, можно перенести последний в sbin и убрать проверку переменных (при условии, что он никогда не будет запускаться вручную), либо заняться копипастой. Предлагаю не заострять на этом внимание.

Через Dockerfile заносим в контейнер всю эту «заразу»:

# Configure
COPY s6-rc.d/ /etc/s6-overlay/s6-rc.d/
COPY --chmod=700 sbin/ /usr/local/sbin/

Надеюсь, скрипт хотя бы с натяжкой можно отнести к задачам администрирования (для чего вроде как и предназначаются директории sbin).

Перевыпуск сертификатов

Это будет «длительный» сервис renew:

  • s6-rc.d/renew/dependencies.d/lighttpd – пустой файл, перевыпуск сертификатов должен запускаться после веб-сервера;
  • s6-rc.d/renew/notification-fd – файловый дескриптор оповещения о готовности сервиса – 5;
  • s6-rc.d/renew/run – команда запуска (рассмотрим далее);
  • s6-rc.d/renew/type – тип сервиса – longrun;
  • s6-rc.d/user/contents.d/renew – пустой файл – «автозапуск» сервиса.

К сожалению, без root-доступа и переменных контейнера не обойтись, поэтому run представляет собой следующее:

#!/command/execlineb -P
with-contenv
/usr/local/sbin/renew

А sbin/renew – такое:

#!/usr/bin/bash
fullchain="/etc/lighttpd/certs/${SERVER_NAME}/fullchain.pem"

trap exit TERM
while :
do
    date1=$(stat -c %y "$fullchain")
    su -s /usr/bin/bash ${WWW_USER} -c "dehydrated -c"

    date2=$(stat -c %y "$fullchain")
    if [ "$date2" != "$date1" ]; then
        s6-svc -1 /var/run/service/lighttpd
    fi

    # readyness
    if [ -w "/proc/self/fd/5" ]; then
        echo >&5
        exec 5>&-
    fi

    sleep $(perl -e 'print 43200 + int(rand(43200))') &
    wait $!
done

Сначала записал в переменную путь к сертификату. Далее перехватываем SIGTERM для выхода из бесконечного цикла, в котором мы как раз сначала проверяем (и перевыпускаем при необходимости) сертификаты, а затем засыпаем на время от 12 до 24 часов.

Возникает вопрос – как определить, что у нас обновился сертификат? Ведь если с ним ничего не произошло, то и веб-сервер нет необходимости перезапускать (к вопросу о root-досутпе – s6-svc как раз требует повышенных привилегий). Решил остановиться на банальном способе сравнения даты изменения файла сертификата, хотя можно было бы сравнить хэш или что-нибудь придумать с хуками dehydrated (впрочем под непривилегированным пользователем толку от них наверное было бы немного).

Далее мы реализуем правильный подход к оповещению о готовности: если заданный через notification-fd файловый дескриптор доступен для записи (то есть в первой итерации цикла), пишем в него пустую строку и закрываем. Я решил реализовать этот механизм на случай запуска контейнера через docker run, чтобы приглашение ко вводу не появилось до того, как отработает dehydrated. Представьте: вошли в консоль, а в нее еще сыпется куча сообщений. Неудобно.

В примерах cron-заданий для certbot для внесения произвольной задержки обычно используется perl, поэтому сделал аналогично (но можно было бы и на PHP подсчитать). Еще один нюанс – комбинация sleep & и wait $!. Если не перевести sleep в фон (амперсандом), то контейнер может остановиться только аварийно по таймауту, а такой хоккей нам не нужен! acute

Теоретически вместо sleep можно было бы взять какой-нибудь аналог cron типа snooze, благо последний тоже умеет в рандом, но зачем плодить лишние сущности? Подозреваю, что скорее всего пришлось бы еще неким образом отделять первый запуск dehydrated -c от регулярных. Тем не менее, на всякий случай упомяну еще один вроде как специальный «cron для Докера» – Ofelia. Из особенностей – настройка через метки и оповещения по e-mail, так что возможно кому-то пригодится.

Заключение

С одной стороны, я думаю что проделанная работа смогла убедить вас в том, что сертификацией лучше заниматься какому-нибудь Traefik’у, а не самостоятельно. С другой стороны, возникла парадоксальная ситуация, ведь теперь можно просто взять мой готовый (хоть и не без шероховатостей) пример, прописать в .env-файле домен и разбавить концентрат приложением на PHP. Взболтать, но не смешивать. cool

Исходный код доступен у меня в репозитории:

https://git.dmkos.ru/containers/php/-/tree/main/linux/lighttpd/examples/standalone

Или версия на момент публикации статьи:

https://git.dmkos.ru/containers/php/-/tree/10-lighttpd-http-2/linux/lighttpd/examples/standalone


Категория: Программирование, веб | Опубликовано 28.10.2025

Похожие материалы

Система инициализации s6-overlay. Вариант образа Lighttpd для Docker

Несмотря на то, что веб-сервер Lighttpd умеет самостоятельно запускать процессы FastCGI (в частности php-fpm), такая возможность скорее побочная и злоупотреблять ею не стоит. С точки зрения контейнеризации это означает, что нужна система, которая смогла бы запустить сначала PHP, а затем веб-сервер, после чего корректно завершить эти процессы при остановке контейнера. Одной из таких является s6-overlay, с помощью которой мы и создадим вариант образа Lighttpd для PHP.

Не краткий обзор HAProxy на примере интеграции с Lighttpd

HAProxy (high availability proxy) - обратный прокси и балансировщик нагрузки, один из старейших и известнейших. В версии 3.2 появилась экспериментальная поддержка протокола ACMEv2, а значит получение сертификатов Let's Encrypt. Пусть это и не совсем то, для чего предназначается балансировщик, но мы можем поставить его перед веб-сервером Lighttpd для терминации SSL.


Комментарии, обсуждение