├── .gitignore ├── .gitmodules ├── Account Basics ├── create_groups-users.yml └── information.md ├── Auto Scaling └── Auto Scaling │ ├── common.yml │ ├── group_vars │ └── all.yaml │ ├── roles │ └── common │ │ └── tasks │ │ └── main.yml │ └── site.yml ├── External Data ├── Part 1 │ ├── common.yml │ ├── group_vars │ │ └── all.yaml │ ├── roles │ │ └── common │ │ │ └── tasks │ │ │ └── main.yml │ └── site.yml ├── dynamodb.sh ├── item.json ├── items.json └── key.json ├── README.md └── Web Hosting Basics ├── Part 1 ├── common.yml ├── group_vars │ └── all.yaml ├── roles │ ├── common │ │ └── tasks │ │ │ └── main.yml │ └── webserver │ │ ├── files │ │ ├── fortunesite.service │ │ └── nginx.conf │ │ └── tasks │ │ └── main.yml ├── site.yml └── webserver.yml └── Part 2 ├── common.yml ├── group_vars └── all.yaml ├── roles └── common │ └── tasks │ └── main.yml └── site.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | *.retry 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "FortuneSite"] 2 | path = FortuneSite 3 | url = https://github.com/Just-Insane/FortuneSite 4 | -------------------------------------------------------------------------------- /Account Basics/create_groups-users.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | connection: local 3 | gather_facts: False 4 | 5 | tasks: 6 | 7 | - name: Create a new Group 8 | iam: 9 | iam_type: group 10 | name: "{{ item }}" 11 | state: present 12 | with_items: 13 | - testgroup 14 | register: new_groups 15 | 16 | - name: Create two new IAM users with API keys 17 | iam: 18 | iam_type: user 19 | name: "{{ item }}" 20 | state: present 21 | password: "TempP@ssw0rd008" 22 | access_key_state: create 23 | groups: testgroup 24 | with_items: 25 | - jcleese 26 | - mpython -------------------------------------------------------------------------------- /Account Basics/information.md: -------------------------------------------------------------------------------- 1 | # Information 2 | ## Account Basics 3 | 4 | Most of the steps in this part are hard to show programatically, as they require using the root account and deleting API keys, ect. These parts were done manually, except for the creation of example users and groups. 5 | 6 | AWS CLI is configured and able to connect to AWS on host machine. -------------------------------------------------------------------------------- /Auto Scaling/Auto Scaling/common.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | roles: 4 | - common -------------------------------------------------------------------------------- /Auto Scaling/Auto Scaling/group_vars/all.yaml: -------------------------------------------------------------------------------- 1 | key_name: Justin-YubiKey 2 | instance_type: t2.micro 3 | security_group: webserver 4 | subnet: subnet-06dd7a6e 5 | image: ami-49f0762d 6 | region: ca-central-1 -------------------------------------------------------------------------------- /Auto Scaling/Auto Scaling/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Get EC2 Instance Facts 2 | ec2_instance_facts: 3 | filters: 4 | "tag:Name": webserver 5 | "instance-state-name": running 6 | register: ec2facts 7 | 8 | - name: Snapshot Instance 9 | ec2_snapshot: 10 | instance_id: "{{ item.instance_id }}" 11 | device_name: /dev/sda1 12 | region: "{{ region }}" 13 | description: Snapshot of created webserver 14 | snapshot_tags: 15 | Name: webserver 16 | Software: nginx 17 | with_items: "{{ ec2facts.instances }}" 18 | 19 | - name: Get Snapshot facts 20 | ec2_snapshot_facts: 21 | filters: 22 | "tag:Name": webserver 23 | "tag:Software": nginx 24 | register: snapshot 25 | 26 | - name: Terminate instances after snapshot 27 | ec2: 28 | state: 'absent' 29 | region: "{{ region }}" 30 | instance_id: "{{ item.instance_id }}" 31 | with_items: "{{ ec2facts.instances }}" 32 | 33 | - name: Create AMI Registration 34 | ec2_ami: 35 | name: autoscaling-AMI 36 | state: present 37 | architecture: x86_64 38 | virtualization_type: hvm 39 | root_device_name: /dev/sda1 40 | device_mapping: 41 | - device_name: /dev/sda1 42 | size: 10 43 | snapshot_id: "{{ item.snapshot_id }}" 44 | delete_on_termination: true 45 | volume_type: gp2 46 | with_items: "{{ snapshot.snapshots }}" 47 | register: image 48 | 49 | - local_action: 50 | module: ec2_elb_lb 51 | name: "autoscalling-lb" 52 | state: present 53 | region: "{{ region }}" 54 | zones: 55 | - ca-central-1a 56 | - ca-central-1b 57 | listeners: 58 | - protocol: http 59 | load_balancer_port: 80 60 | instance_port: 80 61 | 62 | - name: create launch config 63 | ec2_lc: 64 | name: autoscaling-lc 65 | image_id: "{{ item.image_id }}" 66 | key_name: "{{ key_name }}" 67 | region: "{{ region }}" 68 | security_groups: "{{ security_group }}" 69 | instance_type: "{{ instance_type }}" 70 | assign_public_ip: yes 71 | instance_profile_name: arn:aws:iam::388750927632:instance-profile/DynamoDB-Admin 72 | with_items: "{{ image.results }}" 73 | 74 | - ec2_vpc_subnet_facts: 75 | register: subnet_facts 76 | 77 | - ec2_asg: 78 | name: autoscaling-asg 79 | launch_config_name: autoscaling-lc 80 | load_balancers: [ 'autoscalling-lb' ] 81 | health_check_period: 60 82 | health_check_type: ELB 83 | replace_all_instances: yes 84 | min_size: 2 85 | max_size: 2 86 | desired_capacity: 2 87 | region: "{{ region }}" 88 | vpc_zone_identifier: [ "{{ subnet_facts.subnets[0].id }}", "{{ subnet_facts.subnets[1].id }}" ] 89 | wait_timeout: 1500 90 | tags: 91 | - environment: production -------------------------------------------------------------------------------- /Auto Scaling/Auto Scaling/site.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | 4 | - import_playbook: common.yml -------------------------------------------------------------------------------- /External Data/Part 1/common.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | roles: 4 | - common -------------------------------------------------------------------------------- /External Data/Part 1/group_vars/all.yaml: -------------------------------------------------------------------------------- 1 | key_name: Justin-YubiKey 2 | instance_type: t2.micro 3 | security_group: webserver 4 | subnet: subnet-06dd7a6e 5 | image: ami-49f0762d 6 | region: ca-central-1 -------------------------------------------------------------------------------- /External Data/Part 1/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Create Fortune-of-the-day DynamoDB Table 2 | dynamodb_table: 3 | name: FortuneList 4 | region: "{{ region }}" 5 | hash_key_name: FortuneID 6 | hash_key_type: STRING 7 | read_capacity: 2 8 | write_capacity: 2 -------------------------------------------------------------------------------- /External Data/Part 1/site.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | 4 | - import_playbook: common.yml -------------------------------------------------------------------------------- /External Data/dynamodb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws dynamodb create-table --table-name FortuneList --attribute-definitions AttributeName=FortuneID,AttributeType=S --key-schema AttributeName=FortuneID,KeyType=HASH --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 4 | 5 | aws dynamodb wait table-exists --table-name FortuneList 6 | 7 | aws dynamodb put-item --table-name FortuneList --item file://item.json 8 | 9 | aws dynamodb batch-write-item --request-items file://items.json 10 | 11 | aws dynamodb get-item --table-name FortuneList --key file://key.json 12 | -------------------------------------------------------------------------------- /External Data/item.json: -------------------------------------------------------------------------------- 1 | { 2 | "FortuneID": {"S": "fortune0001"}, 3 | "Fortune": {"S": "It will be cold tomorrow"} 4 | } 5 | -------------------------------------------------------------------------------- /External Data/items.json: -------------------------------------------------------------------------------- 1 | { 2 | "FortuneList": [ 3 | { 4 | "PutRequest": { 5 | "Item": { 6 | "FortuneID": {"S": "fortune0002"}, 7 | "Fortune": {"S": "It will rain tomorrow."} 8 | } 9 | } 10 | }, 11 | { 12 | "PutRequest": { 13 | "Item": { 14 | "FortuneID": {"S": "fortune0003"}, 15 | "Fortune": {"S": "It will be a great day!"} 16 | } 17 | } 18 | }, 19 | { 20 | "PutRequest": { 21 | "Item": { 22 | "FortuneID": {"S": "fortune0004"}, 23 | "Fortune": {"S": "It will snow tomorrow"} 24 | } 25 | } 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /External Data/key.json: -------------------------------------------------------------------------------- 1 | { 2 | "FortuneID": {"S": "fortune0002"} 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS-Automation 2 | 3 | ## Information: 4 | Automating AWS deployment of guide: https://www.reddit.com/r/sysadmin/comments/8inzn5/so_you_want_to_learn_aws_aka_how_do_i_learn_to_be/ 5 | 6 | ### Introduction 7 | 8 | So many people struggle with where to get started with AWS and cloud technologies in general. There is popular "How do I learn to be a Linux admin?" post that inspired me to write an equivalent for cloud technologies. This post serves as a guide of goals to grow from basic AWS knowledge to understanding and deploying complex architectures in an automated way. Feel free to pick up where you feel relevant based on prior experience. 9 | 10 | ### Assumptions: 11 | 12 | * You have basic-to-moderate Linux systems administration skills 13 | * You are at least familiar with programming/scripting. You don't need to be a whiz but you should have some decent hands-on experience automating and programming. 14 | * You are willing to dedicate the time to overcome complex issues. 15 | * You have an AWS Account and a marginal amount of money to spend improving your skills. 16 | 17 | ### How to use this guide: 18 | 19 | * This is not a step by step how-to guide. 20 | * You should take each goal and "figure it out". I have hints to guide you in the right direction. 21 | * Google is your friend. AWS Documentation is your friend. Stack Overflow is your friend. 22 | * Find out and implement the "right way", not the quick way. Ok, maybe do the quick way first then refactor to the right way before moving on. 23 | * Shut down or de-provision as much as you can between learning sessions. You should be able to do everything in this guide for literally less than $50 using the AWS Free Tier. Rebuilding often will reinforce concepts anyway. 24 | * Skip ahead and read the Cost Analysis and Automation sections and have them in the back of your mind as you work through the goals. 25 | * Lastly, just get hands on, no better time to start then NOW. 26 | 27 | ### Project Overview 28 | 29 | This is NOT a guide on how to develop websites on AWS. This uses a website as an excuse to use all the technologies AWS puts at your fingertips. The concepts you will learn going through these exercises apply all over AWS. 30 | 31 | This guide takes you through a maturity process from the most basic webpage to an extremely cheap scalable web application. The small app you will build does not matter. It can do anything you want, just keep it simple. 32 | 33 | Need an idea? Here: Fortune-of-the-Day - Display a random fortune each page load, have a box at the bottom and a submit button to add a new fortune to the random fortune list. 34 | 35 | #### Account Basics 36 | 37 | * Create an IAM user for your personal use. 38 | * Set up MFA for your root user, turn off all root user API keys. 39 | * Set up Billing Alerts for anything over a few dollars. 40 | * Configure the AWS CLI for your user using API credentials. 41 | * _Checkpoint: You can use the AWS CLI to interrogate information about your AWS account._ 42 | 43 | #### Web Hosting Basics 44 | 45 | * Deploy a EC2 VM and host a simple static "Fortune-of-the-Day Coming Soon" web page. 46 | * Take a snapshot of your VM, delete the VM, and deploy a new one from the snapshot. Basically disk backup + disk restore. 47 | * _Checkpoint: You can view a simple HTML page served from your EC2 instance._ 48 | 49 | #### Auto Scaling 50 | 51 | * Create an AMI from that VM and put it in an autoscaling group so one VM always exists. 52 | * Put a Elastic Load Balancer infront of that VM and load balance between two Availability Zones (one EC2 in each AZ). 53 | * _Checkpoint: You can view a simple HTML page served from both of your EC2 instances. You can turn one off and your website is still accessible._ 54 | 55 | #### External Data 56 | 57 | * Create a DynamoDB table and experiment with loading and retrieving data manually, then do the same via a script on your local machine. 58 | * Refactor your static page into your Fortune-of-the-Day website (Node, PHP, Python, whatever) which reads/updates a list of fortunes in the AWS DynamoDB table. (Hint: EC2 Instance Role) 59 | * _Checkpoint: Your HA/AutoScaled website can now load/save data to a database between users and sessions._ 60 | 61 | #### Web Hosting Platform-as-a-Service 62 | 63 | * Retire that simple website and re-deploy it on Elastic Beanstalk. 64 | * Create a S3 Static Website Bucket, upload some sample static pages/files/images. Add those assets to your Elastic Beanstalk website. 65 | * Register a domain (or re-use and existing one). Set Route53 as the Nameservers and use Route53 for DNS. Make www.yourdomain.com go to your Elastic Beanstalk. Make static.yourdomain.com serve data from the S3 bucket. 66 | * Enable SSL for your Static S3 Website. This isn't exactly trivial. (Hint: CloudFront + ACM) 67 | * Enable SSL for your Elastic Beanstalk Website. 68 | * _Checkpoint: Your HA/AutoScaled website now serves all data over HTTPS. The same as before, except you don't have to manage the servers, web server software, website deployment, or the load balancer._ 69 | 70 | #### Microservices 71 | 72 | * Refactor your EB website into ONLY providing an API. It should only have a POST/GET to update/retrieve that specific data from DynamoDB. Bonus: Make it a simple REST API. Get rid of www.yourdomain.com and serve this EB as api.yourdomain.com 73 | * Move most of the UI piece of your EB website into your Static S3 Website and use Javascript/whatever to retrieve the data from your api.yourdomain.com URL on page load. Send data to the EB URL to have it update the DynamoDB. Get rid of static.yourdomain.com and change your S3 bucket to serve from www.yourdomain.com. 74 | * _Checkpoint: Your EB deployment is now only a structured way to retrieve data from your database. All of your UI and application logic is served from the S3 Bucket (via CloudFront). You can support many more users since you're no longer using expensive servers to serve your website's static data._ 75 | 76 | #### Serverless 77 | 78 | * Write a AWS Lambda function to email you a list of all of the Fortunes in the DynamoDB table every night. Implement Least Privilege security for the Lambda Role. (Hint: Lambda using Python 3, Boto3, Amazon SES, scheduled with CloudWatch) 79 | * Refactor the above app into a Serverless app. This is where it get's a little more abstract and you'll have to do a lot of research, experimentation on your own. 80 | * The architecture: Static S3 Website Front-End calls API Gateway which executes a Lambda Function which reads/updates data in the DyanmoDB table. 81 | * Use your SSL enabled bucket as the primary domain landing page with static content. 82 | * Create an AWS API Gateway, use it to forward HTTP requests to an AWS Lambda function that queries the same data from DynamoDB as your EB Microservice. 83 | * Your S3 static content should make Javascript calls to the API Gateway and then update the page with the retrieved data. 84 | * Once you have the "Get Fortune" API Gateway + Lambda working, do the "New Fortune" API. 85 | * _Checkpoint: Your API Gateway and S3 Bucket are fronted by CloudFront with SSL. You have no EC2 instances deployed. All work is done by AWS services and billed as consumed._ 86 | 87 | #### Cost Analysis 88 | 89 | * Explore the AWS pricing models and see how pricing is structured for the services you've used. 90 | * Answer the following for each of the main architectures you built: 91 | * Roughly how much would this have costed for a month? 92 | * How would I scale this architecture and how would my costs change? 93 | * Architectures 94 | * Basic Web Hosting: HA EC2 Instances Serving Static Web Page behind ELB 95 | * Microservices: Elastic Beanstalk SSL Website for only API + S3 Static Website for all static content + DynamoDB Table + Route53 + CloudFront SSL 96 | * Serverless: Serverless Website using API Gateway + Lambda Functions + DynamoDB + Route53 + CloudFront SSL + S3 Static Website for all static content 97 | 98 | #### Automation 99 | 100 | **_!!! This is REALLY important !!!_** 101 | 102 | * These technologies are the most powerful when they're automated. You can make a Development environment in minutes and experiment and throw it away without a thought. This stuff isn't easy, but it's where the really skilled people excel. 103 | * Automate the deployment of the architectures above. Use whatever tool you want. The popular ones are AWS CloudFormation or Teraform. Store your code in AWS CodeCommit or on GitHub. Yes, you can automate the deployment of ALL of the above with native AWS tools. 104 | * I suggest when you get each app-related section of the done by hand you go back and automate the provisioning of the infrastructure. For example, automate the provisioning of your EC2 instance. Automate the creation of your S3 Bucket with Static Website Hosting enabled, etc. This is not easy, but it is very rewarding when you see it work. 105 | 106 | #### Continuous Delivery 107 | 108 | * As you become more familiar with Automating deployments you should explore and implement a Continuous Delivery pipeline. 109 | * Develop a CI/CD pipeline to automatically update a dev deployment of your infrastructure when new code is published, and then build a workflow to update the production version if approved. Travis CI is a decent SaaS tool, Jenkins has a huge following too, if you want to stick with AWS-specific technologies you'll be looking at CodePipeline. 110 | 111 | #### Miscellaneous / Bonus 112 | 113 | These didn't fit in nicely anywhere but are important AWS topics you should also explore: 114 | 115 | * IAM: You should really learn how to create complex IAM Policies. You would have had to do basic roles+policies for for the EC2 Instance Role and Lambda Execution Role, but there are many advanced features. 116 | * Networking: Create a new VPC from scratch with multiple subnets (you'll learn a LOT of networking concepts), once that is working create another VPC and peer them together. Get a VM in each subnet to talk to eachother using only their private IP addresses. 117 | * KMS: Go back and redo the early EC2 instance goals but enable encryption on the disk volumes. Learn how to encrypt an AMI. 118 | 119 | ### Final Thoughts 120 | 121 | I've been recently recruiting for Cloud Systems Engineers and Cloud Systems Administrators. We've interviewed over a dozen local people with relevant resume experience. Every single person we interviewed would probably struggle starting with the DynamoDB/AutoScaling work. I'm finding there are very few people that HAVE ACTUALLY DONE THIS STUFF. Many people are familiar with the concepts, but when pushed for details they don't have answers or admit to just peripheral knowledge. You learn SO MUCH by doing. 122 | 123 | If you can't find an excuse or get support to do this as part of your job I would find a small but flashy/impressive personal project that you can build and show off as proof of your skills. Open source it on GitHub, make professional documentation, comment as much as is reasonable, and host a demo of the website. Add links to your LinkedIn, reference it on your resume, work it into interview answers, etc. When in a job interview you'll be able to answer all kinds of real-world questions because you've been-there-done-that with most of AWS' major services. 124 | 125 | I'm happy to hear any feedback. I'm considering making THIS post my flashy/impressive personal project in the form of a GitHub repo with sample code for each step, architecture diagrams, etc. 126 | 127 | By: https://www.reddit.com/user/SpectralCoding -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/common.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | roles: 4 | - common -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/group_vars/all.yaml: -------------------------------------------------------------------------------- 1 | key_name: Justin-YubiKey 2 | instance_type: t2.micro 3 | security_group: webserver 4 | subnet: subnet-06dd7a6e 5 | image: ami-49f0762d 6 | region: ca-central-1 7 | iamrole: DynamoDB-Admin -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Create a new EC2 Instance 2 | ec2: 3 | key_name: "{{ key_name }}" 4 | instance_type: "{{ instance_type }}" 5 | image: "{{ image }}" 6 | wait: true 7 | group: "{{ security_group }}" 8 | count: 1 9 | vpc_subnet_id: "{{ subnet }}" 10 | assign_public_ip: yes 11 | region: "{{ region }}" 12 | instance_tags: 13 | Name: webserver 14 | Software: nginx 15 | register: ec2 16 | 17 | - name: Attach instance role 18 | shell: "aws ec2 associate-iam-instance-profile --instance-id {{ item.id }} --iam-instance-profile Name=DynamoDB-Admin" 19 | with_items: "{{ ec2.instances }}" 20 | 21 | - name: Add new instance to host group 22 | add_host: 23 | hostname: "{{ item.public_ip }}" 24 | groupname: launched 25 | with_items: "{{ ec2.instances }}" 26 | 27 | - name: Wait for SSH to come up 28 | wait_for: 29 | host: "{{ item.public_dns_name }}" 30 | port: 22 31 | delay: 60 32 | timeout: 320 33 | state: started 34 | with_items: "{{ ec2.instances }}" -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/roles/webserver/files/fortunesite.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Fortune Site 3 | 4 | [Service] 5 | ExecStart=/home/ec2-user/FortuneSite/server.js 6 | Restart=always 7 | User=ec2-user 8 | Group=ec2-user 9 | Environment=PATH=/usr/bin:/usr/local/bin 10 | Environment=NODE_ENV=production 11 | WorkingDirectory=/home/ec2-user/FortuneSite/ 12 | 13 | [Install] 14 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/roles/webserver/files/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes 1; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | server { 32 | listen 80; 33 | #server_name fortunesite.com; 34 | 35 | location / { 36 | proxy_pass http://127.0.0.1:3000; 37 | proxy_http_version 1.1; 38 | proxy_set_header Upgrade $http_upgrade; 39 | proxy_set_header Connection 'upgrade'; 40 | proxy_set_header Host $host; 41 | proxy_cache_bypass $http_upgrade; 42 | } 43 | } 44 | 45 | include /etc/nginx/conf.d/*.conf; 46 | } 47 | -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/roles/webserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install updates 2 | yum: name=* state=latest 3 | become: yes 4 | 5 | - name: Setup nginx repo 6 | yum_repository: 7 | name: nginx 8 | description: NGINX Repo 9 | baseurl: http://nginx.org/packages/rhel/7/$basearch/ 10 | gpgcheck: no 11 | enabled: yes 12 | become: yes 13 | 14 | - name: Install packages 15 | yum: 16 | name: "{{ item }}" 17 | state: latest 18 | with_items: 19 | - nginx 20 | - git 21 | become: yes 22 | 23 | - name: Get Node.JS 24 | shell: curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash - 25 | 26 | - name: Install Node.JS 27 | yum: 28 | name: "{{ item }}" 29 | state: latest 30 | with_items: 31 | - nodejs 32 | - gcc-c++ 33 | - make 34 | become: yes 35 | 36 | - name: Curl credentials 37 | shell: curl http://169.254.169.254/latest/meta-data/iam/security-credentials/DynamoDB-Admin 38 | 39 | - name: Setup cron jobs for credentials 40 | cron: 41 | name: "Hourly IAM Role credential update" 42 | special_time: hourly 43 | user: ec2-user 44 | job: "curl http://169.254.169.254/latest/meta-data/iam/security-credentials/DynamoDB-Admin" 45 | 46 | - cron: 47 | name: "reboot IAM Role credential update" 48 | special_time: reboot 49 | user: ec2-user 50 | job: "curl http://169.254.169.254/latest/meta-data/iam/security-credentials/DynamoDB-Admin" 51 | 52 | - name: Pull git repo 53 | git: 54 | repo: 'https://github.com/Just-Insane/FortuneSite.git' 55 | dest: /home/ec2-user/FortuneSite/ 56 | version: master 57 | 58 | - name: make server.js executable 59 | file: 60 | path: /home/ec2-user/FortuneSite/server.js 61 | owner: ec2-user 62 | group: ec2-user 63 | mode: 0775 64 | become: yes 65 | 66 | - name: Setup FortuneSite Service 67 | copy: 68 | src: fortunesite.service 69 | dest: /etc/systemd/system 70 | owner: root 71 | group: root 72 | mode: 0644 73 | become: yes 74 | 75 | - name: Install dependancies 76 | shell: cd /home/ec2-user/FortuneSite/ && npm install 77 | 78 | - name: Copy nginx conf file 79 | copy: 80 | src: nginx.conf 81 | dest: /etc/nginx/nginx.conf 82 | owner: root 83 | group: root 84 | mode: 0644 85 | backup: yes 86 | become: yes 87 | 88 | - name: Set selinux policy 89 | selinux: 90 | policy: targeted 91 | state: permissive 92 | become: yes 93 | 94 | - service: 95 | name: fortunesite 96 | state: restarted 97 | enabled: yes 98 | become: yes 99 | 100 | - service: 101 | name: nginx 102 | state: restarted 103 | enabled: yes 104 | become: yes 105 | 106 | - shell: "curl {{ ansible_eth0.ipv4.address }} && sleep 10 && curl {{ ansible_eth0.ipv4.address }}" 107 | 108 | - shell: cd /tmp && cat /var/log/audit/audit.log | audit2allow -a -M policy && semodule -i policy.pp && rm -f policy.* 109 | become: yes 110 | 111 | - selinux: 112 | policy: targeted 113 | state: enforcing 114 | become: yes 115 | 116 | - name: Restart FortuneSite Service 117 | service: 118 | name: fortunesite 119 | state: restarted 120 | enabled: yes 121 | become: yes 122 | 123 | - name: Restart service nginx, if not running 124 | service: 125 | name: nginx 126 | state: restarted 127 | enabled: yes 128 | become: yes -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/site.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | 4 | - import_playbook: common.yml 5 | - import_playbook: webserver.yml -------------------------------------------------------------------------------- /Web Hosting Basics/Part 1/webserver.yml: -------------------------------------------------------------------------------- 1 | - hosts: launched 2 | user: ec2-user 3 | roles: 4 | - webserver -------------------------------------------------------------------------------- /Web Hosting Basics/Part 2/common.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | roles: 4 | - common -------------------------------------------------------------------------------- /Web Hosting Basics/Part 2/group_vars/all.yaml: -------------------------------------------------------------------------------- 1 | key_name: Justin-YubiKey 2 | instance_type: t2.micro 3 | security_group: webserver 4 | subnet: subnet-06dd7a6e 5 | image: ami-49f0762d 6 | region: ca-central-1 -------------------------------------------------------------------------------- /Web Hosting Basics/Part 2/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Get EC2 Instance Facts 2 | ec2_instance_facts: 3 | filters: 4 | "tag:Name": webserver 5 | "instance-state-name": running 6 | register: ec2facts 7 | 8 | - name: Snapshot Instance 9 | ec2_snapshot: 10 | instance_id: "{{ item.instance_id }}" 11 | device_name: /dev/sda1 12 | region: "{{ region }}" 13 | description: Snapshot of created webserver 14 | snapshot_tags: 15 | Name: webserver 16 | Software: nginx 17 | with_items: "{{ ec2facts.instances }}" 18 | 19 | - name: Get Snapshot facts 20 | ec2_snapshot_facts: 21 | filters: 22 | "tag:Name": webserver 23 | "tag:Software": nginx 24 | register: snapshot 25 | 26 | - name: Terminate instances after snapshot 27 | ec2: 28 | state: 'absent' 29 | region: "{{ region }}" 30 | instance_id: "{{ item.instance_id }}" 31 | with_items: "{{ ec2facts.instances }}" 32 | 33 | - name: Create AMI Registration 34 | ec2_ami: 35 | name: webserver AMI 36 | state: present 37 | architecture: x86_64 38 | virtualization_type: hvm 39 | root_device_name: /dev/sda1 40 | device_mapping: 41 | - device_name: /dev/sda1 42 | size: 10 43 | snapshot_id: "{{ item.snapshot_id }}" 44 | delete_on_termination: true 45 | volume_type: gp2 46 | with_items: "{{ snapshot.snapshots }}" 47 | register: image 48 | 49 | - name: Create EC2 instance from image 50 | ec2: 51 | key_name: "{{ key_name }}" 52 | instance_type: "{{ instance_type }}" 53 | image: "{{ item.image_id }}" 54 | wait: true 55 | group: "{{ security_group }}" 56 | count: 1 57 | vpc_subnet_id: "{{ subnet }}" 58 | assign_public_ip: yes 59 | region: "{{ region }}" 60 | instance_tags: 61 | Name: webserver 62 | Software: nginx 63 | with_items: "{{ image.results }}" 64 | register: ec2instance -------------------------------------------------------------------------------- /Web Hosting Basics/Part 2/site.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | user: justin 3 | 4 | - import_playbook: common.yml --------------------------------------------------------------------------------