В данной статье я хочу подробно разобрать тему хостинга статических сайтов на AWS. Тему нельзя назвать сильно сложной, но нюансов хватает. Для настройки вручную потребуется организовать взаимодействие 4-5 сервисов, а по дороге порой можно встретить весьма интересные грабли.

Некоторое время назад существовал официальный туториал по такой ручной настройке. Местами он мог показаться сложным, местами странным. Скорее всего, это была дань универсальности и необходимости продемонстрировать разные варианты хостинга. Однако сейчас туториал кардинально обновлен, и предлагает использовать сервис AWS Amplify для решения такой задачи. С одной стороны, это удобно, но с другой стороны, иногда необходимо разобраться, что же именно происходит “под капотом”. Поэтому здесь мы разберем, как все настроить руками.

Статические сайты


Для начала, в двух словах — а почему статический сайт? Как ни странно, мода на статические сайты, вернувшаяся лет 8-10 назад, до сих пор не проходит. И речь не только об огромном количестве сайтов на GitHub Pages. Генераторы статических сайтов такие как Jekyll, Hugo или хипстерский Gatsby продолжают выпускать регулярно новые релизы и остаются более чем востребованными.

Проверка временем давно пройдена. Но чем же это круто? Когда у вас статический веб-сайт, на нем практически нечего ломать. Нет форм логина, админки, динамических скриптов, которые можно обмануть. Статический сайт — это очень быстро. Вам не нужно грузить CPU обработкой тяжелого запроса. Содержимое можно кэшировать, начиная от CDN’а и заканчивая браузером пользователя.

Хостинг сайта или почему AWS


На статическом сайте практически нечего ломать. Если нельзя ломать сайт, можно ломать, например, хостинг. Вы купили виртуальную машинку в DigitalOcean, поставили туда nginx и залили сайт. Но nginx и другие пакеты тоже надо периодически обновлять. Поэтому логичным выбором в пользу уменьшения забот (ака maintenance) является использование облаков, например, AWS. ОСь и веб-сервер никуда не денутся, но их обновление и защита перестанут быть вашей задачей.

Для примера я взял сайт, который мы (Plesk) используем в качестве промо наших open source проектов на GitHub.


Сайт статический. Состоит, по сути, из одной странички index.html, нескольких картинок, кастомного шрифта, css-стилей и некоторого количества JavaScript’а.

Этот сайт мы и попробуем разместить в инфраструктуре AWS. Схематично инфраструктура будет выглядеть следующим образом:


AWS S3


Для хостинга сайта мы воспользуемся сервисом AWS S3. Первое, что нам потребуется, это создать S3 bucket. По сути, это именованное место для хранения файлов. Имя должно быть глобально уникально. Сайт я планирую разместить по адресу tech.plesk.space, поэтому в качестве имени bucket’а выбрал tech-plesk-space (можно было и с точками). Регион пусть будет Франкфурт, eu-central-1. Во Франкфурте расположена самая крупная в Европе точка обмена трафиком. В нашем случае я не планирую раздавать контент напрямую с S3, мы это сделаем с помощью CloudFront, поэтому выбор региона не сильно принципиален. Но, в целом, с точки зрения latency и connectivity для потребителей из Европы, Франкфурт — это очень хорошая локация. Из скриншота ниже можно заметить, что выставлена галочка “Block all public access”. Все верно, раздавать контент мы будем не напрямую с S3, а через сервис CloudFront, который представляет собой Content Delivery Network от Amazon.


После создания bucket пуст, и нам нужно залить туда файлы, которые мы планируем раздавать. Можно сделать это через веб-интерфейс, но я воспользуюсь AWS CLI. Сделать это можно с помощью следующей команды из директории, где локально расположены файлы сайта:

aws s3 sync --delete . s3://tech-plesk-space

Что здесь происходит? Мы выполняем синхронизацию локальных файлов с S3 bucket с названием tech-plesk-space. Опция “delete” позволяет удалить файлы в bucket, если они отсутствуют локально.

Проверяем через веб-интерфейс — файлы доступны:


Если бы мы не ограничили публичный доступ, то файлы можно было бы посмотреть через технический домен. Amazon для удобства создал нам tech-plesk-space.s3.eu-central-1.amazonaws.com. Как видно, доменное имя состоит из названия bucket, названия сервиса S3, региона eu-central-1 и суффикса для технических доменов: amazonaws.com.

Route 53


Прежде чем настраивать публичный доступ к сайту, давайте разберемся с доменным именем. В качестве такового я выбрал tech.plesk.space.

Отправляемся в консоль Amazon, открываем сервис Route 53 и создаем новую публичную зону.


После создания зоны мы получаем информацию об NS-записях. Это DNS-серверы, которые будут хранить информацию о нашей зоне. Если вы раньше работали с какими-нибудь небольшими провайдерами, то выглядело это примерно так: есть ns1, ns2, и на них хостятся все домены. В случае с AWS сказать какие DNS-серверы будут обслуживать зону заранее нельзя.

Итак, у нас есть список NS-записей, что с ним делать? Если вы купили домен, то далее идете в панель управления доменом и прописываете полученные записи. Вот так это выглядит, например, у GoDaddy:


В нашем случае домен tech.plesk.space является поддоменом plesk.space, а эта зона хостится в Digital Ocean DNS аккаунте. Для того, чтобы правильно выполнить делегирование, нам нужно прописать соответствующие glue records.


Проверяем с помощью dig’а:


Одних NS-записей для обслуживания сайта не достаточно. Нужна еще A-запись. Мы вернемся к этой теме немного позже, когда доберемся до CloudFront, но перед этим нам нужно сделать еще одно действие.

