Deploy a NGINX server on private EC2 server and proxy it via REST API

Create a REST API which acts as a proxy for a NGINX server hosted on a Amazon Elastic Compute Cloud (Amazon EC2)

VPCAPI GatewayNetwork Load BalancerEC2
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  (uksb-1tthgi812) (tag:apigw-ec2)
  This CloudFormation deploys public REST API along with private network load balancer which will route the request to an EC2 website via vpc link
Parameters:
  InstanceType:
    Type: String
    Description: Select an instance type
    Default: t2.micro
    AllowedValues: [c4.2xlarge, c4.4xlarge, c4.8xlarge, c4.large, c4.xlarge, c5.12xlarge, c5.18xlarge, c5.24xlarge, c5.2xlarge, c5.4xlarge, c5.9xlarge, c5.large, c5.metal, c5.xlarge, c5a.12xlarge, c5a.16xlarge, c5a.24xlarge, c5a.2xlarge, c5a.4xlarge, c5a.8xlarge, c5a.large, c5a.xlarge, c5d.12xlarge, c5d.18xlarge, c5d.24xlarge, c5d.2xlarge, c5d.4xlarge, c5d.9xlarge, c5d.large, c5d.metal, c5d.xlarge, c5n.18xlarge, c5n.2xlarge, c5n.4xlarge, c5n.9xlarge, c5n.large, c5n.metal, c5n.xlarge, c6g.12xlarge, c6g.16xlarge, c6g.2xlarge, c6g.4xlarge, c6g.8xlarge, c6g.large, c6g.medium, c6g.metal, c6g.xlarge, c6gd.12xlarge, c6gd.16xlarge, c6gd.2xlarge, c6gd.4xlarge, c6gd.8xlarge, c6gd.large, c6gd.medium, c6gd.metal, c6gd.xlarge, c6gn.12xlarge, c6gn.16xlarge, c6gn.2xlarge, c6gn.4xlarge, c6gn.8xlarge, c6gn.large, c6gn.medium, c6gn.xlarge, c6i.12xlarge, c6i.16xlarge, c6i.24xlarge, c6i.2xlarge, c6i.32xlarge, c6i.4xlarge, c6i.8xlarge, c6i.large, c6i.metal, c6i.xlarge, d2.2xlarge, d2.4xlarge, d2.8xlarge, d2.xlarge, d3.2xlarge, d3.4xlarge, d3.8xlarge, d3.xlarge, g3.16xlarge, g3.4xlarge, g3.8xlarge, g4ad.16xlarge, g4ad.2xlarge, g4ad.4xlarge, g4ad.8xlarge, g4ad.xlarge, g4dn.12xlarge, g4dn.16xlarge, g4dn.2xlarge, g4dn.4xlarge, g4dn.8xlarge, g4dn.metal, g4dn.xlarge, g5.12xlarge, g5.16xlarge, g5.24xlarge, g5.2xlarge, g5.48xlarge, g5.4xlarge, g5.8xlarge, g5.xlarge, i3.16xlarge, i3.2xlarge, i3.4xlarge, i3.8xlarge, i3.large, i3.metal, i3.xlarge, i3en.12xlarge, i3en.24xlarge, i3en.2xlarge, i3en.3xlarge, i3en.6xlarge, i3en.large, i3en.metal, i3en.xlarge, i4i.16xlarge, i4i.2xlarge, i4i.32xlarge, i4i.4xlarge, i4i.8xlarge, i4i.large, i4i.metal, i4i.xlarge, im4gn.16xlarge, im4gn.2xlarge, im4gn.4xlarge, im4gn.8xlarge, im4gn.large, im4gn.xlarge, inf1.24xlarge, inf1.2xlarge, inf1.6xlarge, inf1.xlarge, is4gen.2xlarge, is4gen.4xlarge, is4gen.8xlarge, is4gen.large, is4gen.medium, is4gen.xlarge, m4.10xlarge, m4.16xlarge, m4.2xlarge, m4.4xlarge, m4.large, m4.xlarge, m5.12xlarge, m5.16xlarge, m5.24xlarge, m5.2xlarge, m5.4xlarge, m5.8xlarge, m5.large, m5.metal, m5.xlarge, m5a.12xlarge, m5a.16xlarge, m5a.24xlarge, m5a.2xlarge, m5a.4xlarge, m5a.8xlarge, m5a.large, m5a.xlarge, m5ad.12xlarge, m5ad.16xlarge, m5ad.24xlarge, m5ad.2xlarge, m5ad.4xlarge, m5ad.8xlarge, m5ad.large, m5ad.xlarge, m5d.12xlarge, m5d.16xlarge, m5d.24xlarge, m5d.2xlarge, m5d.4xlarge, m5d.8xlarge, m5d.large, m5d.metal, m5d.xlarge, m6g.12xlarge, m6g.16xlarge, m6g.2xlarge, m6g.4xlarge, m6g.8xlarge, m6g.large, m6g.medium, m6g.metal, m6g.xlarge, m6i.12xlarge, m6i.16xlarge, m6i.24xlarge, m6i.2xlarge, m6i.32xlarge, m6i.4xlarge, m6i.8xlarge, m6i.large, m6i.metal, m6i.xlarge, p3.16xlarge, p3.2xlarge, p3.8xlarge, r4.16xlarge, r4.2xlarge, r4.4xlarge, r4.8xlarge, r4.large, r4.xlarge, r5.12xlarge, r5.16xlarge, r5.24xlarge, r5.2xlarge, r5.4xlarge, r5.8xlarge, r5.large, r5.metal, r5.xlarge, r5a.12xlarge, r5a.16xlarge, r5a.24xlarge, r5a.2xlarge, r5a.4xlarge, r5a.8xlarge, r5a.large, r5a.xlarge, r5ad.12xlarge, r5ad.16xlarge, r5ad.24xlarge, r5ad.2xlarge, r5ad.4xlarge, r5ad.8xlarge, r5ad.large, r5ad.xlarge, r5b.12xlarge, r5b.16xlarge, r5b.24xlarge, r5b.2xlarge, r5b.4xlarge, r5b.8xlarge, r5b.large, r5b.metal, r5b.xlarge, r5d.12xlarge, r5d.16xlarge, r5d.24xlarge, r5d.2xlarge, r5d.4xlarge, r5d.8xlarge, r5d.large, r5d.metal, r5d.xlarge, r5n.12xlarge, r5n.16xlarge, r5n.24xlarge, r5n.2xlarge, r5n.4xlarge, r5n.8xlarge, r5n.large, r5n.metal, r5n.xlarge, r6g.12xlarge, r6g.16xlarge, r6g.2xlarge, r6g.4xlarge, r6g.8xlarge, r6g.large, r6g.medium, r6g.metal, r6g.xlarge, r6gd.12xlarge, r6gd.16xlarge, r6gd.2xlarge, r6gd.4xlarge, r6gd.8xlarge, r6gd.large, r6gd.medium, r6gd.metal, r6gd.xlarge, r6i.12xlarge, r6i.16xlarge, r6i.24xlarge, r6i.2xlarge, r6i.32xlarge, r6i.4xlarge, r6i.8xlarge, r6i.large, r6i.metal, r6i.xlarge, t2.2xlarge, t2.large, t2.medium, t2.micro, t2.nano, t2.small, t2.xlarge, t3.2xlarge, t3.large, t3.medium, t3.micro, t3.nano, t3.small, t3.xlarge, t3a.2xlarge, t3a.large, t3a.medium, t3a.micro, t3a.nano, t3a.small, t3a.xlarge, t4g.2xlarge, t4g.large, t4g.medium, t4g.micro, t4g.nano, t4g.small, t4g.xlarge, u-3tb1.56xlarge, u-6tb1.112xlarge, u-6tb1.56xlarge, x1.16xlarge, x1.32xlarge, x1e.16xlarge, x1e.2xlarge, x1e.32xlarge, x1e.4xlarge, x1e.8xlarge, x1e.xlarge, x2idn.16xlarge, x2idn.24xlarge, x2idn.32xlarge, x2idn.metal, x2iedn.16xlarge, x2iedn.24xlarge, x2iedn.2xlarge, x2iedn.32xlarge, x2iedn.4xlarge, x2iedn.8xlarge, x2iedn.metal, x2iedn.xlarge, c5ad.12xlarge, c5ad.16xlarge, c5ad.24xlarge, c5ad.2xlarge, c5ad.4xlarge, c5ad.8xlarge, c5ad.large, c5ad.xlarge, c6a.12xlarge, c6a.16xlarge, c6a.24xlarge, c6a.2xlarge, c6a.32xlarge, c6a.48xlarge, c6a.4xlarge, c6a.8xlarge, c6a.large, c6a.metal, c6a.xlarge, c6id.12xlarge, c6id.16xlarge, c6id.24xlarge, c6id.2xlarge, c6id.32xlarge, c6id.4xlarge, c6id.8xlarge, c6id.large, c6id.metal, c6id.xlarge, c6in.12xlarge, c6in.16xlarge, c6in.24xlarge, c6in.2xlarge, c6in.32xlarge, c6in.4xlarge, c6in.8xlarge, c6in.large, c6in.xlarge, c7g.12xlarge, c7g.16xlarge, c7g.2xlarge, c7g.4xlarge, c7g.8xlarge, c7g.large, c7g.medium, c7g.metal, c7g.xlarge, d3en.12xlarge, d3en.2xlarge, d3en.4xlarge, d3en.6xlarge, d3en.8xlarge, d3en.xlarge, dl1.24xlarge, f1.16xlarge, f1.2xlarge, f1.4xlarge, g3s.xlarge, g5g.16xlarge, g5g.2xlarge, g5g.4xlarge, g5g.8xlarge, g5g.metal, g5g.xlarge, h1.16xlarge, h1.2xlarge, h1.4xlarge, h1.8xlarge, m5dn.12xlarge, m5dn.16xlarge, m5dn.24xlarge, m5dn.2xlarge, m5dn.4xlarge, m5dn.8xlarge, m5dn.large, m5dn.metal, m5dn.xlarge, m5n.12xlarge, m5n.16xlarge, m5n.24xlarge, m5n.2xlarge, m5n.4xlarge, m5n.8xlarge, m5n.large, m5n.metal, m5n.xlarge, m5zn.12xlarge, m5zn.2xlarge, m5zn.3xlarge, m5zn.6xlarge, m5zn.large, m5zn.metal, m5zn.xlarge, m6a.12xlarge, m6a.16xlarge, m6a.24xlarge, m6a.2xlarge, m6a.32xlarge, m6a.48xlarge, m6a.4xlarge, m6a.8xlarge, m6a.large, m6a.metal, m6a.xlarge, m6gd.12xlarge, m6gd.16xlarge, m6gd.2xlarge, m6gd.4xlarge, m6gd.8xlarge, m6gd.large, m6gd.medium, m6gd.metal, m6gd.xlarge, m6id.12xlarge, m6id.16xlarge, m6id.24xlarge, m6id.2xlarge, m6id.32xlarge, m6id.4xlarge, m6id.8xlarge, m6id.large, m6id.metal, m6id.xlarge, m6idn.12xlarge, m6idn.16xlarge, m6idn.24xlarge, m6idn.2xlarge, m6idn.32xlarge, m6idn.4xlarge, m6idn.8xlarge, m6idn.large, m6idn.xlarge, m6in.12xlarge, m6in.16xlarge, m6in.24xlarge, m6in.2xlarge, m6in.32xlarge, m6in.4xlarge, m6in.8xlarge, m6in.large, m6in.xlarge, m7g.12xlarge, m7g.16xlarge, m7g.2xlarge, m7g.4xlarge, m7g.8xlarge, m7g.large, m7g.medium, m7g.metal, m7g.xlarge, mac1.metal, mac2.metal, p2.16xlarge, p2.8xlarge, p2.xlarge, p3dn.24xlarge, p4d.24xlarge, r5dn.12xlarge, r5dn.16xlarge, r5dn.24xlarge, r5dn.2xlarge, r5dn.4xlarge, r5dn.8xlarge, r5dn.large, r5dn.metal, r5dn.xlarge, r6a.12xlarge, r6a.16xlarge, r6a.24xlarge, r6a.2xlarge, r6a.32xlarge, r6a.48xlarge, r6a.4xlarge, r6a.8xlarge, r6a.large, r6a.metal, r6a.xlarge, r6id.12xlarge, r6id.16xlarge, r6id.24xlarge, r6id.2xlarge, r6id.32xlarge, r6id.4xlarge, r6id.8xlarge, r6id.large, r6id.metal, r6id.xlarge, r6idn.12xlarge, r6idn.16xlarge, r6idn.24xlarge, r6idn.2xlarge, r6idn.32xlarge, r6idn.4xlarge, r6idn.8xlarge, r6idn.large, r6idn.xlarge, r6in.12xlarge, r6in.16xlarge, r6in.24xlarge, r6in.2xlarge, r6in.32xlarge, r6in.4xlarge, r6in.8xlarge, r6in.large, r6in.xlarge, r7g.12xlarge, r7g.16xlarge, r7g.2xlarge, r7g.4xlarge, r7g.8xlarge, r7g.large, r7g.medium, r7g.metal, r7g.xlarge, trn1.2xlarge, trn1.32xlarge, u-12tb1.112xlarge, u-18tb1.112xlarge, u-24tb1.112xlarge, u-9tb1.112xlarge, vt1.24xlarge, vt1.3xlarge, vt1.6xlarge, x2gd.12xlarge, x2gd.16xlarge, x2gd.2xlarge, x2gd.4xlarge, x2gd.8xlarge, x2gd.large, x2gd.medium, x2gd.metal, x2gd.xlarge, x2iezn.12xlarge, x2iezn.2xlarge, x2iezn.4xlarge, x2iezn.6xlarge, x2iezn.8xlarge, x2iezn.metal, z1d.12xlarge, z1d.2xlarge, z1d.3xlarge, z1d.6xlarge, z1d.large, z1d.metal, z1d.xlarge, hpc6a.48xlarge, hpc6id.32xlarge]

  KeyPair:
    Description: Select the key pair 
    Type: AWS::EC2::KeyPair::KeyName

  VPC:
    Description: Please select if you want to use existing VPC
    Type: AWS::EC2::VPC::Id
  
  PrivateSubnetIDs: 
    Description: Private Subnet IDs for VPCE
    Type: "List<AWS::EC2::Subnet::Id>"

  SecurityGroupIDsForNLBAndEC2: 
    Description: Security group IDs for NLB and EC2. Note - please make sure that the security group allows traffic on port 80 from VPC Cidr or 0.0.0.0
    Type: "List<AWS::EC2::SecurityGroup::Id>"
  
  RouteTableId:
    Description: PrivateSubnets route table Id
    Type: String


