I created a new aws-lam2-Ubuntu-CloudInit script that anyone could launch on Amazon Web Services (AWS).

A web, shell and proxy server built from a Generic Ubuntu Server image

The script builds a web, shell and proxy server from the Generic Ubuntu 20.04 Server image available at no additional charge over the cost of running the EC2 instance.

All the source is on GitHub and the creation and storage of a custom Amazon Machine Image is not required.

The web server is configured for three websites. The default website would be displayed if a domain name is pointed to the IP address or domain name of the running instance. A second website is configured if the browser gets to the site by IP address or the public-hostname assigned to the instance when it launched. The third website is configured for some domain names I have control of.

I can launch from the command line with:

aws ec2 run-instances --count 1 --image-id ami-07dd19a7900a1f049 \
--instance-type t3.nano --security-group-ids sg-3bda0647 \
--associate-public-ip-address --key-name aws-nwo-lam1 --user-data \

LAM AWS command line options

Launch a single ec2 instance of the t3.nano type which is cheapest or of the t2.micro type which is part of the AWS Free Tier offering.
aws ec2 run-instances --count 1 --instance-type t3.nano
Get a public IP address and launch using my key
--associate-public-ip-address --key-name aws-nwo-lam1
Use a predefined security group
--security-group-ids sg-3bda0647
Use the latest Ubuntu Server image
--image-id ami-056cb9ae6e2df09e8
Specify the file with the user data 
--user-data file://<file name>
  • ami-056cb9ae6e2df09e8 This is the Ubuntu Server 20.04 LTS image for the US west 2 AWS region
    • If you want to run this in another region, use the appropriate image which you can find at the bottom of the Launch instance wizard page.
  • aws-nwo-lam1 This is my key from AWS Identity and Access Management for the IAM user I want to be able to access the instance.
  • sg-3bda0647 This is a pre defined security group.
  • t3.nano This is a very small instance and you would want to use the larger t2.mico to be eligible for the Free Tier.


I would love to have someone test this script but can't think of who to ask. I have been retired for over five years so don't have co-workers I could ask. My friends and family are not really interested in what I do related to computers for fun.

AWS Account

I have a root user account that I almost never use and a separate AWS IAM user for that account that I use for everything. My user level access has access to a everything for the account including billing.

Unknown level of knowledge

I don't even remember all the steps in setting up the two sets of credentials and granting the proper level of access to the user account so I never have to use the root account but I remember there were lots of guidelines on the web.

This page is not a tutorial and is instead an example. It is also documentation for myself and has enough that I can launch the instance with copy and paste and even do the check in to a Dynamic Domain Name Service steps I documented below.

You can launch the instance from the AWS Console

You can launch the instance from the AWS Console from Services - EC2 - Instances - Launch Instance

As of August 2020 you have to scroll down a ways to find the Ubuntu 20.04 image with Ubuntu 18.04, Ubuntu 16.04, Amazon, RedHat, Suse and many other images listed before the relatively new Ubuntu 20.04 image.

You can paste the data passed as a file on the command line into the User data box in the advanced section of the Configure Instance Details page.

You can even configure a new security group from the launch web interface although this is step six with many previous options to launch before seeing that page.

I am sure an advanced user could launch one of these instances from this post.

Install awscli and set credentials to use the command line

This awscli package is in the standard Ubuntu repositories. The .aws/credentials file has key information for aws-nwo-lam1 to launch an instance in my VPC and the .aws/config file holds us-west-2 as the region value where the instance is launched.

LAM AWS resources

Use a predefined security group

The security group definition controls the traffic within the Virtual Private Cloud and with the outside world. I use the same security group definition for multiple images with only a limited number of inbound ports open. The definition details are:

  • GroupName - aws-web-anywhere-alt-ssh-port
  • Inbound Port 22 TCP Rule - SSH from VPC -
  • Inbound Port 80 Custom TCP Rule - HTTP -
  • Inbound Port 443 Custom TCP Rule - HTTPS or SSH on an Alternate port -
  • Inbound Port 55520 Custom TCP Rule - SSH on an Alternate port -
  • Inbound Port 55593 Custom TCP Rule - IMAPS on an Alternate port -
  • Outbound All/All