ACM


Современные тенденции говорят, что сайт должен быть доступен по HTTPS, и на нем должен присутствовать валидный сертификат. В AWS есть сервис по управлению сертификатами и называется он AWS Certificate Manager (или сокращенно ACM). Отправляемся туда для создания сертификата. Это абсолютно бесплатно, но секретную часть сертификата (ключ) вам не дадут. Так что этими сертификатами можно воспользоваться только внутри инфраструктуры Amazon.

Еще один любопытный момент: для нужд CloudFront сертификат нужно создавать в зоне us-east-1 (N. Virginia), иначе вы не сможете им воспользоваться в рамках CloudFront. Что ж, переключаем регион на us-east-1 и идем создавать сертификат. В качестве способа валидации выбираем DNS-валидацию. Так как зону мы разместили в Route53, есть удобная кнопочка создания валидационной записи:


Процесс может занять до 30 минут. На практике обычно это занимало гораздо меньше времени. В конце процедуры, после успешного выписывания сертификата, можно сходить в Route53 и удалить валидационную запись.

Сертификат выдается сроком на 1 год и для его обновления дополнительно делать ничего не нужно.

CloudFront


Осталось буквально последнее действие — настроить CloudFront, чтобы наш сайт стал доступным для пользователей.

Для этого отправляемся в интерфейс CloudFront и создаем новую сущность под названием Distribution. Выбираем в Origin Domain Name tech-plesk-space.s3.amazonaws.com. То есть S3 у нас будет выступать origin’ом, а раздачу контента будет выполнять CloudFront. Кто не знаком с идеологией CDN, origin — это хранилище оригинальных файлов, а edges — это серверы, которые кэшируют данные origin’а и непосредственно раздают контент клиентам. Также для красоты можно еще изменить настройку Viewer Redirect Policy и выставить ее в положение “Redirect HTTP to HTTPS”.


В качестве Alternate Domain Names (CNAMEs) указываем tech.plesk.space. Не забываем и про SSL Certificate: там выбираем Custom SSL Certificate и из выпадашки (которая совершенно не выглядит выпадашкой) выбираем нужный нам сертификат.


Еще одна вещь, которую стоит сделать, — это задать Default Root Object. Здесь мы укажем index.html. Без этого действия при обращении к сайту без указания файла (то есть написав в браузере просто https://tech.plesk.space/) мы получим 403 ошибку. В контексте веб-серверов такая настройка обычно называется Directory Index.


Жмем кнопку “Создать” и набираемся терпения. Процесс может занять минут 10.

После того, как Distribution был создан, нужно немного поправить доступ к origin. Для этого отправляемся на редактирование в соответствующую вкладку. Далее выбираем, что мы хотим ограничить доступ, настройка Restrict Bucket Access; хотим создать новую Access Identity и разрешаем обновить bucket policy. Выглядеть это должно, примерно, так:


Зачем было нужно действие выше? Вспоминаем, что при настройки S3 мы оставили опцию “блокировать весь доступ” по-умолчанию. Таким образом, CloudFront не получил бы возможность читать контент из bucket’а.

Остается последний штрих: указать в Route53, что именно будет служить у нас A-записями для домена tech.plesk.space. Для этого идем в интерфейс Route53, выбираем Create New Record Set, выбираем тип A-запись, но вместо самой записи выбираем, что у нас Alias, а из выпадающего списка выбираем соответствующий CloudFront distribution. Выглядеть это должно, примерно, так:


Открываем браузер, вводим https://tech.plesk.space/ и видим наш сайт:


Для интереса смотрим A-записи:

Проверяем с помощью curl, что нас действительно обслуживает CloudFront:

Как видно из последних 5 заголовков, это действительно так.

На этом, в общем-то, и всё. Сайт запущен, работает и доступен клиентам.

Прочие моменты


Я не затрагивал тему логирования запросов. По-умолчанию оно выключено, но его можно настроить. Логи будут складываться в S3 bucket. Нужно учитывать специфику подхода к CDN (тут Amazon совершенно не уникален) о том, что такое логирование — это не инструмент real time отладки. Логи доставляются с приличными задержками, а документация говорит, что такие задержки могут быть до 24 часов. Из практики могу сказать, что подключение Google Analytics почти всегда снимало вопросы про логирование для таких статических сайтов.

Еще один момент, который хотел кратко упомянуть, это цена. В случае free tier и небольшой нагрузки стоимость будет около 50 центов, и то только на Route53. Без free tier получалось где-то 1-2 доллара в месяц. В целом, наверное, может показаться, что это даже дорого для хостинга статического сайта, но, на самом деле, в случае с AWS, у нас огромный потенциал для развития проекта (масштабируемость, оплата по мере роста, глобальная доступность, огромное количество других удобных сервисов и многое-многое другое).

Заключение


Как я уже упоминал в начале, официальный туториал от Amazon теперь советует использовать сервис AWS Amplify. Он действительно удобней: тут и подключение Git-репозитория, и полуавтоматическая настройка ряда вышеописанных вещей. Но, порой, нужно разобраться с уже настроенной инфраструктурой или организовать некоторые вариации хостинга, из-за чего уже придется разбираться со всеми нюансами.

Еще один интересный взгляд на данную проблему — это сервисы типа Netlify. Они еще сильнее упрощают некоторые вещи (правда, бывает и усложняют), но, конечно, и их использование будет стоить дополнительных денег.

Надеюсь, статья поможет сберечь время при настройке хостинга статического сайта в AWS.