ただいま絶賛開発中の、簡単に字幕を付けられるアプリ「字幕くん」。インフラ周りはAWSをメインに使っており、CloudFormationを活用してコードベースで管理されています。インフラ構築は非常に便利で良い時代になったとしみじみ感じるものです。
ただ、我々Notedで取り扱うサービスはXServer上で管理されているものも多く、事実noted.runドメインもXServer上での管理です。開発陣営である私としてはAWSサービスに慣れており、ぜひそちらに寄せたいものですが、現状で動いているサービスとの兼ね合いもあるので、ドメイン移管なども得策ではなさそうです。
今回はそんな、インフラサービスの垣根を超えるためのTipsになります。
(ま、とは言いつつすでに世の中に解決策が出てはいるので、今回は実際に構築するうえでの注意点や所感など交えて伝えようと思います。)
今回の前提
今回開発しているサービスのインフラ構成は以下のように非常にシンプルです。
- S3での静的サイトホスティング
 - CloudFrontによるHTTPS化
 
本来AWSサービスだけで済ませるのであれば、ここにRoute53が入ってきて、ドメインとの紐づけがされて…となることでしょう。

ただ、今回は違います。以下のようにXServerで管理するドメインを紐づける必要がありますからね。

ではここから実際にXServerのドメインとAWSのリソースを紐づけていきましょう。
手順
AWS上で証明書を発行しよう
まず初めにやっておくべきはAWS側での証明書発行です。HTTPS化をするのに証明書が必要ですが、申請が受理されるのに時間がかかる可能性がありますからね。
AWS Certificate Managerよりパブリック証明書をリクエストしましょう。
以下のように完全修飾ドメイン名の箇所に *.<対象のドメイン名>として設定し、ほかはデフォルトのままで設定しましょう。
字幕くんは https://zimaku.noted.run/ なので、完全修飾ドメイン名は *.noted.runです。

リクエストすると、証明書のドメインの項目にCNAME名とCNAME値が入っています。これらの値をメモしておきましょう。

続いてXServer側でこの値を用いてDNSレコードを追加します。DNSレコード設定からそれぞれ以下のルールで設定しましょう。
| ホスト名 | 先ほどメモしたCNAME名 ⚠️先頭のアンダースコアも一緒につけること!  | 
| 種別 | CNAME | 
| 内容 | 先ほどメモしたCNAME値。 ⚠️先頭のアンダースコア・最後のピリオドをつけないこと!  | 
| TTL | 3600 (デフォルト) | 
| 優先度 | 0 (デフォルト) | 

以上でDNSレコードを追加してください。
ここまで完了したら一度待ちです。先ほどのAWS Certificate Manager画面上でドメインのステータスが「成功」になるのを待ちましょう。人にもよりますが、大体1~10分程度で証明書が利用可能な状態になるはずです。(逆に10分以上かかる場合は設定に間違いがあるかもなので、見直してみてください。)
また後々使うため、証明書のページでARNをメモしておいてください。
AWSリソースを構築
証明書が発行できたら、AWSリソースを構築しましょう。先ほどお見せした構成を作るだけなので、各リソースの説明を細かくはしません。以下テンプレート元にサクッとCloudFormationで構築しちゃいましょう。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  DomainName:
    Type: String
  ACMPublicCertificateArn:
    Type: String
Resources:
  MainBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    Properties:
      BucketName: !Ref DomainName
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      CorsConfiguration:
        CorsRules:
          - AllowedHeaders:
              - '*'
            AllowedMethods:
              - 'GET'
            AllowedOrigins:
              - '*'
  MainBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref MainBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudfront.amazonaws.com
            Action:
              - s3:GetObject
              - s3:ListBucket
            Resource:
              - !Sub arn:aws:s3:::${MainBucket}
              - !Sub arn:aws:s3:::${MainBucket}/*
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - Id: S3Origin
            DomainName: !Sub "${MainBucket}.s3.${AWS::Region}.amazonaws.com"
            S3OriginConfig:
              OriginAccessIdentity: ""
            OriginAccessControlId: !GetAtt CloudFrontOriginAccessControl.Id
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          TargetOriginId: S3Origin
          ViewerProtocolPolicy: redirect-to-https
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
        ViewerCertificate:
          AcmCertificateArn: !Ref ACMPublicCertificateArn
          MinimumProtocolVersion: TLSv1.2_2021
          SslSupportMethod: sni-only
        HttpVersion: http2
        Enabled: true
        IPV6Enabled: false
        Aliases:
          - !Ref DomainName
  CloudFrontOriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Name: !Sub "oac-${AWS::StackName}"
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4
作成時に証明書のARNとドメイン名が必要となるので、先ほどメモしたARNと今回のドメインを入力し、後はデフォルトのままでスタックを作成してください。
こちらも5~10分程度待つとAWSリソースが構築されるはずです。失敗している場合はCloudFormationにエラーの概要が出ているはずなので、確認してみてください。
構築されたら、対象のS3バケットにindex.htmlとして、HTMLファイルを置いてみましょう。
Hello From AWS!
置けたらCloudFront上で提示された「ディストリビューションドメイン名」をコピーしてブラウザ上でアクセスしてみてください。成功していれば以下のようにサイトが見れるはずです!

CloudFrontとXServerをつなぐ
さて、大詰めです。XServer側からCloudFrontにアクセスできるようにしましょう。
XServer側でDNSレコードをもう一つ追加します。
| ホスト名 | ドメイン名。先ほどCloudFomation上でつけたものと同じもの。 | 
| 種別 | CNAME | 
| 内容 | CloudFront上で提示された「ディストリビューションドメイン名」 | 
| TTL | 3600 (デフォルト) | 
| 優先度 | 0 (デフォルト) | 
内容を確認出来たら追加し、みたびの待ちです。ここは他と比べてかなり待つと思います。設定を間違えづらいとも思うので気長に待っていただければと思います。(下手したら1時間以上かかる?)
しばらく待ってからドメインにアクセスすると Hello From AWS! が見えるようになると思います。やり遂げました、設定完了です!
最後に
今回は備忘録もかねてXServerとAWSリソースをつなげる方法を記事にしました。全体を通じて簡単そうに進めていますがかなり迷う点もあったので、今迷っている方への助けになれば幸いです。
ではでは。