This security group definition allows web traffic on the standard ports from the public interface (, Secure Shell on an alternate high numbered port and IMAPS on an alternate high numbered port. The security group definition allows Secure Shell on the standard port. The SSH SOCKS5 Proxy instance uses the same security group definition but is accepting Secure Shell traffic on the port that is normally used for Secure Web (HTTPS) traffic. The security group definition does allow outgoing traffic from the server over the public interface.

What is missing

The instance doesn't check in to a Dynamic Domain Name Service

My main lam2 script checks in as http://lam2.duckdns.org which is one of four names that along with the aws public-hostname can be used to access the customized website. The instance-type is also shown on the page as well as a link to the Cloud-init log. I can use this page to toggle between the four Dynamic Domain Names I use for the group of servers I use to support the websites.

From another instance in the same VPC I can use Secure Copy to get the private ubuntu resource archive to the new instance over the local area network with:

scp -p /mnt/efs/aws-lam1-ubuntu/ubuntu.t* <local-ipv4>:/home/ubuntu

On the new instance I can install these resources with:

tar -xzf ubuntu.tgz --directory /home/ubuntu

Check in and get a verbose response:

echo url="https://www.duckdns.org/update?domains=${DDNS_NAME}&token=$(cat \
~/.duckdns)&verbose=true&ip=" | curl -k -K - ; echo \
" for ${DDNS_NAME}.duckdns.org IP address update" ; echo

Upon successful completion the output with the verbose option will look like the following:


UPDATED for lam2.duckdns.org IP address update

If the ubuntu resources were not installed the following error is reported:

cat: ~/.duckdns: No such file or directory

Alternately the Duck DNS token file can be created with:

echo {DuckDNStokenValue} > /home/ubuntu/.duckdns

The HTTPS port is an alternate SSH port

The main function of this AWS EC2 instance is to be a SSH SOCKS5 Proxy server on port 443.

Port 443 is normally used for HTTPS so is likely to be available even when other ports are blocked.

No MediaWiki, No HTTPS site defined or modules loaded

My main lam1 Cloud-init script has the HTTPS site definition in a private repository.

No mount of a persistent parallel file system

My main lam1 Cloud-init script utilizes an AWS Elastic File System (EFS) that all the instances can access as a persistent parallel file system. Private git repositories and other shared resources are on that filesystem.

Why the lam2 instance

The lam2 instance was a candidate to be modified so that anyone could launch it precisely because it did not have html/Private, MediaWiki or the databases that I only support on HTTPS.

I have had an AWS VPC since 2017 but early on added the private EFS and private S3 buckets as a source for initializing.

This year I finally switched to git as my main VCS and decided to publish repos that did not need to remain private to GidHub because of it's value for documentation. Once I had published the aws Linux Apache MariaDB in the cloud, no-ssl Default unsecure site configuration, ubuntu-etc Ubuntu Server 20.04 configuration changes for LAM AWS VPC EC2 instances and arsc Lawrence A. Murakami at ARSC repos to GitHub I realized I could launch the lam2 instance using only publicly available sources for the initialization.

This page was retrieved from my private MediaWiki instance

Most of the pages I end up publishing to the web are a Static Copy of a page in my private MediaWiki instance. In this case I use view source and copy the parts from to From: <!-- start content --> To: <!-- end content --> to a file and add Front Matter for Jekyll that will build the page to be published on GitHub Pages.

Retrieved from "https://ak20.lam1.us/A/index.php?title=A_Cloud-init_script_that_anyone_could_launch_on_Amazon_Web_Services_(AWS)&oldid=5254"