RSSAmplifier

Signs of Triviality · Aug 17, 2024

Creating NetBSD EC2 AMIs

0
Sign in to vote or save

netmeister.org

August 17th, 2024

The reference platform for both of the classes I teach (Advanced Programming in the UNIX Environment and System Administration) has been NetBSD for about two decades now. I provide students with instructions for how to install NetBSD in VirtualBox or UTM, but also want them to use Amazon EC2. Unfortunately, the NetBSD project does not provide up to date Amazon Machine Images (AMIs) for EC2, so I have been creating my own. This page describes how - primarily for myself, so I remember the steps next semester if I need to roll a new image.

Here are instructions to create an amd64 image from scratch.

Fetching the NetBSD image

In this example, I'm using NetBSD/evbarm. As of August 2024, the latest release for NetBSD is 10.0; you may want to update the steps below for different releases in the future.

$ ftp https://ftp.netbsd.org/pub/NetBSD/NetBSD-10.0/evbarm-aarch64/binary/gzimg/arm64.img.gz
Trying [2001:470:a085:999::21]:443 ...
Requesting https://ftp.netbsd.org/pub/NetBSD/NetBSD-10.0/evbarm-aarch64/binary/gzimg/arm64.img.gz
100% |*******************************************| 380 MiB  426.87 KiB/s    00:00 ETA
$ 

Installing bsdec2-image-upload

The tool we use to build the image is bsdec2-image-upload. You can install it from pkgsrc or via pkgin:

$ sudo pkgin -y install bsdec2-image-upload
calculating dependencies...done.
1 package to install:
  bsdec2-image-upload-1.4.5nb1
0 to refresh, 0 to upgrade, 1 to install
0B to download, 63K to install
installing bsdec2-image-upload-1.4.5nb1...
pkg_install warnings: 0, errors: 0
reading local summary...
processing local summary...
marking bsdec2-image-upload-1.4.5nb1 as non auto-removable
$ 

Alternatively, you can of course also install it from GitHub:

$ git clone https://github.com/cperciva/bsdec2-image-upload.git
Cloning into 'bsdec2-image-upload'...
[...]
$ cd bsdec2-image-upload
$ make
[...]
cc -o bsdec2-image-upload main.o sha256.o elasticarray.o asprintf.o entropy.o
getopt.o hexify.o insecure_memzero.o warnp.o aws_readkeys.o aws_sign.o
rfc3986.o sslreq.o   -lcrypto -lssl
$ ./bsdec2-image-upload/bsdec2-image-upload -h
usage: bsdec2-image-upload [--public] [--publicamis] [--allregions] [--publicsnap]
[--ssm-name <path>] [--sriov] [--ena] [--arm64] [--vhd] <disk image>
<name> <description> <region> <bucket> <AWS keyfile>
[<topicarn> <releaseversion> <imageversion>]
$ 

Note that depending on your platform you may want to specify an alternate location for OpenSSL. For example, on macOS, I had to point to /opt/homebrew by specifying:

$ make CFLAGS="-I/opt/homebrew/include" LDFLAGS="-L/opt/homebrew/lib -Wl,-rpath,/opt/homebrew/lib"

Create necessary AWS resources

You will need a file containing access credentials for an account with the right privileges (e.g., as described in the SETUP file). If you're lazy and you only have one set of access credentials configured for use with the AWS CLI, you can probably do the following:

$ umask 077
$ awk '/=/ { print toupper($1) "=" $3 }' ~/.aws/credentials |
        sed -e 's/AWS_//' -e 's/SECRET_ACCESS_KEY/ACCESS_KEY_SECRET/' > keyfile

Next, you'll want to create a new S3 bucket. Remember that amazingly the S3 bucket name must be globally unique:

$ export S3BUCKET=${USER}-netbsd-amis
$ aws s3 mb s3://${S3BUCKET}
make_bucket: jschauma-netbsd-amis
$ 

Making changes to the image

The default NetBSD image will already do the right thing when running in EC2. That is, it will correctly detect the fact that it's running in EC2 and install the specified SSH key for the ec2-user user. However, should you want to customize the image, you can do so by first mounting the image using vndconfig(8):

