nginxでhello worldしてみる

## はじめに
EC2インスタンスにNGINXをインストールし、設定ファイルの確認&ヘルスチェックを通してhello worldしてみました。ミドルウェアの学習の一環として行ったもので備忘録としても記事にします。

## CFnテンプレート
### VPC
```
AWSTemplateFormatVersion: 2010-09-09
Description: VPC with public and private subnets

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: test-vpc

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref AWS::Region
      MapPublicIpOnLaunch: true

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref AWS::Region
      MapPublicIpOnLaunch: true

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.10.0/24
      AvailabilityZone: !Select
        - 0
        - Fn::GetAZs: !Ref AWS::Region       

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.11.0/24
      AvailabilityZone: !Select
        - 1
        - Fn::GetAZs: !Ref AWS::Region

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: test-igw

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-public-crt

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable

  PublicRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway  

Outputs:
  VPCID:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub ${AWS::StackName}-VPCID

  PublicSubnet1ID:
    Description: Public Subnet1 ID
    Value: !Ref PublicSubnet1
    Export:
      Name: !Sub ${AWS::StackName}-public-subnet1-id

  PublicSubnet2ID:
    Description: Public Subnet2 ID
    Value: !Ref PublicSubnet2
    Export:
      Name: !Sub ${AWS::StackName}-public-subnet2-id

  PrivateSubnet1ID:
    Description: Private Subnet1 ID
    Value: !Ref PrivateSubnet1
    Export:
      Name: !Sub ${AWS::StackName}-private-subnet1-id

  PrivateSubnet2ID:
    Description: Private Subnet2 ID
    Value: !Ref PrivateSubnet2
    Export:
      Name: !Sub ${AWS::StackName}-private-subnet2-id      
```
### EC2
インスタンスコネクトのIPを許可しています。
```
AWSTemplateFormatVersion: 2010-09-09
Description: template to launch an EC2 instance

Parameters:
  VPCStack:
    Type: String
    Description: test-vpc
    Default: test-vpc
  EC2AMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"

Resources:
  EC2Instance1A:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2AMI
      InstanceType: t2.micro
      SubnetId: !ImportValue 
        Fn::Sub: "${VPCStack}-public-subnet1-id"
      SecurityGroupIds:
        - !Ref EC2SG

  EC2Instance1C:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2AMI
      InstanceType: t2.micro
      SubnetId: !ImportValue
        Fn::Sub: "${VPCStack}-public-subnet2-id"
      SecurityGroupIds:
        - !Ref EC2SG

  EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP access
      VpcId: !ImportValue 
        Fn::Sub: "${VPCStack}-VPCID"
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 10.0.0.0/16
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 3.112.23.0/29

Outputs:
  EC2Instance1A:
    Value: !Ref EC2Instance1A
    Export:
      Name: !Sub ${AWS::StackName}-EC2Instance1A

  EC2Instance1C:
    Value: !Ref EC2Instance1C
    Export:
      Name: !Sub ${AWS::StackName}-EC2Instance1C
```
### ALB
```
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template to create EC2 instances with Multi-AZ and ELB for load balancing (without Auto Scaling)

Parameters:
  VPCStack:
    Type: String
    Default: test-vpc
  EC2Stack:
    Type: String
    Default: test-ec2

Resources:
  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: "MyLoadBalancer"
      Subnets:
        - !ImportValue 
            Fn::Sub: "${VPCStack}-public-subnet1-id"
        - !ImportValue 
            Fn::Sub: "${VPCStack}-public-subnet2-id"
      SecurityGroups:
        - !Ref LoadBalancerSecurityGroup
      Scheme: internet-facing
  
  LoadBalancerListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Protocol: HTTP
      Port: 80
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref LoadBalancerTargetGroup

  LoadBalancerTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: "MyTargetGroup"
      VpcId: !ImportValue 
        Fn::Sub: "${VPCStack}-VPCID"
      Port: 80
      Protocol: HTTP
      Targets:
        - Id: !ImportValue 
            Fn::Sub: "${EC2Stack}-EC2Instance1A"
        - Id: !ImportValue 
            Fn::Sub: "${EC2Stack}-EC2Instance1C"
      HealthCheckPath: /health

  LoadBalancerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for the Load Balancer
      VpcId: !ImportValue 
        Fn::Sub: "${VPCStack}-VPCID"
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

Outputs:
  LoadBalancerEndpoint:
    Value: !GetAtt LoadBalancer.DNSName
    Export:
      Name: !Sub ${AWS::StackName}-Endpoint
```
## インストール
Amazon Linuxの標準リポジトリにはnginxパッケージがないようで、yumではなくAmazon Linux Extrasからインストールしました。
```
$ sudo amazon-linux-extras install nginx1 -y
$ sudo systemctl enable nginx
```
## 設定ファイルの確認
/etc/nginxにnginx.confがあるので確認しました。
```
$ cat nginx.conf
・
・
・
    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
```
サーバーブロックでドキュメントルートの指定がありました。
```
root /usr/share/nginx/html;: ドキュメントルートの指定。ここにウェブページのファイルが配置されることがわかる
```
## ヘルスチェック
ALBのテンプレートでHealthCheckPath: /healthにしているので、ドキュメントルートにAliveを示すファイルを作成します。
```
cd /usr/share/nginx/html
echo "<html><body>OK</body></html>" | sudo tee /usr/share/nginx/html/health
```
- i-03cda8349312d3c3aのみ追加した結果です
![20250308_000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/82c7e8d1-41cb-4566-96fd-73e5291af810.jpeg)

## Hello World
ドキュメントルートのindex.htmlを以下のように書き換えます。
```
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello, World!</title>
</head>
<body>
    <h1>Hello, World!</h1>
</body>
</html>
```
----
![20250308_000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/c17f820a-f4fe-4b98-9b3e-19f3ca525281.jpeg)