How to build an Ubuntu Pro golden image in AWS with Packer
This article explains how to build an Ubuntu Pro golden image in AWS with Packer. We will use Ubuntu Pro 20.04 as the base for the image, but this process can be done on any version of Ubuntu Pro.
To be able to use Ubuntu Pro as a base in AWS, all you need to do is subscribe to the marketplace product before-hand. You can accept the terms and subscribe by finding the product in the AWS Marketplace and subscribing to it. For example, in the AWS services list, select AWS Marketplace Subscriptions. Click on Discover products to the left and search for ubuntu pro. Pick the version you need (ie. Ubuntu Pro 20.04 LTS) and on the page of that product click on Continue to Subscribe. In the Subscribe to this software page, click on Accept Terms to accept the extra pricing and terms and wait a few minutes for the subscription to complete.
Once you have the subscription active, you can proceed to building your base image with Packer. The example I use is taken from the Build an Image page on the Hashicorp website.
Create a Packer template called example-pro.pkr.hcl
with the following content:
variable "ami_name" {
type = string
default = "my-custom-pro-ami"
}
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
source "amazon-ebs" "example" {
ami_name = "packer example ${local.timestamp}"
instance_type = "t2.micro"
region = "us-east-1"
source_ami = "ami-0ed28656d62ce20d6"
ssh_username = "ubuntu"
}
build {
sources = ["source.amazon-ebs.example"]
provisioner "file" {
destination = "/home/ubuntu/"
source = "./welcome.txt"
}
provisioner "shell" {
inline = ["sudo ua detach --assume-yes"]
}
}
The source AMI ami-0ed28656d62ce20d6
in the above example corresponds to an Ubuntu Pro 20.04 AMI created by Canonical on 2020-10-22 as we can see with the following command:
$ aws ec2 describe-images --filters "Name=name,Values=ubuntu-pro-server/images/*20.04*" | grep -i -e imageid -e creationdate -e \"name\"
"CreationDate": "2020-08-14T09:20:41.000Z",
"ImageId": "ami-01e2764da55c94742",
"Name": "ubuntu-pro-server/images/hvm-ssd/ubuntu-focal-20.04-amd64-pro-serve-ae7ed378-8838-4fcf-842d-d1d09b34f116-ami-01575b6f5a4085419.4",
"CreationDate": "2020-10-22T19:42:54.000Z",
"ImageId": "ami-0ed28656d62ce20d6",
"Name": "ubuntu-pro-server/images/hvm-ssd/ubuntu-focal-20.04-amd64-pro-serve-ae7ed378-8838-4fcf-842d-d1d09b34f116-ami-0d173ef9b96def311.4",
"CreationDate": "2020-09-10T21:28:42.000Z",
"ImageId": "ami-0fb29f6090e62a703",
"Name": "ubuntu-pro-server/images/hvm-ssd/ubuntu-focal-20.04-amd64-pro-serve-ae7ed378-8838-4fcf-842d-d1d09b34f116-ami-08503d07277c98720.4",
In the build {}
section of the Packer template above, we can see we use the file
provisioner to copy a welcome.txt file inside the instance. This can be anything customization you want.
The one post-command that is recommended to run to create a golden image in the cloud based on Ubuntu Pro is ua detach
. This will make sure that the golden image base instance doesn’t propagate its token information to all your other instances.
Once your Packer template is created, you can build your golden image with packer build
:
$ packer build example-pro.pkr.hcl
amazon-ebs.example: output will be in this color.
==> amazon-ebs.example: Prevalidating any provided VPC information
==> amazon-ebs.example: Prevalidating AMI Name: packer example 20210426194519
amazon-ebs.example: Found Image ID: ami-0ed28656d62ce20d6
==> amazon-ebs.example: Creating temporary keypair: packer_6087184f-3704-3a74-a24d-9aea48dc6645
==> amazon-ebs.example: Creating temporary security group for this instance: packer_60871851-056f-eacd-a0c5-7f88b5dd0865
==> amazon-ebs.example: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs.example: Launching a source AWS instance...
==> amazon-ebs.example: Adding tags to source instance
amazon-ebs.example: Adding tag: "Name": "Packer Builder"
amazon-ebs.example: Instance ID: i-0fe280e360cbd4da3
==> amazon-ebs.example: Waiting for instance (i-0fe280e360cbd4da3) to become ready...
==> amazon-ebs.example: Using ssh communicator to connect: 3.86.39.143
==> amazon-ebs.example: Waiting for SSH to become available...
==> amazon-ebs.example: Connected to SSH!
==> amazon-ebs.example: Uploading ./welcome.txt => /home/ubuntu/
amazon-ebs.example: welcome.txt 53 B / 53 B [=============================================================================================================================================] 100.00% 0s
==> amazon-ebs.example: Provisioning with shell script: /tmp/packer-shell243199400
amazon-ebs.example: This machine is now detached
==> amazon-ebs.example: Stopping the source instance...
amazon-ebs.example: Stopping instance
==> amazon-ebs.example: Waiting for the instance to stop...
==> amazon-ebs.example: Creating AMI packer example 20210426194519 from instance i-0fe280e360cbd4da3
amazon-ebs.example: AMI: ami-048dd96f85f54811b
==> amazon-ebs.example: Waiting for AMI to become ready...
==> amazon-ebs.example: Terminating the source AWS instance...
==> amazon-ebs.example: Cleaning up any extra volumes...
==> amazon-ebs.example: No volumes to clean up, skipping
==> amazon-ebs.example: Deleting temporary security group...
==> amazon-ebs.example: Deleting temporary keypair...
Build 'amazon-ebs.example' finished after 3 minutes 7 seconds.
==> Wait completed after 3 minutes 7 seconds
==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs.example: AMIs were created:
us-east-1: ami-048dd96f85f54811b
And that’s it. You can see Packer created a custom AMI ami-048dd96f85f54811b in region us-east-1. After you create a new instance from that AMI, your new instance will be automatically attached to Ubuntu Advantage as you can see here:
$ ua status
SERVICE ENTITLED STATUS DESCRIPTION
cc-eal yes n/a Common Criteria EAL2 Provisioning Packages
cis-audit no — Center for Internet Security Audit Tools
esm-apps yes enabled UA Apps: Extended Security Maintenance
esm-infra yes enabled UA Infra: Extended Security Maintenance
fips yes n/a NIST-certified FIPS modules
fips-updates yes n/a Uncertified security updates to FIPS modules
livepatch yes enabled Canonical Livepatch service
Enable services with: ua enable <service>
Account: <redacted>
Subscription: <redacted>
Valid until: 9999-12-31 00:00:00
Technical support level: essential