Simple PowerShell scripts for automated provisioning of Linux EC2 instances within AWS. Running these will provision an Amazon Linux 2 EC2 instance with SSH key pair and Security Group, with a webapp deployed thereon, plus an associated DNS record in Route 53.
I've written a blog article about these scripts here.
- An AWS account with a VPC set up, and with a DNS domain/zone set up in Route 53.
- PowerShell needs to be installed if you don't already have it, as per Microsoft's instructions for installing on macOS, Linux, Windows, etc.
- AWS Tools for PowerShell needs to be installed, as per the installation instructions for macOS/Linux or for Windows. I installed the AWS.Tools version on macOS, as opposed to the AWSPowerShell.NetCore version.
- SSH needs to be installed for the deployment phase. This is only likely to be an issue on Windows, so follow Microsoft's instructions for getting OpenSSH installed and configured.
I'm using the AWS.Tools version of AWS Tools for PowerShell on macOS, so I found it necessary to install the necessary AWS modules for shared services, EC2 and Route 53, as follows. (Start Powershell with pwsh
if needed before running these commands):
Install-Module -Name AWS.Tools.Common
Install-Module -Name AWS.Tools.EC2
Install-Module -Name AWS.Tools.Route53
With the AWSPowerShell.NetCore version of AWS Tools for PowerShell, installing these additional modules does not appear to be necessary.
On macOS I found that AWS Tools for PowerShell used my existing AWS credentials and config set up in ~/.aws/credentials and ~/.aws/config (originally set up for use with the AWS CLI) without any additional setup needed.
If you need help setting up your AWS credentials and config (e.g. default AWS region) for use with PowerShell, refer to the Getting Started documentation.
Copy etc/variables_template.ps1 to etc/variables.ps1 and edit the file as per your requirements. The $ZoneDnsName
in particular will need to be changed for the DNS domain you want to use in Route 53.
If necessary, run pwsh
to enter PowerShell if you're on macOS or Linux, or start the Windows PowerShell app if you're on Windows, then change to this PowerShell_AWS_Linux directory to run the scripts.
Run ./provision.ps1 to provision the instance and DNS. This will provision an SSH key pair and Security Group, then launch the EC2 instance, then set up a CNAME in the DNS pointing www.mydomain.com
to the public DNS of the EC2 instance.
N.B. This script saves the private SSH key to etc/$AppName.pem. For the SSH deployment to work (see below) this file needs to have its permissions set to mode 0600, but there does not seem to be a standard way of achieving this in PowerShell. I've used a non-PowerShell chmod
command in the script which will work on macOS and Linux.
In Windows PowerShell this line will need to be commented out because chmod
does not exist in that environment. If the permissions of this file prevent SSH deployment on Windows, you'll need to manually set the permissions before running deploy.ps1. If anyone knows of a better solution for solving this across all operating systems, let me know.
Run ./deploy.ps1 to deploy the webapp on the EC2 instance. This does the following via SSH connections:
- Downloads my basic Python webapp simple-webapp to the instance and unzips it to the necessary location.
- Installs the systemd service script for the webapp, then enables it and starts it as a service running on port 8080.
- Installs nginx and downloads an nginx config file which proxies all incoming requests on port 80 to the webapp on port 8080.
- Enables nginx and starts it as a service running on port 80.
You can modify this script to deploy a different webapp if so desired.
Run ./destroy.ps1 to delete the DNS entry, terminate the EC2 instance, remove the Security Group and SSH key pair, and delete the private key file.
N.B. Run this script with extreme caution as it removes AWS infrastructure and has the potential for serious damage if, for example, you accidentally run it in the wrong environment.
To check the webapp via the EC2 instance Public DNS:
$InstancePublicDNS = (Get-EC2Instance -Filter @( @{name='tag:Name'; values="simple-webapp"})).Instances.publicdnsname ; curl http://$InstancePublicDNS/
To check the webapp via the Route 53 DNS:
curl http://www.mydomain.com/
To check the nginx access log:
$InstancePublicDNS = (Get-EC2Instance -Filter @( @{name='tag:Name'; values="simple-webapp"})).Instances.publicdnsname ; ssh -o CheckHostIP=no -o StrictHostKeyChecking=no -i etc/simple-webapp.pem ec2-user@$InstancePublicDNS "sudo tail -50 /var/log/nginx/access.log"
To check the nginx error log:
$InstancePublicDNS = (Get-EC2Instance -Filter @( @{name='tag:Name'; values="simple-webapp"})).Instances.publicdnsname ; ssh -o CheckHostIP=no -o StrictHostKeyChecking=no -i etc/simple-webapp.pem ec2-user@$InstancePublicDNS "sudo tail -50 /var/log/nginx/error.log"
To check the webapp log:
$InstancePublicDNS = (Get-EC2Instance -Filter @( @{name='tag:Name'; values="simple-webapp"})).Instances.publicdnsname ; ssh -o CheckHostIP=no -o StrictHostKeyChecking=no -i etc/simple-webapp.pem ec2-user@$InstancePublicDNS "sudo grep simple-webapp /var/log/messages | tail -50"
To get an interactive session on the EC2 instance:
$InstancePublicDNS = (Get-EC2Instance -Filter @( @{name='tag:Name'; values="simple-webapp"})).Instances.publicdnsname ; ssh -o CheckHostIP=no -o StrictHostKeyChecking=no -i etc/simple-webapp.pem ec2-user@$InstancePublicDNS