Create EC2 Module
This quickstart creates a Nullstone Application module that provisions an AWS EC2 instance. This walks you through:
- Registering a new module in Nullstone (and defining the contract)
- Developing the Terraform code
- Testing the module in a sandbox environment
- Publishing the final version to Nullstone
The following category, provider, and platform are used when registering the module:
- Category:
app
- Subcategory:
server
- Provider:
aws
- Platform:
ec2
A working copy of this code can be found at https://github.com/nullstone-modules/create-ec2-guide.
Prerequisites
Before following this quickstart, make sure the following are installed and configured.
TIP
If you are unfamiliar with Terraform, it may be helpful to follow their basic guide.
Create EC2 module
Create a new repository/directory to store the module. We recommend having a repository for each module; however, you may have multiple modules in a single repository as long as they are in different directories.
The following will create a .nullstone/module.yaml
that contains metadata about the Nullstone module.
mkdir test-ec2 && cd test-ec2
nullstone modules generate
# This command will ask you a set of questions to configure the module
# Specify the following:
# Module Name: test-ec2
# Friendly Name: Test EC2 Instance
# Description: Creates an EC2 instance
# Make this module available to everybody? No
# Category: app
# Subcategory: server
# ProviderTypes: aws
# Platform: ec2
Register module
Run modules new
to register the module. This uses .nullstone/module.yaml
to register in the Nullstone catalog.
nullstone modules new
Define network connection
Add a network to our module by creating a network.tf
with the following.
data "ns_connection" "network" {
name = "network"
contract = "aws/network/vpc"
}
locals {
vpc_id = data.ns_connection.network.outputs.vpc_id
private_subnet_ids = data.ns_connection.network.outputs.private_subnet_ids
}
Define EC2 instance
Create a file named instance.tf
with the following contents.
data "aws_ami" "this" {
most_recent = true
owners = ["amazon"]
filter {
name = "owner-alias"
values = ["amazon"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm*"]
}
}
locals {
ami = data.aws_ami.this.id
}
resource "aws_instance" "this" {
ami = local.ami
instance_type = "t3.nano"
subnet_id = local.private_subnet_ids[0]
vpc_security_group_ids = [aws_security_group.this.id]
associate_public_ip_address = false
tags = merge(local.tags, { Name = local.resource_name })
}
resource "aws_security_group" "this" {
name = local.resource_name
vpc_id = local.vpc_id
tags = merge(local.tags, { Name = local.resource_name })
}
resource "aws_security_group_rule" "this-https-to-world" {
security_group_id = aws_security_group.this.id
type = "egress"
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = ["0.0.0.0/0"]
}
Enable nullstone ssh
To enable SSH to the server using Nullstone, add an adminer
user to adminer.tf
.
resource "aws_iam_user" "adminer" {
name = "adminer-${local.resource_name}"
tags = local.tags
}
resource "aws_iam_access_key" "adminer" {
user = aws_iam_user.adminer.name
}
resource "aws_iam_user_policy" "adminer" {
user = aws_iam_user.adminer.name
policy = data.aws_iam_policy_document.adminer.json
}
data "aws_iam_policy_document" "adminer" {
statement {
sid = "AllowSSMSession"
effect = "Allow"
actions = ["ssm:StartSession"]
resources = [
aws_instance.this.arn,
"arn:aws:ssm:us-east-1::document/AWS-StartSSHSession",
]
}
}
Adhere to server/aws-ec2
This quickstart launches an EC2 instance using Nullstone. To get the full benefits of Nullstone, amend outputs.tf
to adhere to the app/aws/ec2 contract.
TIP
Terraform does not support output types in the definition. Nullstone encodes these into the description
field as seen below.
data "aws_region" "this" {}
output "region" {
value = data.aws_region.this.name
description = "string ||| The AWS region where the EC2 instance resides."
}
output "instance_id" {
value = aws_instance.this.id
description = "string ||| The Instance ID of the EC2 instance."
}
output "adminer" {
value = {
name = aws_iam_user.adminer.name
access_key = aws_iam_access_key.adminer.id
secret_key = aws_iam_access_key.adminer.secret
}
description = "object({ name: string, access_key: string, secret_key: string }) ||| An AWS User with explicit privilege to admin the EC2 instance."
sensitive = true
}
Test in Sandbox
To test our new module, create a sandbox environment and necessary dependencies. In this scenario, we need a network and an app for our new EC2 module.
Create sandbox provider
Follow the guide to Connect to AWS to create a provider named aws-sandbox
.
Create sandbox environment
Create a sandbox
stack and a sandbox
environment.
nullstone stacks new --name=sandbox --description="Sandbox for module testing"
nullstone envs new --name=sandbox --stack=sandbox --provider=aws-sandbox --region=us-east-1
Create sandbox network
In our sandbox
stack, create a network block using the nullstone/aws-network
module. In our example, let's name the network network1
and launch the network.
nullstone blocks new --name=network1 --stack=sandbox --module=nullstone/aws-network
nullstone up --block=network1 --env=sandbox --watch
Create sandbox EC2
In our sandbox
stack, create a block using our new module named test-ec2
.
nullstone blocks new --name=test-ec2 --stack=sandbox --module=test-ec2
Initialize Terraform using the following command.
nullstone workspaces select --block=test-ec2 --env=sandbox
TIP
This command will generate __backend__.tf
and add to .gitignore
. This contains state backend information that is automatically changed when workspaces select
is run.
Configure AWS credentials
Previously, you configured a provider in Nullstone, but you need to authenticate with AWS locally test the module locally. Authenticate with AWS and export AWS_REGION
, AWS_ACCESS_KEY_ID
, and AWS_SECRET_ACCESS_KEY
. These access keys should have access to the aws-sandbox
AWS account.
export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID=<access key id>
export AWS_SECRET_ACCESS_KEY=<secret access key>
Apply infrastructure changes
Run terraform to test the module.
terraform apply
SSH into server
Once the infrastructure is provisioned, SSH into the box using the following command.
TIP
It can take several minutes for an EC2 instance to boot and become available depending on the image.
nullstone ssh --app=test-ec2 --env=sandbox
Publish module
Once your module is complete, publish the module to the Nullstone registry. A user can launch this module directly from the Nullstone UI without any coding or Terraform setup.
nullstone modules publish --version=v0.0.1