diff --git a/.gitignore b/.gitignore index 8dd04e9..3d828d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -certificates \ No newline at end of file +certificates/ +cli-helpers.md +commit-stack.yml +tmp \ No newline at end of file diff --git a/README.md b/README.md index c7aa5ba..c335866 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,117 @@ + + + +1. Create a VPC and Two Subnets: +``` shell +aws ec2 create-vpc --cidr-block 10.0.0.0/16 +``` +``` shell +aws ec2 create-subnet --vpc-id --cidr-block 10.0.1.0/24 --availability-zone +``` +``` shell +aws ec2 create-subnet --vpc-id --cidr-block 10.0.2.0/24 --availability-zone +``` + Replace with the VPC ID you got in the first command, and replace and with your preferred availability zones. + +2. Create a Network ACL (NACL) and Associate it with Subnets: +``` shell +aws ec2 create-network-acl --vpc-id +``` +``` shell +aws ec2 create-network-acl-entry --network-acl-id --rule-number 100 --protocol tcp --rule-action allow --cidr-block 0.0.0.0/0 --port-range From=80,To=80 +``` +``` shell +aws ec2 create-network-acl-association --network-acl-id --subnet-id +``` +``` shell +aws ec2 create-network-acl-association --network-acl-id --subnet-id +``` + Replace , , and with the appropriate values. + +3. Create an ECS Cluster: +``` shell +aws ecs create-cluster --cluster-name +``` +4. Create a Docker Container with NGINX: + + You will need to create a Dockerfile and build a Docker image with NGINX and your "Hello Commit" page. Once you have the image, you can push it to a container registry like Amazon ECR or Docker Hub. + +5. Deploy the NGINX Container to ECS: + Before deploying, make sure you have an ECS Task Definition and Service configured. Then, use the ECS CLI or AWS Console to create the service and deploy the container to one of your subnets. + +Task Definition: +``` json +{ + "family": "nginx-task", + "containerDefinitions": [ + { + "name": "nginx-container", + "image": "", + "memory": 512, + "cpu": 256, + "essential": true, + "portMappings": [ + { + "containerPort": 80, + "hostPort": 80 + } + ] + } + ] +} +``` + +then, register the task definition: +``` shell +aws ecs register-task-definition --cli-input-json file://nginx-task-definition.json +``` + +Create an ECS Service: + +Create an ECS service that uses the task definition you just registered. Replace , , and other placeholders with your specific values: +``` shell +aws ecs create-service --cluster --service-name nginx-service --task-definition nginx-task --desired-count 1 --launch-type EC2 --scheduling-strategy REPLICA --network-configuration "awsvpcConfiguration={subnets=[]}" +``` +This command will create an ECS service called nginx-service running one instance of your NGINX container in one of your subnets. + +Update Security Groups and Inbound Rules: + + +Create a New Security Group: +To create a new security group that allows incoming traffic on port 80 (HTTP) and 443 (HTTPS), use the following AWS CLI command: +``` shell +aws ec2 create-security-group --group-name my-ecs-sg --description "ECS Security Group" +``` + +Authorize Inbound Traffic on Port 80 and 443: +``` shell +aws ec2 authorize-security-group-ingress --group-id --protocol tcp --port 80 --cidr 0.0.0.0/0 +aws ec2 authorize-security-group-ingress --group-id --protocol tcp --port 443 --cidr 0.0.0.0/0 +``` + + +Associate the Security Group with Your ECS Instances: +To associate the newly created security group with your ECS instances, you'll need to update the launch configuration or task definition associated with your ECS cluster. If you're using AWS Fargate, you can specify the security group in the task definition. If you're using EC2 instances for ECS, make sure to specify the security group when launching or updating the instances. + +For example, when launching EC2 instances with the create-service command, you can use the --launch-type EC2 option and specify the --security-groups parameter with your security group ID: + +``` shell +aws ecs create-service --cluster --service-name nginx-service --task-definition nginx-task --desired-count 1 --launch-type EC2 --network-configuration "awsvpcConfiguration={subnets=[],securityGroups=[]}" +``` + + + +6. Create an RDS Instance (MySQL/PostgreSQL): + +aws rds create-db-instance --db-instance-identifier my-rds-instance --db-instance-class db.t2.micro --engine mysql --master-username --master-user-password --allocated-storage 20 + +7. Configure NGINX to Query the RDS Database: +You'll need to modify your NGINX configuration to connect to the RDS instance and execute queries. This will depend on your NGINX configuration and application logic. + +8. Expose the Service Over HTTPS with a Self-Signed Certificate: +You'll need to create a self-signed certificate and configure NGINX to serve HTTPS requests. This will depend on your NGINX configuration and application logic. Self Signed Certificate: - -openssl genpkey -algorithm RSA -out private-key.pem - this is the private key -openssl req -new -key private-key.pem -x509 -days 365 -out certificate.pem - this is the certificate - +``` shell +openssl genpkey -algorithm RSA -out private-key.pem +openssl req -new -key private-key.pem -x509 -days 365 -out certificate.pem +``` \ No newline at end of file diff --git a/nginx/Dockerfile b/nginx/Dockerfile index fc9f4c9..68906d6 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -1,9 +1,27 @@ -# Use the official NGINX image as the base image -FROM nginx +# Use the official Nginx base image +FROM nginx:latest -# Copy your custom HTML and logo files to the NGINX web root +# Create a directory to store your custom Nginx configuration +RUN mkdir -p /etc/nginx/custom + +# Install MySQL client library (if needed) +# RUN apt-get update && apt-get install -y default-mysql-client + +# Copy your custom HTML and logo files to the Nginx web root COPY index.html /usr/share/nginx/html/ COPY logo.png /usr/share/nginx/html/ -# Expose port 80 for HTTP traffic -EXPOSE 80 \ No newline at end of file +# Copy Nginx configuration file +COPY nginx.conf /etc/nginx/custom/nginx.conf + +# Copy a custom script that will start Nginx and keep it running +COPY start-nginx.sh /usr/local/bin/start-nginx.sh + +# Make the script executable +RUN chmod +x /usr/local/bin/start-nginx.sh + +# Expose port 80 for incoming HTTP traffic +EXPOSE 80 + +# Define the command to start Nginx using your custom script +CMD ["/usr/local/bin/start-nginx.sh"] diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..214b661 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + } + + # Other server block configurations... +} \ No newline at end of file diff --git a/nginx/start-nginx.sh b/nginx/start-nginx.sh new file mode 100644 index 0000000..0baa32a --- /dev/null +++ b/nginx/start-nginx.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Start Nginx in the foreground +nginx -g "daemon off;" diff --git a/service/nginx-task-definition.json b/service/nginx-task-definition.json new file mode 100644 index 0000000..0994c3a --- /dev/null +++ b/service/nginx-task-definition.json @@ -0,0 +1,18 @@ +{ + "family": "nginx-task", + "containerDefinitions": [ + { + "name": "nginx-container", + "image": "", + "memory": 512, + "cpu": 256, + "essential": true, + "portMappings": [ + { + "containerPort": 80, + "hostPort": 80 + } + ] + } + ] +} diff --git a/vpc-subnets-stack.yml b/vpc-subnets-stack.yml index d2a2833..aeceb0f 100644 --- a/vpc-subnets-stack.yml +++ b/vpc-subnets-stack.yml @@ -1,22 +1,26 @@ AWSTemplateFormatVersion: "2010-09-09" +Parameters: + NginxImage: + Type: String + Default: 539634357948.dkr.ecr.eu-central-1.amazonaws.com/commit-nginx:latest Resources: VPC: - Type: AWS::EC2::VPC # or AWS::RDS::DBSubnetGroup - Properties: # or Properties - CidrBlock: 10.0.0.0/16 # this is the VPC CIDR block (CIDR = Classless Inter-Domain Routing, it means you can use 0.0.0.0/0 for all IPs) - EnableDnsSupport: true # Enable DNS hostnames (EnableDnsSupport is true by default) - EnableDnsHostnames: true # Enable DNS hostnames (EnableDnsHostnames is true by default) + Type: AWS::EC2::VPC + Properties: + CidrBlock: 10.0.0.0/16 + EnableDnsSupport: true + EnableDnsHostnames: true SubnetA: - Type: AWS::EC2::Subnet # this subnet is for the ECS instances (webserver) + Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC - CidrBlock: 10.0.0.0/24 # this is the subnet CIDR block it means that you can use 10.0.0.0/24 + CidrBlock: 10.0.0.0/24 AvailabilityZone: eu-central-1a SubnetB: - Type: AWS::EC2::Subnet # this subnet is for the RDS + Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 @@ -37,7 +41,7 @@ Resources: PortRange: From: 443 To: 443 - Egress: false # Egress means outbound + Egress: false CidrBlock: 0.0.0.0/0 InboundRuleHttp: @@ -50,7 +54,7 @@ Resources: PortRange: From: 80 To: 80 - Egress: false # Egress means outbound + Egress: false CidrBlock: 0.0.0.0/0 OutboundRuleHttps: @@ -84,14 +88,14 @@ Resources: Properties: AllocatedStorage: 20 DBInstanceClass: db.t2.micro - Engine: mysql # or postgres + Engine: mysql MasterUsername: root_user MasterUserPassword: root_password DBName: root_db MultiAZ: false ECSCluster: - Type: AWS::ECS::Cluster # this ECSCluster is to run the ECS tasks + Type: AWS::ECS::Cluster ECSTaskDefinition: Type: AWS::ECS::TaskDefinition @@ -105,9 +109,9 @@ Resources: Memory: 0.5GB Family: !Ref ECSCluster ContainerDefinitions: - - Name: commit-nginx - Image: 539634357948.dkr.ecr.eu-central-1.amazonaws.com/commit-nginx:latest - Memory: 512 # Specify memory here (in MiB) + - Name: commit-stack # Updated application name to "commit-stack" + Image: !Ref NginxImage + Memory: 512 PortMappings: - ContainerPort: 80 - ContainerPort: 443 @@ -117,9 +121,9 @@ Resources: Properties: Cluster: !Ref ECSCluster LoadBalancers: - - ContainerName: commit-nginx + - ContainerName: commit-stack # Updated container name ContainerPort: 80 - LoadBalancerName: !GetAtt LoadBalancer.Name + LoadBalancerName: !Ref LoadBalancer TaskDefinition: !Ref ECSTaskDefinition DesiredCount: 1 LaunchType: EC2 @@ -128,19 +132,14 @@ Resources: Subnets: - !Ref SubnetA - !Ref SubnetB - DependsOn: - - "LoadBalancer" - LoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: "Commit-elb" LoadBalancerAttributes: - # this is the default, but is specified here in case it needs to be changed - Key: idle_timeout.timeout_seconds Value: 60 - # "internal" is also an option Scheme: internet-facing Subnets: - !Ref SubnetA @@ -183,9 +182,7 @@ Resources: InternetGatewayId: !Ref MyInternetGateway VpcId: !Ref VPC - - - ListenerHTTPS: + ListenerHTTP: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: @@ -194,14 +191,11 @@ Resources: LoadBalancerArn: !Ref LoadBalancer Port: 80 Protocol: HTTP - # Certificates: - # - CertificateArn: "arn:aws:acm:eu-central-1:539634357948:certificate/584cfb24-bc7a-431b-9150-16d47bdb8ea9" TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 10 - # will look for a 200 status code by default unless specified otherwise HealthCheckPath: "/" HealthCheckTimeoutSeconds: 5 UnhealthyThresholdCount: 2 @@ -211,6 +205,6 @@ Resources: Protocol: HTTP TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds - Value: 60 # default is 300 + Value: 60 TargetType: ip VpcId: !Ref VPC