AWS: S3 – хостинг статического сайта

Автор: | 28/09/2016

aws-logo-square-02Введение

Amazon Web Services позволяет размещать сайты со статическим контентом прямо в корзине Simple Storage Service.

Для размещения такого сайта – вам необходимо настроить корзину S3 и загрузить в неё файлы приложения. После этого – оно будет доступно через URL вида <bucket-name>.s3-website-<AWS-region>.amazonaws.com. Кроме того – вы можете подключить собственный домен, что бы получать доступ к сайту в S3 через него.

Общие сведения по работе с AWS S3 – в посте AWS: S3, Simple Storage Service – описание, примеры.

Для того, что бы хостить свой сайт в корзине S3 – вам необходимо её соответствующим образом настроить.

Такая настройка включает в себя:

Содержимое:

Размещение статического сайта в S3

Создание и настройка корзины S3

С помощью AWS CLI – создаём корзину:

$ aws s3 mb s3://static-site-example
make_bucket: s3://static-site-example/

Проверяем:

$ aws s3api list-buckets --query '[Buckets[*]]' --output text | grep static
2016-09-15T14:45:17.000Z        static-site-example

Настраиваем WebSite для корзины:

$ aws s3 website s3://static-site-example --index-document index.htm --error-document 4xx.htm

В зависимости от Availability Zone – endpoint сайта будет выглядеть так:

static-site-example.s3-website-eu-west-1.amazonaws.com

Все endpoint-ы можно найти тут>>>.

Проверяем:

$ curl static-site-example.s3-website-eu-west-1.amazonaws.com
<html>
<head><title>403 Forbidden</title></head>
<body>
<h1>403 Forbidden</h1>
<ul>
<li>Code: AccessDenied</li>
<li>Message: Access Denied</li>
<li>RequestId: E645BA06FAAFB2E8</li>
<li>HostId: ntBfezrYi3ICqFWanqV4fjMATnvOtn+I4Am/HhgGQyN2nas5xPuydrs77wk7+voqetuapNH+Tio=</li>
</ul>
<h3>An Error Occurred While Attempting to Retrieve a Custom Error Document</h3>
<ul>
<li>Code: AccessDenied</li>
<li>Message: Access Denied</li>
</ul>
<hr/>
</body>
</html>

Настройка политик доступа корзины

Создаём JSON с описанием политики доступа:

{
  "Version":"2012-10-17",
  "Statement":[{
    "Sid":"PublicReadForGetBucketObjects",
        "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::static-site-example/*"
      ]
    }
  ]
}

Подключаем его к корзине:

$ aws s3api put-bucket-policy --bucket static-site-example --policy file://site-policy.json

Проверяем:

$ curl static-site-example.s3-website-eu-west-1.amazonaws.com
<html>
<head><title>404 Not Found</title></head>
<body>
<h1>404 Not Found</h1>
<ul>
<li>Code: NoSuchKey</li>
<li>Message: The specified key does not exist.</li>
<li>Key: index.htm</li>
<li>RequestId: 57181FF91EA5C204</li>
<li>HostId: uP9NBV7LPsYI6nGIsAmRXHytOpG3MMk99yh8N4Whs4fhn6dSsdVCNB0a5rGxWTSGt6ncLUVAqGo=</li>
</ul>
<h3>An Error Occurred While Attempting to Retrieve a Custom Error Document</h3>
<ul>
<li>Code: NoSuchKey</li>
<li>Message: The specified key does not exist.</li>
<li>Key: 4xx.htm</li>
</ul>
<hr/>
</body>
</html>

404 “Key not found”, т.к. ни index.htm, ни 4xx.htm в корзине ещё нет.

Загрузка данных

Создадим два файла – индексный, и страницу ошибок:

$ echo "Test Site index page" > index.htm
$ echo "Error page" > 4xx.htm

Загружаем их:

$ aws s3 cp index.htm s3://static-site-example
upload: ./index.htm to s3://static-site-example/index.htm
$ aws s3 cp 4xx.htm s3://static-site-example
upload: ./4xx.htm to s3://static-site-example/4xx.htm

Проверяем:

$ aws s3 curl static-site-example.s3-website-eu-west-1.amazonaws.com
Test Site index page

Индексная страница работает.

Проверяем несуществующую страницу:

$ curl static-site-example.s3-website-eu-west-1.amazonaws.com/nonexistentpage.htm
Error page

S3 вернул страницу 4xx.htm.

Сайт в S3 со своим доменом

Создание корзин

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

