Полный CDN сайта на базе AWS CloudFront

Всем привет. Недавно я настроил установку Discourse с использованием AWS CloudFront (CF) для полной ускорения сайта и выгрузки SSL с помощью сертификатов AWS в CF. Обратите внимание, что эта установка отклоняется от официального руководства в отношении конфигурации CDN и SSL — поэтому это может быть спорным и привести к будущим проблемам с поддержкой. Так что будьте предупреждены… здесь водятся драконы. Я делюсь здесь конфигурацией, которая сработала для меня:

  1. Настройте Discourse на прослушивание только порта 80 и отключите Let’s Encrypt, закомментировав указанные строки в файле app.yml:

  2. Настройте Discourse на использование заголовка CF cloudfront-forwarded-proto вместо x-forwarded-proto (который CF не передаёт — и, странно, его нельзя настроить на передачу источнику… черт возьми! :angry:)

  3. Настройте распределение CF с CNAME для вашего предполагаемого публичного имени хоста (например, forum.example.com), используя сертификат AWS ACM (который вы создали).

  4. Настройте источник CF, используя публичный Elastic IP сервера EC2, на котором размещён Discourse (например, ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com). Настройте его только для HTTP (то есть порт 80, без 443). Вам не нужно настраивать источник с красивым именем хоста в DNS, например forum-origin.example.com. Имя хоста EC2 или IP отлично работают.

  5. Настройте «поведения» (behaviors) CF для различных путей запросов. Ключевое здесь — настроить поведение кэширования для явно статических ресурсов и настроить отсутствие кэширования для всего остального (то есть эти запросы просто передаются как есть источнику без кэширования). Ещё один важный момент: последнее правило передачи («по умолчанию») использует пользовательскую «политику запросов к источнику», которая передаёт все оригинальные заголовки источнику в дополнение к заголовку CF cloudfront-forwarded-proto. Также настройте перенаправление с HTTP на HTTPS в ваших поведенческих правилах, чтобы все запросы пользователей принудительно обрабатывались через HTTPS в CF.

  6. Не настраивайте переменную окружения “DISCOURSE_CDN_URL”.

  7. Включите опцию “force https”.

  8. Не настраивайте “long polling base url” — оставьте её пустой. Несмотря на все мрачные предупреждения о том, что это может быть проблематично при пропускании через прокси, у меня это пока работает отлично. Возможно, стандартное время удержания соединения (keep-alive) в CF достаточно велико, чтобы предотвратить разрыв соединения.

Думаю, это всё… :thinking:

В результате все запросы, HTTP-документы, все вспомогательные статические ресурсы, все AJAX-вызовы и т.д. обслуживаются на одном и том же доменном имени (например, forum.example.com). Поведение кэширования (и поведение передачи) определяется вашими «поведениями», настроенными в CF. Все соединения зашифрованы с использованием сертификатов AWS ACM, завершённых на границе CF, а затем незашифрованный/HTTP-трафик отправляется обратно на сервер источника.

Скажу прямо: это может быть даже чище, чем то, что сейчас реализовано на meta.discourse.org :shushing_face:.

Привет, @jaffadog

У меня схожая ситуация, но с полным сайтом и другой CDN. В вашем эксперименте вы когда-либо пробовали настраивать DISCOURSE_CDN_URL с URL домена веб-сайта? Например, в режиме полной CDN, если URL вашего сайта — https://foo.bar.com, то URL CDN также должен быть https://foo.bar.com. Если оставить DISCOURSE_CDN_URL пустым, то URL активов сайта будут начинаться с относительного пути. Например, как в приведённом ниже фрагменте:

      <link rel="preload" href="/extra-locales/admin?v=8f522e122c802d1ed66dfa7fecafbb35" as="script">
<script defer src="/extra-locales/admin?v=8f522e122c802d1ed66dfa7fecafbb35"></script>

Это выглядит не очень элегантно на продакшн-сайте, хотя оба URL отправляют запросы на https://foo.bar.com.