Mappings:
  RegionMap:
    us-east-1:
      AMI: ami-0dfcb1ef8550277af
    us-east-2:
      AMI: ami-0cc87e5027adcdca8
    us-west-1:
      AMI: ami-00569e54da628d17c
    us-west-2:
      AMI: ami-0f1a5f5ada0e7da53
    ap-southeast-4:
      AMI: ami-0272ee0cbe63bb8e8
    ap-east-1:
      AMI: ami-0e679816c1d0be6df
    ap-south-2:
      AMI: ami-0155ae3341da656ae
    ap-south-1:
      AMI: ami-0e742cca61fb65051
    ap-northeast-3:
      AMI: ami-090ae0a4750988734
    ap-northeast-2:
      AMI: ami-0f6e451b865011317
    ca-central-1:
      AMI: ami-099effcf516c942b7
    eu-north-1:
      AMI: ami-0bb935e4614c12d86
    eu-west-1:
      AMI: ami-06e0ce9d3339cb039
    eu-west-2:
      AMI: ami-09ee0944866c73f62
    eu-west-3:
      AMI: ami-00575c0cbc20caf50
    eu-central-1:
      AMI: ami-0c0d3776ef525d5dd
    ap-southeast-1:
      AMI: ami-0f2eac25772cd4e36
    ap-southeast-2:
      AMI: ami-0692dea0a2f8a1b35
    ap-northeast-1:
      AMI: ami-0ffac3e16de16665e
    sa-east-1:
      AMI: ami-01fc9174dd9330556
    af-south-1:
      AMI: ami-0d4fd6ba7ffe8260e
    ap-southeast-3:
      AMI: ami-0ebaeda1c62cceddb
    eu-west-3:
      AMI: ami-00575c0cbc20caf50
    eu-south-2:
      AMI: ami-089ea1de61e0c9c18
    me-south-1:
      AMI: ami-06131a860e2930b5c
    me-central-1:
      AMI: ami-0c30c5d64bef7fade
    