Имеется домен – azinchenko.com, следовательно – корзина должна называться azinchenko.com.

Создаём:

$ aws s3 mb s3://azinchenko.com
make_bucket: s3://azinchenko.com/

К www – перейдём чуть позже.

Повторяем настройку, как в примерах выше:

$ aws s3 website s3://azinchenko.com --index-document index.htm --error-document 4xx.htm
$ aws s3api put-bucket-policy --bucket azinchenko.com --policy file://azinchenko.com.policy.json
$ echo "Test Site index page" > index.htm
$ echo "Error page" > 4xx.htm
$ aws s3 cp index.htm s3://azinchenko.com
upload: ./index.htm to s3://azinchenko.com/index.htm
$ aws s3 cp 4xx.htm s3://azinchenko.com
upload: ./4xx.htm to s3://azinchenko.com/4xx.htm
$ curl azinchenko.com.s3-website-eu-west-1.amazonaws.com
Test Site index page

Редирект www 

Для редиректа домена с www на домен без него – создаём вторую корзину, с www:

$ aws s3 mb s3://www.azinchenko.com
make_bucket: s3://www.azinchenko.com/

Редиректы описаны тут>>> и тут>>>.

Создаём JSON:

$ cat azinchenko.com.redirects.json 
{
    "RedirectAllRequestsTo": {
        "HostName": "azinchenko.com"
    }
}

Подключаем редирект:

$ aws s3api put-bucket-website --bucket www.azinchenko.com --website-configuration file://azinchenko.com.redirects.json

Проверяем:

$ aws s3api get-bucket-website --bucket www.azinchenko.com
{
    "RedirectAllRequestsTo": {
        "HostName": "azinchenko.com"
    }
}

Проверяем:

$ curl -L www.azinchenko.com.s3-website-eu-west-1.amazonaws.com
<!DOCTYPE html>
<!--[if IE 7]>
<html class="ie ie7" lang="en-US">
<![endif]-->
<!--[if IE 8]>
<html class="ie ie8" lang="en-US">
<![endif]-->
<!--[if !(IE 7) | !(IE 8)  ]><!-->
<html lang="en-US">
<!--<![endif]-->
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>RTFM: Linux, DevOps и системное администрирование</title>
...

🙂

Домен azinchenko.com всё ещё направлен на RTFM, редирект уже работает.

Настройка домена для S3

Находим зону:

$ aws route53 list-hosted-zones --query 'HostedZones[*].{ID:Id,Name:Name}' --output text
/hostedzone/Z2W76WVFMAMGZQ      azinchenko.com.

Проверяем текущие записи для зоны:

$ aws route53 list-resource-record-sets --hosted-zone-id Z2W76WVFMAMGZQ --output text
RESOURCERECORDSETS      azinchenko.com. 300     A
RESOURCERECORDS 52.208.35.167
...
RESOURCERECORDSETS      www.azinchenko.com.     300     CNAME
RESOURCERECORDS azinchenko.com

Находим Hosted Zone ID для entrypoint-а корзины (azinchenko.com.s3-website-eu-west-1.amazonaws.com, следовательно ищем по s3-website-eu-west-1.amazonaws.com) тут>>>:

EU (Ireland) s3-website-eu-west-1.amazonaws.com Z1BKCTXD74EZPE

Создаём JSON для обновления IN A записи зоны azinchenko.com – добавляем алиас вместо IP:

$ cat azinchenko.com.json
{
  "Comment":"Static website hosting on S3",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "azinchenko.com.",
        "Type": "A",
        "AliasTarget": {
          "HostedZoneId": "Z1BKCTXD74EZPE",
          "DNSName": "s3-website-eu-west-1.amazonaws.com.",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}

С помощью change-resource-record-sets – загружаем обновление:

$ aws rouaws route53 change-resource-record-sets --hosted-zone-id Z2W76WVFMAMGZQ --change-batch file://azinchenko.com.json
{
    "ChangeInfo": {
        "Status": "PENDING", 
        "Comment": "Static website hosting on S3", 
        "SubmittedAt": "2016-09-27T17:30:06.436Z", 
        "Id": "/change/CEIZE3NGCFDY"
    }
}

Проверяем:

$ aws route53 get-change-details --id CEIZE3NGCFDY

A client error (Throttling) occurred when calling the GetChangeDetails operation: Rate for operation GetChange exceeded

WTF?

Проверяем:

$ curl -L azinchenko.com
Test Site index page
$ curl -L www.azinchenko.com
Test Site index page

Готово.

Ссылки по теме

Hosting a Static Website on Amazon S3