$ gzip -d arm64.img.gz
$ su
# vndconfig vnd0 arm64.img
# dmesg | grep vnd0
[    49.790348] vnd0: GPT GUID: 987939cb-c08e-4614-88c3-6749b5d3104f
[    49.790348] dk3 at vnd0: "EFI", 163840 blocks at 32768, type: msdos
[    49.790348] dk4 at vnd0: "netbsd-root", 2891776 blocks at 196608, type: ffs
# mount /dev/dk4 /mnt
# cd /mnt
# ls
.cshrc    bin       etc       libexec   proc      sbin      usr
.profile  boot      lib       mnt       rescue    stand     var
altroot   dev       libdata   netbsd    root      tmp
#
[ make changes here ]
# cd
# umount /mnt
# vndconfig -u vnd0
# exit
$ 

Running bsdec2-image-upload

Running the bsdec2-image-upload command will then upload the image to the S3 bucket, create a snapshot, and finally create the AMI:

$ export AWS_REGION=$(awk '/^region =/ { print $3}' ~/.aws/config)
$ bsdec2-image-upload --sriov --ena --arm64 arm64.img    \
"NetBSD 10.0 Arm" "NetBSD/evbarm 10.0 $(date +%Y-%m-%d)" \
${AWS_REGION} ${S3BUCKET} keyfile
[...]
Uploading volume manifest... done.
Importing volume: Progress: 40% done.
Creating snapshot....... done.
Registering AMI... done.
Created AMI in us-east-1 region: ami-01eeb2af939d69edd
$ 

(Note from experience, wasting at least 30 minutes on chasing wrong ends: if you mistype the AWS region, the command will fail with a misleading error message (SSL handshake failed).)

As mentioned above, the command uploads the image to the S3 bucket. Those files are no longer needed once the AMI has been created, but bsdec2-image-upload does not remove them. To avoid charges for storing unneeded files, you can safely nuke the folder it created:

$ aws s3 ls s3://${S3BUCKET}
                           PRE 88d97df5b81413acc10503ba8c997fe8/
$ aws s3 ls s3://${S3BUCKET}/88d97df5b81413acc10503ba8c997fe8/
[...]
2024-08-16 15:42:46   10485760 part97
2024-08-16 15:42:51   10485760 part98
2024-08-16 15:42:58   10485760 part99
$ aws s3 rm --recursive s3://${S3BUCKET}/88d97df5b81413acc10503ba8c997fe8/
[...]
delete: s3://jschauma-netbsd-amis/88d97df5b81413acc10503ba8c997fe8/part97
delete: s3://jschauma-netbsd-amis/88d97df5b81413acc10503ba8c997fe8/part98
delete: s3://jschauma-netbsd-amis/88d97df5b81413acc10503ba8c997fe8/part99
$ 

You can also delete the entire bucket (aws s3 rb s3://${S3BUCKET}), but keeping an empty bucket doesn't incur any charges.

You should now be able to launch the new instance. Since this is an Arm image, you want to use either an a1 or a t4g instance:

$ export AMI=ami-01eeb2af939d69edd
$ aws ec2 run-instances --image-id ${AMI} --instance-type t4g.nano
[...]
$ ssh ec2-user@ec2-3-85-77-28.compute-1.amazonaws.com
NetBSD 10.0 (GENERIC64) #0: Thu Mar 28 08:33:33 UTC 2024
Welcome to NetBSD!
ip-10-10-0-24$ uname -a
NetBSD ip-10-10-0-24.ec2.internal 10.0 NetBSD 10.0 (GENERIC64) #0: Thu Mar 28 08:33:33 UTC 2024 mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC64 evbarm
ip-10-10-0-24$ ifconfig -a
ena0: flags=0x8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	capabilities=0x200<IP4CSUM_Tx>
	enabled=0x200<IP4CSUM_Tx>
	ec_capabilities=0x4<JUMBO_MTU>
	ec_enabled=0
	address: 0e:50:7e:03:4f:b3
	media: Ethernet autoselect
	status: active
	inet6 fe80::cd2b:35fb:2408:cc4f%ena0/64 flags 0 scopeid 0x1
	inet6 2600:1f18:400c:b800:5606:9173:aacc:ea32/128 flags 0
	inet 10.10.0.24/26 broadcast 10.10.0.63 flags 0
lo0: flags=0x8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33624
	status: active
	inet6 ::1/128 flags 0x20<NODAD>
	inet6 fe80::1%lo0/64 flags 0 scopeid 0x2
	inet 127.0.0.1/8 flags 0
ip-10-10-0-24$ 

If you're happy with the image, you can then mark it as public to allow other users to launch instances from it:

$ aws ec2 modify-image-attribute --image-id ${AMI} \
    --launch-permission "Add=[{Group=all}]"

August 17th, 2024


Links:

Read the original on netmeister.org

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.