Resources:
  VPCE:
    Type: AWS::EC2::VPCEndpoint
    Properties: 
      RouteTableIds: 
        - !Ref RouteTableId
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      VpcEndpointType: Gateway
      VpcId: !Ref VPC

  EC2:
    Type: AWS::EC2::Instance
    DependsOn: ApiGatewayModel
    Properties:
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyPair
      ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
      SecurityGroupIds: !Ref SecurityGroupIDsForNLBAndEC2
      SubnetId: !Select [0, !Ref PrivateSubnetIDs]
      UserData:
        Fn::Base64:
          !Sub  |
            #!/bin/bash
            yum update -y
            sudo amazon-linux-extras install nginx1 -y
            sudo systemctl enable --now nginx
      Tags:
        - Key: Name
          Value: priv

  NetworkLoadBalancer:
    DependsOn:  EC2
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties: 
      Name: NLB
      Scheme: internal
      Subnets:
        - !Select [0, !Ref PrivateSubnetIDs]
        - !Select [1, !Ref PrivateSubnetIDs]
      Type: network
  
  NetworkLoadBalancerTargetGroup:
    DependsOn:  EC2
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 80
      Name: NLBTargetGroup
      HealthCheckEnabled: true
      Protocol: TCP
      VpcId: !Ref VPC
      Targets:
        - Id: !GetAtt EC2.PrivateIp
          Port: 80
      TargetType: ip
  
  NetworkLoadBalancerListener:
    DependsOn: NetworkLoadBalancerTargetGroup
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup
      LoadBalancerArn: !Ref NetworkLoadBalancer
      Port: '80'
      Protocol: TCP

  ApiGatewayRestApi:
    Type: 'AWS::ApiGateway::RestApi'
    DependsOn: VPCE
    Properties:
      ApiKeySourceType: HEADER
      Description: An API Gateway to connect to ec2 server
      Name: PublicApiViaCFN
      EndpointConfiguration:
        Types:
          - REGIONAL
  
  ApiGatewayGetMethod:
    DependsOn: VPCLink
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      AuthorizationType: NONE
      Integration:
        ConnectionType: VPC_LINK
        ConnectionId: "${stageVariables.vpclink}"
        IntegrationHttpMethod: GET
        PassthroughBehavior: WHEN_NO_MATCH
        TimeoutInMillis: 10000
        Type: HTTP_PROXY
        Uri: !Sub 
              - "http://${privateIP}"
              - privateIP: !GetAtt EC2.PrivateIp
      ResourceId: !GetAtt ApiGatewayRestApi.RootResourceId
      RestApiId: !Ref ApiGatewayRestApi
  
  ApiGatewayModel:
    DependsOn: ApiGatewayRestApi
    Type: AWS::ApiGateway::Model
    Properties:
      ContentType: 'application/json'
      RestApiId: !Ref ApiGatewayRestApi
      Schema: {}
  
  ApiGatewayStage:
    Type: AWS::ApiGateway::Stage
    DependsOn: ApiGatewayDeployment
    Properties:
      DeploymentId: !Ref ApiGatewayDeployment
      Description: API Stage v0
      RestApiId: !Ref ApiGatewayRestApi
      StageName: 'v0'
      Variables:
        vpclink: !Ref VPCLink
  
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: ApiGatewayGetMethod
    Properties:
      RestApiId: !Ref ApiGatewayRestApi
 
  VPCLink:
    Type: AWS::ApiGateway::VpcLink
    DependsOn: NetworkLoadBalancer
    Properties: 
      Name: NLB
      TargetArns:
        - !Join
            - ''
            - - 'arn:aws:elasticloadbalancing:'
              - !Ref AWS::Region
              - ':'
              - !Ref AWS::AccountId
              - ':loadbalancer/'
              - !GetAtt NetworkLoadBalancer.LoadBalancerFullName


Outputs:
  WebsiteURL:
    Value: !Sub 
            - "curl https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com/v0"
            - ApiId: !Ref ApiGatewayRestApi
    Description: ApiGateway URL

Download

git clone https://github.com/aws-samples/serverless-patterns
cd serverless-patterns/apigw-ec2

Pattern repository

View on GitHub

Last updated on 26 Dec 2024

Edit this page