├── ec2-init.sh ├── deprecated ├── create-ami.sh └── README.md ├── obsd-img-builder.sh └── README.md /ec2-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2015, 2016 Antoine Jacoutot 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | # AWS cloud-init like helper for OpenBSD 18 | # ====================================== 19 | # Install as /usr/local/libexec/ec2-init and append to /etc/hostname.xnf0: 20 | # !/usr/local/libexec/ec2-init 21 | 22 | # XXXTODO https://cloudinit.readthedocs.org/en/latest/topics/format.html 23 | 24 | set -e 25 | 26 | cleanjunk() 27 | { 28 | local _l 29 | # reset root's password 30 | #chpass -a 'root:*:0:0:daemon:0:0:Charlie &:/root:/bin/ksh' 31 | # remove generated keys 32 | rm -f /etc/{iked,isakmpd}/{local.pub,private/local.key} \ 33 | /etc/ssh/ssh_host_* 34 | # remove dhcp client configuration and old leases 35 | rm -f /etc/dhcpleased.conf /var/db/dhcpleased/* 36 | # remove cruft from /tmp 37 | rm -rf /tmp/{.[!.],}* 38 | # reset entropy files 39 | >/etc/random.seed 40 | >/var/db/host.random 41 | # empty log files 42 | rm -f /var/log/[a-zA-Z]*.{{out,log}{,.old},[0-9]}* 43 | for _l in $(find /var/log -type f ! -name '*.gz' -size +0); do 44 | >${_l} 45 | done 46 | } 47 | 48 | ec2_fingerprints() 49 | { 50 | cat <<-'EOF-RC' >>/etc/rc.firsttime 51 | logger -s -t ec2 2>/var/log/cloudinit-output.log </etc/myname 67 | } 68 | 69 | ec2_instanceid() 70 | { 71 | local _instanceid="$(mock meta-data/instance-id)" 72 | print -- "${_instanceid}" >/var/db/instance-id 73 | } 74 | 75 | ec2_pubkey() 76 | { 77 | local _pubkey="$(mock meta-data/public-keys/0/openssh-key)" 78 | print -- "${_pubkey}" >>/home/ec2-user/.ssh/authorized_keys 79 | } 80 | 81 | ec2_userdata() 82 | { 83 | local _script="$(mktemp -p /tmp -t aws-user-data.XXXXXXXXXX)" 84 | mock user-data >${_script} && [[ $(head -1 ${_script}) == @(#!*) ]] || 85 | { rm ${_script}; return 0; } 86 | chmod u+x ${_script} && env -i /bin/sh -c ${_script} && rm ${_script} 87 | } 88 | 89 | mock() 90 | { 91 | [[ -n ${1} ]] 92 | local _ret 93 | _ret=$(ftp -MVo - http://169.254.169.254/latest/${1} 2>/dev/null) 94 | [[ -n ${_ret} ]] && print -- "${_ret}" 95 | } 96 | 97 | mock_pf() 98 | { 99 | [[ -z ${INRC} ]] && return 100 | rcctl get pf status || return 0 101 | case ${1} in 102 | open) 103 | print -- \ 104 | "pass out proto tcp from egress to 169.254.169.254 port www" | 105 | pfctl -f - ;; 106 | close) 107 | print -- "" | pfctl -f - ;; 108 | *) 109 | return 1 ;; 110 | esac 111 | } 112 | 113 | if [[ $(id -u) != 0 ]]; then 114 | echo "${0##*/}: needs root privileges" 115 | exit 1 116 | fi 117 | 118 | mock_pf open 119 | if [[ $(mock meta-data/instance-id) != $(cat /var/db/instance-id 2>/dev/null) ]] 120 | then 121 | cleanjunk # run early to prevent erasing logs from ec2-init 122 | ec2_pubkey 123 | ec2_instanceid # write instance-id _after_ ssh keys are installed 124 | ec2_hostname 125 | ec2_userdata 126 | mock_pf close 127 | ec2_fingerprints 128 | fi 129 | -------------------------------------------------------------------------------- /deprecated/create-ami.sh: -------------------------------------------------------------------------------- 1 | #!/bin/ksh 2 | # 3 | # Copyright (c) 2015, 2016 Antoine Jacoutot 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | # 17 | # create an OpenBSD image and AMI for AWS 18 | 19 | set -e 20 | umask 022 21 | 22 | ################################################################################ 23 | AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:=${AWS_ACCESS_KEY}} 24 | AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:=${AWS_SECRET_KEY}} 25 | AWS_REGION=${AWS_REGION:=eu-west-1} 26 | AWS_AZ=${AWS_AZ:=${AWS_REGION}a} 27 | 28 | MIRROR=${MIRROR:=https://cdn.openbsd.org/pub/OpenBSD} 29 | 30 | TIMESTAMP=$(date -u +%G%m%dT%H%M%SZ) 31 | ################################################################################ 32 | 33 | if [[ $(uname -m) != amd64 ]]; then 34 | echo "${0##*/}: only supports amd64" 35 | exit 1 36 | fi 37 | 38 | if (($(id -u) != 0)); then 39 | echo "${0##*/}: need root privileges" 40 | exit 1 41 | fi 42 | 43 | usage() { 44 | echo "usage: ${0##*/}" >&2 45 | echo " -d \"description\"" >&2 46 | echo " -i \"/path/to/image\"" >&2 47 | echo " -n only create the RAW/VMDK images (not the AMI)" >&2 48 | echo " -r \"release\" (e.g 6.0; default to current)" >&2 49 | exit 1 50 | } 51 | 52 | pr_action() { 53 | echo "=========================================================================" 54 | echo "| ${1}" 55 | echo "=========================================================================" 56 | } 57 | 58 | create_img() { 59 | _WRKDIR=$(mktemp -d -p ${TMPDIR:=/tmp} aws-ami.XXXXXXXXXX) 60 | _IMG=${_WRKDIR}/openbsd-${RELEASE:-current}-amd64-${TIMESTAMP} 61 | local _MNT=${_WRKDIR}/mnt _REL=${RELEASE:-$(uname -r)} _p _m 62 | local _VNDEV=$(vnconfig -l | grep 'not in use' | head -1 | 63 | cut -d ':' -f1) 64 | _REL=$(echo ${_REL} | tr -d '.') 65 | 66 | if [[ -z ${_VNDEV} ]]; then 67 | echo "${0##*/}: no vnd(4) device available" 68 | exit 1 69 | fi 70 | 71 | mkdir -p ${_MNT} 72 | 73 | pr_action "creating image container" 74 | vmctl create ${_IMG} -s 8G 75 | 76 | # default disklabel automatic allocation with the following changes: 77 | # - /usr/obj and /usr/src are removed 78 | # - /var is extended from 200M to 512M to accomodate binpatches, logs... 79 | # - /home is extended with the remaining free space 80 | pr_action "creating and mounting image filesystem" 81 | vnconfig ${_VNDEV} ${_IMG} 82 | fdisk -iy ${_VNDEV} 83 | echo 'A\nd i\nd j\nd k\nR e\n512M\na i\n\n*\n\n/home\nq\ny\n' | 84 | disklabel -EF ${_WRKDIR}/fstab ${_VNDEV} 85 | awk '$2~/^\//{sub(/^.+\./,"",$1);print $1, $2}' ${_WRKDIR}/fstab | 86 | while read _p _m; do 87 | newfs /dev/r${_VNDEV}${_p} 88 | install -d ${_MNT}${_m} 89 | mount /dev/${_VNDEV}${_p} ${_MNT}${_m} 90 | done 91 | 92 | pr_action "fetching sets from ${MIRROR:##*//}" 93 | ( cd ${_WRKDIR} && 94 | ftp -V ${MIRROR}/${RELEASE:-snapshots}/amd64/{bsd{,.mp,.rd},{base,comp,game,man,xbase,xshare,xfont,xserv}${_REL}.tgz} ) 95 | 96 | pr_action "fetching ec2-init" 97 | ftp -V -o ${_WRKDIR}/ec2-init \ 98 | https://raw.githubusercontent.com/ajacoutot/aws-openbsd/master/ec2-init.sh 99 | 100 | pr_action "extracting sets" 101 | for i in ${_WRKDIR}/*${_REL}.tgz ${_MNT}/var/sysmerge/{,x}etc.tgz; do 102 | tar xzphf $i -C ${_MNT} 103 | done 104 | 105 | pr_action "installing MP kernel" 106 | mv ${_WRKDIR}/bsd* ${_MNT} 107 | mv ${_MNT}/bsd ${_MNT}/bsd.sp 108 | mv ${_MNT}/bsd.mp ${_MNT}/bsd 109 | chown 0:0 ${_MNT}/bsd* 110 | 111 | pr_action "installing ec2-init" 112 | install -m 0555 -o root -g bin ${_WRKDIR}/ec2-init \ 113 | ${_MNT}/usr/local/libexec/ec2-init 114 | 115 | pr_action "creating devices" 116 | ( cd ${_MNT}/dev && sh ./MAKEDEV all ) 117 | 118 | pr_action "storing entropy for the initial boot" 119 | dd if=/dev/random of=${_MNT}/var/db/host.random bs=65536 count=1 \ 120 | status=none 121 | dd if=/dev/random of=${_MNT}/etc/random.seed bs=512 count=1 \ 122 | status=none 123 | chmod 600 ${_MNT}/var/db/host.random ${_MNT}/etc/random.seed 124 | 125 | pr_action "installing master boot record" 126 | installboot -r ${_MNT} ${_VNDEV} 127 | 128 | pr_action "configuring the image" 129 | # XXX hardcoded 130 | echo "https://cdn.openbsd.org/pub/OpenBSD" >${_MNT}/etc/installurl 131 | sed -e "s#\(/home ffs rw\)#\1,nodev,nosuid#" \ 132 | -e "s#\(/tmp ffs rw\)#\1,nodev,nosuid#" \ 133 | -e "s#\(/usr ffs rw\)#\1,nodev#" \ 134 | -e "s#\(/usr/X11R6 ffs rw\)#\1,nodev#" \ 135 | -e "s#\(/usr/local ffs rw\)#\1,wxallowed,nodev#" \ 136 | -e "s#\(/var ffs rw\)#\1,nodev,nosuid#" \ 137 | -e '1h;1d;$!H;$!d;G' \ 138 | ${_WRKDIR}/fstab >${_MNT}/etc/fstab 139 | sed -i "s,^tty00.*,tty00 \"/usr/libexec/getty std.9600\" vt220 on secure," \ 140 | ${_MNT}/etc/ttys 141 | echo "stty com0 9600" >${_MNT}/etc/boot.conf 142 | echo "set tty com0" >>${_MNT}/etc/boot.conf 143 | echo "dhcp" >${_MNT}/etc/hostname.xnf0 144 | echo "!/usr/local/libexec/ec2-init" >>${_MNT}/etc/hostname.xnf0 145 | chmod 0640 ${_MNT}/etc/hostname.xnf0 146 | echo "127.0.0.1\tlocalhost" >${_MNT}/etc/hosts 147 | echo "::1\t\tlocalhost" >>${_MNT}/etc/hosts 148 | sed -i "s/^#\(PermitRootLogin\) .*/\1 no/" ${_MNT}/etc/ssh/sshd_config 149 | env -i chroot ${_MNT} ln -sf /usr/share/zoneinfo/UTC /etc/localtime 150 | env -i chroot ${_MNT} ldconfig /usr/local/lib /usr/X11R6/lib 151 | env -i chroot ${_MNT} rcctl disable sndiod 152 | env -i chroot ${_MNT} useradd -G wheel -L staff -c 'EC2 Default User' -g =uid \ 153 | -m -u 1000 ec2-user 154 | echo "permit nopass ec2-user" >${_MNT}/etc/doas.conf 155 | echo "ec2-user" >${_MNT}/root/.forward 156 | 157 | pr_action "relinking to create unique kernel" 158 | sha256 ${_MNT}/bsd | (umask 077; sed "s,${_MNT},," \ 159 | >${_MNT}/var/db/kernel.SHA256) 160 | if [[ -x ${_MNT}/usr/libexec/reorder_kernel ]]; then 161 | env -i chroot ${_MNT} /usr/libexec/reorder_kernel 162 | fi 163 | 164 | pr_action "unmounting the image" 165 | awk '$2~/^\//{sub(/^.+\./,"",$1);print $1, $2}' ${_WRKDIR}/fstab | 166 | tail -r | while read _p _m; do 167 | umount ${_MNT}${_m} 168 | done 169 | vnconfig -u ${_VNDEV} 170 | 171 | pr_action "removing downloaded and temporary files" 172 | rm ${_WRKDIR}/*${_REL}.tgz ${_WRKDIR}/ec2-init || true # non-fatal 173 | rm ${_WRKDIR}/fstab || true # non-fatal 174 | rm -r ${_MNT} || true # non-fatal 175 | 176 | pr_action "image available at:" 177 | echo "${_IMG}" 178 | } 179 | 180 | volume_ids() { 181 | aws --region ${AWS_REGION} --output json ec2 describe-conversion-tasks | \ 182 | python2.7 -c 'from __future__ import print_function;import sys,json; [print(task["ImportVolume"]["Volume"]["Id"]) if "Id" in task["ImportVolume"]["Volume"] else None for task in json.load(sys.stdin)["ConversionTasks"]]' 183 | } 184 | 185 | volume_state() { 186 | local _VOL=$1 187 | 188 | aws --region ${AWS_REGION} --output json ec2 describe-conversion-tasks | \ 189 | python2.7 -c 'from __future__ import print_function;import sys,json; [print(task["ImportVolume"]["Volume"]["Id"],task["State"]) if "Id" in task["ImportVolume"]["Volume"] else None for task in json.load(sys.stdin)["ConversionTasks"]]' | grep "${_VOL}" | awk '{print $NF}' 190 | } 191 | 192 | volume_progress() { 193 | local _VOL=$1 194 | aws --region ${AWS_REGION} --output json ec2 describe-conversion-tasks | \ 195 | python2.7 -c 'from __future__ import print_function;import sys,json; [print(task["ImportVolume"]["Volume"]["Id"],task["StatusMessage"]) if ("Id" in task["ImportVolume"]["Volume"] and "StatusMessage" in task) else None for task in json.load(sys.stdin)["ConversionTasks"]]' | grep "${_VOL}" | awk '{print $2,$3}' 196 | } 197 | 198 | create_ami() { 199 | local _IMGNAME=${_IMG##*/} 200 | local _BUCKETNAME=${_IMGNAME} 201 | local _VMDK=${_IMG}.vmdk 202 | local _VOLIDS_NEW _VOLIDS _v 203 | typeset -l _BUCKETNAME 204 | [[ -z ${TMPDIR} ]] || export _JAVA_OPTIONS=-Djava.io.tmpdir=${TMPDIR} 205 | [[ -z ${http_proxy} ]] || { 206 | local host_port=${http_proxy##*/} 207 | export EC2_JVM_ARGS="-Dhttps.proxyHost=${host_port%%:*} \ 208 | -Dhttps.proxyPort=${host_port##*:}" 209 | } 210 | 211 | if [[ -z ${DESCRIPTION} ]]; then 212 | local DESCRIPTION="OpenBSD ${RELEASE:-current} amd64" 213 | [[ -n ${RELEASE} ]] || 214 | DESCRIPTION="${DESCRIPTION} ${TIMESTAMP}" 215 | fi 216 | 217 | pr_action "converting image to stream-based VMDK" 218 | vmdktool -v ${_VMDK} ${_IMG} 219 | 220 | pr_action "uploading image to S3 and converting to volume in az ${AWS_AZ}" 221 | _VOLIDS="$(volume_ids)" 222 | ec2-import-volume \ 223 | ${_VMDK} \ 224 | -f vmdk \ 225 | --region ${AWS_REGION} \ 226 | -z ${AWS_AZ} \ 227 | -d ${_IMGNAME} \ 228 | -O "${AWS_ACCESS_KEY_ID}" \ 229 | -W "${AWS_SECRET_ACCESS_KEY}" \ 230 | -o "${AWS_ACCESS_KEY_ID}" \ 231 | -w "${AWS_SECRET_ACCESS_KEY}" \ 232 | -b ${_BUCKETNAME} 233 | 234 | _VOLIDS_NEW="$(volume_ids)" 235 | echo 236 | while [[ ${_VOLIDS} == ${_VOLIDS_NEW} ]]; do 237 | sleep 10 238 | _VOLIDS_NEW="$(volume_ids)" 239 | done 240 | _VOL=$(for _v in ${_VOLIDS_NEW}; do echo "${_VOLIDS}" | fgrep -q $_v || 241 | echo $_v; done) 242 | 243 | pr_action "waiting for completed conversion of volume for ${_VOL}" 244 | while /usr/bin/true; do 245 | _STATE="$(volume_state ${_VOL})" 246 | [ "${_STATE}" = "completed" ] && break 247 | [ "${_STATE}" = "active" ] && _PROGRESS="$(volume_progress ${_VOL})" 248 | [ -n "${_PROGRESS}" ] && echo "${_PROGRESS}" 249 | sleep 10 250 | done 251 | 252 | # XXX 253 | #echo 254 | #echo "deleting local and remote disk images" 255 | #rm -rf ${_WRKDIR} 256 | #ec2-delete-disk-image 257 | 258 | pr_action "creating snapshot in region ${AWS_REGION}" 259 | ec2-create-snapshot \ 260 | -O "${AWS_ACCESS_KEY_ID}" \ 261 | -W "${AWS_SECRET_ACCESS_KEY}" \ 262 | --region ${AWS_REGION} \ 263 | -d ${_IMGNAME} \ 264 | ${_VOL} 265 | while [[ -z ${_SNAP} ]]; do 266 | _SNAP=$(ec2-describe-snapshots \ 267 | -O "${AWS_ACCESS_KEY_ID}" \ 268 | -W "${AWS_SECRET_ACCESS_KEY}" \ 269 | --region ${AWS_REGION} 2>/dev/null | 270 | grep "${_VOL}" | 271 | grep "completed.*${_IMGNAME}" | 272 | grep -Eo "snap-[[:alnum:]]*") || true 273 | sleep 10 274 | done 275 | 276 | pr_action "registering new AMI in region ${AWS_REGION}: ${_IMGNAME}" 277 | ec2-register \ 278 | -n ${_IMGNAME} \ 279 | -O "${AWS_ACCESS_KEY_ID}" \ 280 | -W "${AWS_SECRET_ACCESS_KEY}" \ 281 | --region ${AWS_REGION} \ 282 | -a x86_64 \ 283 | -d "${DESCRIPTION}" \ 284 | --root-device-name /dev/sda1 \ 285 | --virtualization-type hvm \ 286 | -s ${_SNAP} 287 | } 288 | 289 | CREATE_AMI=true 290 | CREATE_IMG=true 291 | while getopts d:i:nr: arg; do 292 | case ${arg} in 293 | d) DESCRIPTION="${OPTARG}";; 294 | i) CREATE_IMG=false; _IMG="${OPTARG}";; 295 | n) CREATE_AMI=false;; 296 | r) RELEASE="${OPTARG}";; 297 | *) usage;; 298 | esac 299 | done 300 | 301 | if ${CREATE_AMI}; then 302 | if [[ -z ${AWS_ACCESS_KEY_ID} || -z ${AWS_SECRET_ACCESS_KEY} ]]; then 303 | echo "${0##*/}: AWS credentials aren't set" 304 | exit 1 305 | fi 306 | [[ -n ${JAVA_HOME} ]] || 307 | export JAVA_HOME=$(javaPathHelper -h ec2-api-tools) 2>/dev/null 308 | [[ -n ${EC2_HOME} ]] || export EC2_HOME=/usr/local/ec2-api-tools 309 | which ec2-import-volume >/dev/null 2>&1 || 310 | export PATH=${EC2_HOME}/bin:${PATH} 311 | # XXX seems the aws cli does more checking on the image than the ec2 312 | # tools, preventing creating an OpenBSD AMI; so we need java for now :-( 313 | if ! type ec2-import-volume >/dev/null; then 314 | echo "${0##*/}: needs the EC2 CLI tools (\"ec2-api-tools\")" 315 | exit 1 316 | fi 317 | if ! type vmdktool >/dev/null; then 318 | echo "${0##*/}: needs the vmdktool" 319 | exit 1 320 | fi 321 | fi 322 | 323 | if ${CREATE_IMG}; then 324 | create_img 325 | elif [[ ! -f ${_IMG} ]]; then 326 | echo "${0##*/}: ${_IMG} does not exist" 327 | exit 1 328 | fi 329 | 330 | if ${CREATE_AMI}; then 331 | create_ami 332 | fi 333 | -------------------------------------------------------------------------------- /deprecated/README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED, use at your own risk 2 | 3 | # create-ami. 4 | 5 | ## Prerequisites 6 | 7 | * shell access to OpenBSD 6.1 with internet connection available. 8 | * minimum 12GB free space of /tmp (8GB for disk image and ~4GB for temporary files). 9 | * doas configured; for building as a root the "permit nopass keepenv root as root" in /etc/doas.conf is enough. 10 | * curl, ec2-api-tools, awscli and vmdktool packages installed. 11 | * shell environment variables available. 12 | 13 | export AWS_ACCESS_KEY_ID=YOUR_AWS_ACCES_KEY; 14 | export AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_KEY; 15 | 16 | * Identity and Access Management on AWS configured. 17 | 18 | > YOUR_AWS_ACCES_KEY and YOUR_AWS_SECRET_KEY should have AmazonEC2FullAccess and AmazonS3FullAccess policies assigned. 19 | 20 | 21 | ## Script usage 22 | 23 | ```shell 24 | create-ami.sh [-dinsr] 25 | -d "description" 26 | -i "/path/to/image" 27 | -n only create the RAW/VMDK images (not the AMI) 28 | -r "release (e.g 6.0; default to current)" 29 | ``` 30 | 31 | 32 | ## References 33 | http://blog.d2-si.fr/2016/02/15/openbsd-on-aws/ 34 | 35 | 36 | ## Building example 37 | 38 | ### How to build OpenBSD 6.1 AMI 39 | 40 | The example for creating own OpenBSD 6.1 AMI on host with Vagrant and VirtualBox. Using "ftp.fr.openbsd.org" mirror and Amazon AWS Frankfurt (eu-central-1) region. 41 | 42 | #### Have OpenBSD 6.1 on your host (with Vagrant and VirtualBox installed) 43 | 44 | ```shell 45 | cd /your/work/directory; 46 | vagrant init SierraX/openbsd-6.1; vagrant up --provider virtualbox; 47 | vagrant ssh; 48 | ``` 49 | 50 | #### When logged in to your OpenBSD virtual machine 51 | 52 | ```shell 53 | doas su -; 54 | ``` 55 | 56 | Mount wd0k disk with 12GB as /tmp. 57 | ```shell 58 | umount -f /tmp && mount -o "rw,nodev,nosuid" /dev/wd0k /tmp 59 | ``` 60 | 61 | Install required packages 62 | ```shell 63 | pkg_add curl ec2-api-tools awscli vmdktool; 64 | ``` 65 | 66 | Prepare your environment. 67 | ```shell 68 | export AWS_ACCESS_KEY_ID=000_YOUR_AWS_ACCESS_KEY_HERE; 69 | export AWS_SECRET_ACCESS_KEY=000_AWS_SECRET_KEY_HERE; 70 | export AWS_REGION=eu-central-1; 71 | export MIRROR=https://ftp.fr.openbsd.org/pub/OpenBSD/ 72 | ``` 73 | 74 | Build and upload your image. 75 | ```shell 76 | curl -sS -O https://raw.githubusercontent.com/ajacoutot/aws-openbsd/master/create-ami.sh; 77 | ksh create-ami.sh -r "6.1" -d "OpenBSD 6.1 - my AMI"; 78 | ``` 79 | 80 | Launch your newly created AMI, check public IP and login "ssh ec2-user@public_IP". 81 | You might want to delete S3 volume and EBS volume used during creating process as well as destroying your vagrant instance. 82 | 83 | 84 | ## Script output 85 | 86 | ```shell 87 | ========================================================================= 88 | | creating image container 89 | ========================================================================= 90 | vmctl: imagefile created 91 | ========================================================================= 92 | | creating and mounting image filesystem 93 | ========================================================================= 94 | Writing MBR at offset 0. 95 | Label editor (enter '?' for help at any prompt) 96 | > > > > > [+|-]new size (with unit): [436448] > offset: [9567904] size: [7209296] FS type: [4.2BSD] mount point: [none] Rounding size to bsize (32 sectors): 7209280 97 | > Write new label?: [y] /dev/rvnd1a: 131.2MB in 268672 sectors of 512 bytes 98 | 4 cylinder groups of 32.80MB, 2099 blocks, 4224 inodes each 99 | super-block backups (for fsck -b #) at: 100 | 32, 67200, 134368, 201536, 101 | /dev/rvnd1i: 3520.2MB in 7209280 sectors of 512 bytes 102 | 18 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 103 | super-block backups (for fsck -b #) at: 104 | 32, 414688, 829344, 1244000, 1658656, 2073312, 2487968, 2902624, 3317280, 3731936, 4146592, 4561248, 4975904, 5390560, 5805216, 6219872, 6634528, 7049184, 105 | newfs: reduced number of fragments per cylinder group from 25840 to 25728 to enlarge last cylinder group 106 | /dev/rvnd1d: 201.9MB in 413472 sectors of 512 bytes 107 | 5 cylinder groups of 50.25MB, 3216 blocks, 6528 inodes each 108 | super-block backups (for fsck -b #) at: 109 | 32, 102944, 205856, 308768, 411680, 110 | /dev/rvnd1f: 951.2MB in 1948032 sectors of 512 bytes 111 | 5 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 112 | super-block backups (for fsck -b #) at: 113 | 32, 414688, 829344, 1244000, 1658656, 114 | newfs: reduced number of fragments per cylinder group from 69464 to 69184 to enlarge last cylinder group 115 | /dev/rvnd1g: 542.7MB in 1111456 sectors of 512 bytes 116 | 5 cylinder groups of 135.12MB, 8648 blocks, 17408 inodes each 117 | super-block backups (for fsck -b #) at: 118 | 32, 276768, 553504, 830240, 1106976, 119 | /dev/rvnd1h: 2150.4MB in 4404000 sectors of 512 bytes 120 | 11 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 121 | super-block backups (for fsck -b #) at: 122 | 32, 414688, 829344, 1244000, 1658656, 2073312, 2487968, 2902624, 3317280, 3731936, 4146592, 123 | /dev/rvnd1e: 512.0MB in 1048576 sectors of 512 bytes 124 | 4 cylinder groups of 128.00MB, 8192 blocks, 16384 inodes each 125 | super-block backups (for fsck -b #) at: 126 | 32, 262176, 524320, 786464, 127 | ========================================================================= 128 | | fetching sets from ftp.fr.openbsd.org/pub/OpenBSD/ 129 | ========================================================================= 130 | bsd 100% |*************************************************************************************************************************************************************************************************************************************************************| 10433 KB 00:12 131 | bsd.mp 100% |*************************************************************************************************************************************************************************************************************************************************************| 10499 KB 00:12 132 | bsd.rd 100% |*************************************************************************************************************************************************************************************************************************************************************| 9210 KB 00:10 133 | base61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 52322 KB 01:02 134 | comp61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 46070 KB 00:55 135 | game61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 2707 KB 00:02 136 | man61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 8719 KB 00:10 137 | xbase61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 17497 KB 00:20 138 | xshare61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 4406 KB 00:04 139 | xfont61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 39342 KB 00:45 140 | xserv61.tgz 100% |*************************************************************************************************************************************************************************************************************************************************************| 13001 KB 00:15 141 | ========================================================================= 142 | | fetching ec2-init 143 | ========================================================================= 144 | ec2-init.sh 100% |*************************************************************************************************************************************************************************************************************************************************************| 3342 00:00 145 | ========================================================================= 146 | | extracting sets 147 | ========================================================================= 148 | ========================================================================= 149 | | installing MP kernel 150 | ========================================================================= 151 | ========================================================================= 152 | | installing ec2-init 153 | ========================================================================= 154 | ========================================================================= 155 | | creating devices 156 | ========================================================================= 157 | ========================================================================= 158 | | storing entropy for the initial boot 159 | ========================================================================= 160 | ========================================================================= 161 | | installing master boot record 162 | ========================================================================= 163 | ========================================================================= 164 | | configuring the image 165 | ========================================================================= 166 | ========================================================================= 167 | | unmounting the image 168 | ========================================================================= 169 | ========================================================================= 170 | | removing downloaded and temporary files 171 | ========================================================================= 172 | ========================================================================= 173 | | image available at: /tmp/aws-ami.iZa8EwvRnj/openbsd-6.1-amd64-20170512T114247Z 174 | ========================================================================= 175 | ========================================================================= 176 | | converting image to stream-based VMDK 177 | ========================================================================= 178 | ========================================================================= 179 | | uploading image to S3 and converting to volume in region eu-central-1 180 | ========================================================================= 181 | Requesting volume size: 8 GB 182 | TaskType IMPORTVOLUME TaskId import-vol-fhe7ofgr ExpirationTime 2017-05-19T11:48:25Z Status active StatusMessage Pending 183 | DISKIMAGE DiskImageFormat VMDK DiskImageSize 218832384 VolumeSize 8 AvailabilityZone eu-central-1a ApproximateBytesConverted 0 Description openbsd-6.1-amd64-20170512T114247Z 184 | Creating new manifest at openbsd-6.1-amd64-20170512t114247z/f8025ed1-3c09-4d31-a493-0933aba7a28c/openbsd-6.1-amd64-20170512T114247Z.vmdkmanifest.xml 185 | Uploading the manifest file 186 | Uploading 218832384 bytes across 21 parts 187 | ---------------------------------------------------------------------------------------------------- 188 | Upload progress Estimated time Estimated speed 189 | - 100% [====================>] 8.574 MBps 190 | ********************* All 218832384 Bytes uploaded in 25s ********************* 191 | Done uploading. 192 | Average speed was 8.574 MBps 193 | The disk image for import-vol-fhe7ofgr has been uploaded to Amazon S3 194 | where it is being converted into an EBS volume. You may monitor the 195 | progress of this task by running ec2-describe-conversion-tasks. When 196 | the task is completed, you may use ec2-delete-disk-image to remove the 197 | image from S3. 198 | 199 | ========================================================================= 200 | | creating snapshot in region eu-central-1 201 | ========================================================================= 202 | SNAPSHOT snap-010990909c356e639 vol-07f26466f264949e0 pending 2017-05-12T11:50:59+0000 495039774644 8 openbsd-6.1-amd64-20170512T114247Z Not Encrypted 203 | ========================================================================= 204 | | registering new AMI in region eu-central-1: openbsd-6.1-amd64-20170512T114247Z 205 | ========================================================================= 206 | IMAGE ami-1398417c 207 | ``` 208 | -------------------------------------------------------------------------------- /obsd-img-builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/ksh 2 | # 3 | # Copyright (c) 2015, 2016, 2019 Antoine Jacoutot 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | umask 022 19 | 20 | create_ami() { 21 | local _arch=${ARCH} _bucket_conf _importsnapid _snap 22 | 23 | [[ ${_AWS_REGION} == us-east-1 ]] || 24 | _bucket_conf="--create-bucket-configuration LocationConstraint=${_AWS_REGION}" 25 | 26 | ! [[ ${_arch} == amd64 ]] || _arch=x86_64 27 | 28 | pr_title "converting image to stream-based VMDK" 29 | vmdktool -v ${IMGPATH}.vmdk ${IMGPATH} 30 | 31 | pr_title "uploading image to S3" 32 | aws s3api create-bucket --bucket ${_BUCKETNAME} ${_bucket_conf} 33 | aws s3 cp ${IMGPATH}.vmdk s3://${_BUCKETNAME} 34 | 35 | pr_title "converting VMDK to snapshot" 36 | cat <<-EOF >>${_WRKDIR}/containers.json 37 | { 38 | "Description": "${DESCR}", 39 | "Format": "vmdk", 40 | "UserBucket": { 41 | "S3Bucket": "${_BUCKETNAME}", 42 | "S3Key": "${_IMGNAME}.vmdk" 43 | } 44 | } 45 | EOF 46 | 47 | # Cannot use import-image: "ClientError: Unknown OS / Missing OS files." 48 | #aws ec2 import-image --description "${DESCR}" --disk-containers \ 49 | # file://"${_WRKDIR}/containers.json" 50 | 51 | _importsnapid=$(aws ec2 import-snapshot --description "${DESCR}" \ 52 | --disk-container file://"${_WRKDIR}/containers.json" \ 53 | --role-name ${_IMGNAME} --query "ImportTaskId" --output text) 54 | 55 | while true; do 56 | set -A _snap -- $(aws ec2 describe-import-snapshot-tasks \ 57 | --output text --import-task-ids ${_importsnapid} \ 58 | --query \ 59 | "ImportSnapshotTasks[*].SnapshotTaskDetail.[Status,Progress,SnapshotId]") 60 | echo -ne "\r Progress: ${_snap[1]}%" 61 | [[ ${_snap[0]} == completed ]] && echo && break 62 | sleep 10 63 | done 64 | 65 | pr_title "removing bucket ${_BUCKETNAME}" 66 | aws s3 rb s3://${_BUCKETNAME} --force 67 | 68 | pr_title "registering AMI" 69 | aws ec2 register-image --name "${_IMGNAME}" --architecture ${_arch} \ 70 | --root-device-name /dev/sda1 --virtualization-type hvm \ 71 | --description "${DESCR}" --block-device-mappings \ 72 | DeviceName="/dev/sda1",Ebs={SnapshotId=${_snap[2]}} 73 | } 74 | 75 | create_autoinstallconf() 76 | { 77 | local _autoinstallconf=${_WRKDIR}/auto_install.conf 78 | local _mirror=${MIRROR} 79 | 80 | _mirror=${_mirror#*://} 81 | _mirror=${_mirror%%/*} 82 | 83 | pr_title "creating auto_install.conf" 84 | 85 | cat <<-EOF >>${_autoinstallconf} 86 | System hostname = openbsd 87 | Password for root = ************* 88 | Change the default console to com0 = yes 89 | Setup a user = ec2-user 90 | Full name for user ec2-user = EC2 Default User 91 | Password for user = ************* 92 | What timezone are you in = UTC 93 | Location of sets = cd 94 | Set name(s) = done 95 | EOF 96 | 97 | # XXX if checksum fails 98 | for i in $(jot 11); do 99 | echo "Checksum test for = yes" >>${_autoinstallconf} 100 | done 101 | echo "Continue without verification = yes" >>${_autoinstallconf} 102 | 103 | cat <<-EOF >>${_autoinstallconf} 104 | Location of sets = disk 105 | Is the disk partition already mounted = no 106 | Which disk contains the install media = sd1 107 | Which sd1 partition has the install sets = a 108 | INSTALL.${ARCH} not found. Use sets found here anyway = yes 109 | Set name(s) = site* 110 | Checksum test for = yes 111 | Continue without verification = yes 112 | EOF 113 | } 114 | 115 | create_iam_role() 116 | { 117 | pr_title "creating IAM role" 118 | local _awsarn="aws" 119 | [[ ${_AWS_REGION} != cn-north-1 ]] || 120 | _awsarn="aws-cn" 121 | cat <<-'EOF' >>${_WRKDIR}/trust-policy.json 122 | { 123 | "Version": "2012-10-17", 124 | "Statement": [ 125 | { 126 | "Effect": "Allow", 127 | "Principal": { "Service": "vmie.amazonaws.com" }, 128 | "Action": "sts:AssumeRole", 129 | "Condition": { 130 | "StringEquals":{ 131 | "sts:Externalid": "vmimport" 132 | } 133 | } 134 | } 135 | ] 136 | } 137 | EOF 138 | 139 | cat <<-EOF >>${_WRKDIR}/role-policy.json 140 | { 141 | "Version":"2012-10-17", 142 | "Statement":[ 143 | { 144 | "Effect":"Allow", 145 | "Action":[ 146 | "s3:GetBucketLocation", 147 | "s3:GetObject", 148 | "s3:ListBucket" 149 | ], 150 | "Resource":[ 151 | "arn:${_awsarn}:s3:::${_BUCKETNAME}", 152 | "arn:${_awsarn}:s3:::${_BUCKETNAME}/*" 153 | ] 154 | }, 155 | { 156 | "Effect":"Allow", 157 | "Action":[ 158 | "ec2:ModifySnapshotAttribute", 159 | "ec2:CopySnapshot", 160 | "ec2:RegisterImage", 161 | "ec2:Describe*" 162 | ], 163 | "Resource":"*" 164 | } 165 | ] 166 | } 167 | EOF 168 | 169 | aws iam create-role --role-name ${_IMGNAME} \ 170 | --assume-role-policy-document \ 171 | "file://${_WRKDIR}/trust-policy.json" 172 | 173 | aws iam put-role-policy --role-name ${_IMGNAME} --policy-name \ 174 | ${_IMGNAME} --policy-document \ 175 | "file://${_WRKDIR}/role-policy.json" 176 | } 177 | 178 | create_img() 179 | { 180 | local _bsdrd=${_WRKDIR}/bsd.rd _rdextract=${_WRKDIR}/bsd.rd.extract 181 | local _rdgz=false _rdmnt=${_WRKDIR}/rdmnt _vndev 182 | 183 | create_install_site_disk 184 | 185 | create_autoinstallconf 186 | 187 | pr_title "creating modified bsd.rd for autoinstall" 188 | ftp -MV -o ${_bsdrd} ${MIRROR}/${RELEASE}/${ARCH}/bsd.rd 189 | 190 | # 6.9 onwards uses a compressed rd file 191 | if [[ $(file -bi ${_bsdrd}) == "application/x-gzip" ]]; then 192 | mv ${_bsdrd} ${_bsdrd}.gz 193 | gunzip ${_bsdrd}.gz 194 | _rdgz=true 195 | fi 196 | 197 | rdsetroot -x ${_bsdrd} ${_rdextract} 198 | _vndev=$(vnconfig ${_rdextract}) 199 | install -d ${_rdmnt} 200 | mount /dev/${_vndev}a ${_rdmnt} 201 | cp ${_WRKDIR}/auto_install.conf ${_rdmnt} 202 | umount ${_rdmnt} 203 | vnconfig -u ${_vndev} 204 | rdsetroot ${_bsdrd} ${_rdextract} 205 | 206 | if ${_rdgz}; then 207 | gzip ${_bsdrd} 208 | mv ${_bsdrd}.gz ${_bsdrd} 209 | fi 210 | 211 | pr_title "starting autoinstall inside vmm(4)" 212 | 213 | vmctl create -s ${IMGSIZE}G ${IMGPATH} 214 | 215 | # handle cu(1) EOT 216 | (sleep 10 && vmctl wait ${_IMGNAME} && _tty=$(get_tty ${_IMGNAME}) && 217 | vmctl stop -f ${_IMGNAME} && pkill -f "/usr/bin/cu -l ${_tty}")& 218 | 219 | # XXX handle installation error 220 | # (e.g. ftp: raw.githubusercontent.com: no address associated with name) 221 | vmctl start -b ${_WRKDIR}/bsd.rd -c -L -d ${IMGPATH} -d \ 222 | ${_WRKDIR}/siteXX.img -r ${_WRKDIR}/installXX.iso ${_IMGNAME} 223 | } 224 | 225 | create_install_site() 226 | { 227 | # XXX bsd.mp + relink directory 228 | 229 | pr_title "creating install.site" 230 | 231 | cat <<-'EOF' >>${_WRKDIR}/install.site 232 | chown root:bin /usr/local/libexec/ec2-init 233 | chmod 0555 /usr/local/libexec/ec2-init 234 | 235 | echo "!/usr/local/libexec/ec2-init" >>/etc/hostname.vio0 236 | cp -p /etc/hostname.vio0 /etc/hostname.xnf0 237 | 238 | echo "https://cdn.openbsd.org/pub/OpenBSD" >/etc/installurl 239 | echo "sndiod_flags=NO" >/etc/rc.conf.local 240 | echo "permit keepenv nopass ec2-user" >/etc/doas.conf 241 | 242 | rm /install.site 243 | EOF 244 | 245 | chmod 0555 ${_WRKDIR}/install.site 246 | } 247 | 248 | create_install_site_disk() 249 | { 250 | # XXX trap vnd and mount 251 | 252 | local _cnproxy _rel _relint _retrydl=true _vndev 253 | local _siteimg=${_WRKDIR}/siteXX.img _sitemnt=${_WRKDIR}/siteXX 254 | 255 | [[ ${RELEASE} == snapshots ]] && _rel=$(uname -r) || _rel=${RELEASE} 256 | _relint=${_rel%.*}${_rel#*.} 257 | 258 | create_install_site 259 | 260 | pr_title "creating install_site disk" 261 | 262 | vmctl create -s 1G ${_siteimg} 263 | _vndev="$(vnconfig ${_siteimg})" 264 | fdisk -iy ${_vndev} 265 | echo "a a\n\n\n\nw\nq\n" | disklabel -E ${_vndev} 266 | newfs ${_vndev}a 267 | 268 | install -d ${_sitemnt} 269 | mount /dev/${_vndev}a ${_sitemnt} 270 | install -d ${_sitemnt}/${_rel}/${ARCH} 271 | 272 | pr_title "downloading installation ISO" 273 | while ! ftp -o ${_WRKDIR}/installXX.iso \ 274 | ${MIRROR}/${RELEASE}/${ARCH}/install${_relint}.iso; do 275 | # in case we're running an X.Y snapshot while X.Z is out; 276 | # (e.g. running on 6.4-current and installing 6.5-beta) 277 | ${_retrydl} || pr_err "cannot download installation ISO" 278 | _relint=$((_relint+1)) 279 | _retrydl=false 280 | done 281 | 282 | pr_title "downloading ec2-init" 283 | [[ ${_AWS_REGION} != cn-north-1 ]] || 284 | _cnproxy="https://ghproxy.com/" 285 | install -d ${_WRKDIR}/usr/local/libexec/ 286 | ftp -o ${_WRKDIR}/usr/local/libexec/ec2-init \ 287 | ${_cnproxy}https://raw.githubusercontent.com/ajacoutot/aws-openbsd/master/ec2-init.sh 288 | 289 | pr_title "storing siteXX.tgz into install_site disk" 290 | cd ${_WRKDIR} && tar czf \ 291 | ${_sitemnt}/${_rel}/${ARCH}/site${_relint}.tgz ./install.site \ 292 | ./usr/local/libexec/ec2-init 293 | 294 | umount ${_sitemnt} 295 | vnconfig -u ${_vndev} 296 | } 297 | 298 | get_tty() 299 | { 300 | local _tty _vmname=$1 301 | [[ -n ${_vmname} ]] 302 | 303 | vmctl status | grep "${_vmname}" | while read -r _ _ _ _ _ _tty _; do 304 | echo /dev/${_tty} 305 | done 306 | } 307 | 308 | pr_err() 309 | { 310 | echo "${0##*/}: ${1}" 1>&2 && return ${2:-1} 311 | } 312 | 313 | pr_title() 314 | { 315 | local _line=$(printf "%80s" | tr ' ' '=') 316 | echo "${_line}\n| ${@}\n${_line}" 317 | } 318 | 319 | setup_vmd() 320 | { 321 | if ! $(rcctl check vmd >/dev/null); then 322 | pr_title "starting vmd(8)" 323 | rcctl start vmd 324 | _RESET_VMD=true 325 | fi 326 | } 327 | 328 | trap_handler() 329 | { 330 | set +e # we're trapped 331 | 332 | if aws iam get-role --role-name ${_IMGNAME} >/dev/null 2>&1; then 333 | pr_title "removing IAM role" 334 | aws iam delete-role-policy --role-name ${_IMGNAME} \ 335 | --policy-name ${_IMGNAME} 2>/dev/null 336 | aws iam delete-role --role-name ${_IMGNAME} 2>/dev/null 337 | fi 338 | 339 | if ${_RESET_VMD:-false}; then 340 | pr_title "stopping vmd(8)" 341 | rcctl stop vmd >/dev/null 342 | fi 343 | 344 | if [[ -n ${_WRKDIR} ]]; then 345 | rmdir ${_WRKDIR} 2>/dev/null || 346 | pr_title "work directory: ${_WRKDIR}" 347 | fi 348 | } 349 | 350 | usage() 351 | { 352 | echo "usage: ${0##*/} 353 | -a \"architecture\" -- default to \"amd64\" 354 | -d \"description\" -- AMI description; defaults to \"openbsd-\$release-\$timestamp\" 355 | -i \"path to RAW image\" -- use image at path instead of creating one 356 | -m \"install mirror\" -- defaults to installurl(5) or \"https://cdn.openbsd.org/pub/OpenBSD\" 357 | -n -- only create a RAW image (don't convert to an AMI nor push to AWS) 358 | -r \"release\" -- e.g \"6.5\"; default to \"snapshots\" 359 | -s \"image size in GB\" -- default to \"12\"" 360 | 361 | return 1 362 | } 363 | 364 | while getopts a:d:i:m:nr:s: arg; do 365 | case ${arg} in 366 | a) ARCH="${OPTARG}" ;; 367 | d) DESCR="${OPTARG}" ;; 368 | i) IMGPATH="${OPTARG}" ;; 369 | m) MIRROR="${OPTARG}" ;; 370 | n) CREATE_AMI=false ;; 371 | r) RELEASE="${OPTARG}" ;; 372 | s) IMGSIZE="${OPTARG}" ;; 373 | *) usage ;; 374 | esac 375 | done 376 | 377 | trap 'trap_handler' EXIT 378 | trap exit HUP INT TERM 379 | 380 | _TS=$(date -u +%G%m%dT%H%M%SZ) 381 | _WRKDIR=$(mktemp -d -p ${TMPDIR:=/tmp} aws-ami.XXXXXXXXXX) 382 | 383 | # XXX add support for installation proxy in create_img 384 | if [[ -n ${http_proxy} ]]; then 385 | export HTTP_PROXY=${http_proxy} 386 | export HTTPS_PROXY=${http_proxy} 387 | fi 388 | 389 | ARCH=${ARCH:-amd64} 390 | CREATE_AMI=${CREATE_AMI:-true} 391 | IMGSIZE=${IMGSIZE:-12} 392 | RELEASE=${RELEASE:-snapshots} 393 | 394 | if [[ -z ${MIRROR} ]]; then 395 | MIRROR=$(while read _line; do _line=${_line%%#*}; [[ -n ${_line} ]] && 396 | print -r -- "${_line}"; done /dev/null 398 | [[ ${MIRROR} == @(http|https)://* ]] || 399 | MIRROR="https://cdn.openbsd.org/pub/OpenBSD" 400 | fi 401 | 402 | _IMGNAME=openbsd-${RELEASE}-${ARCH}-${_TS} 403 | [[ ${RELEASE} == snapshots ]] && 404 | _IMGNAME=${_IMGNAME%snapshots*}current${_IMGNAME#*snapshots} 405 | [[ -n ${IMGPATH} ]] && _IMGNAME=${IMGPATH##*/} || 406 | IMGPATH=${_WRKDIR}/${_IMGNAME} 407 | _BUCKETNAME=$(echo ${_IMGNAME} | tr '[:upper:]' '[:lower:]')-${RANDOM} 408 | DESCR=${DESCR:-${_IMGNAME}} 409 | 410 | readonly _BUCKETNAME _IMGNAME _TS _WRKDIR HTTP_PROXY HTTPS_PROXY 411 | readonly CREATE_AMI DESCR IMGPATH IMGSIZE MIRROR RELEASE 412 | 413 | # requirements checks to build the RAW image 414 | if [[ ! -f ${IMGPATH} ]]; then 415 | (($(id -u) != 0)) && pr_err "need root privileges" 416 | grep -q ^vmm0 /var/run/dmesg.boot || pr_err "need vmm(4) support" 417 | [[ ${_IMGNAME}} != [[:alpha:]]* ]] && 418 | pr_err "image name must start with a letter" 419 | fi 420 | 421 | # requirements checks to build and register the AMI 422 | if ${CREATE_AMI}; then 423 | [[ ${ARCH} == i386 ]] && 424 | pr_err "${ARCH} lacks xen(4) support to run on AWS" 425 | type aws >/dev/null 2>&1 || pr_err "package \"awscli\" is not installed" 426 | type vmdktool >/dev/null 2>&1 || 427 | pr_err "package \"vmdktool\" is not installed" 428 | aws ec2 describe-regions --region-names us-east-1 >/dev/null || 429 | pr_err "you may need to export: 430 | AWS_CONFIG_FILE 431 | AWS_DEFAULT_PROFILE 432 | AWS_SHARED_CREDENTIALS_FILE" 433 | fi 434 | 435 | if [[ ! -f ${IMGPATH} ]]; then 436 | setup_vmd 437 | create_img 438 | fi 439 | 440 | if ${CREATE_AMI}; then 441 | _AWS_REGION=$(aws configure get region) 442 | create_iam_role 443 | create_ami 444 | fi 445 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS-OpenBSD 2 | 3 | AWS playground for OpenBSD kids. 4 | Running whatever is in this repo will propably end up destroying a kitten factory. 5 | 6 | ## Prerequisites for obsd-img-builder.sh (OpenBSD AMI builder) 7 | 8 | * shell access to OpenBSD current >6.5 with vmm(4) support and Internet access 9 | * 3.5GB of free space in ${TMPDIR} 10 | * *awscli* and *vmdktool* packages installed 11 | * AWS IAM user with enough permissions (AmazonEC2FullAccess, AmazonS3FullAccess, IAMFullAccess) 12 | * AWS environment variables properly set (when not use root's awscli configuration): 13 | * *AWS_CONFIG_FILE* 14 | * *AWS_DEFAULT_PROFILE* (when not using the *default* profile) 15 | * *AWS_SHARED_CREDENTIALS_FILE* 16 | 17 | ## Script usage 18 | 19 | ``` 20 | usage: obsd-img-builder.sh 21 | -a "architecture" -- default to "amd64" 22 | -d "description" -- AMI description; defaults to "openbsd-$release-$timestamp" 23 | -i "path to RAW image" -- use image at path instead of creating one 24 | -m "install mirror" -- defaults to installurl(5) or "https://cdn.openbsd.org/pub/OpenBSD" 25 | -n -- only create a RAW image (don't convert to an AMI nor push to AWS) 26 | -r "release" -- e.g "6.5"; default to "snapshots" 27 | -s "image size in GB" -- default to "12" 28 | ``` 29 | 30 | ## TODO 31 | 32 | * arm64 support 33 | * MP support 34 | 35 | ### Misc 36 | 37 | ### KARL (kernel address randomized link) 38 | 39 | While a newly built image/AMI will contain a randomized kernel, it is advised 40 | to add user-data at first boot that will reboot the instance once the first 41 | randomization is done. This is so that every instance will indeed run a 42 | different relinked kernel. 43 | 44 | ### ENI hotplug 45 | 46 | ``` 47 | # cat <<-'EOF' >/etc/hotplug/attach 48 | #!/bin/sh 49 | 50 | case $1 in 51 | 3) echo "!/sbin/dhclient -i routers $2" >/etc/hostname.$2 52 | /bin/sh /etc/netstart $i 53 | ;; 54 | esac 55 | EOF 56 | # chmod 0555 /etc/hotplug/attach 57 | # rcctl enable hotplugd && rcctl start hotplugd 58 | ``` 59 | 60 | ### Build sample output 61 | 62 | ``` 63 | # export AWS_CONFIG_FILE=/home/myuser/.aws/config 64 | # export AWS_DEFAULT_PROFILE=builder 65 | # export AWS_SHARED_CREDENTIALS_FILE=/home/myuser/.aws/credentials 66 | ``` 67 | 68 | ``` 69 | # ./obsd-img-builder.sh 70 | ================================================================================ 71 | | creating install.site 72 | ================================================================================ 73 | ================================================================================ 74 | | creating sd1 and storing siteXX.tgz 75 | ================================================================================ 76 | vmctl: raw imagefile created 77 | Writing MBR at offset 0. 78 | Label editor (enter '?' for help at any prompt) 79 | > offset: [128] size: [2096972] FS type: [4.2BSD] > > No label changes. 80 | /dev/rvnd0a: 1023.9MB in 2096960 sectors of 512 bytes 81 | 6 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 82 | super-block backups (for fsck -b #) at: 83 | 32, 414688, 829344, 1244000, 1658656, 2073312, 84 | ================================================================================ 85 | | creating auto_install.conf 86 | ================================================================================ 87 | ================================================================================ 88 | | creating modified bsd.rd for autoinstall 89 | ================================================================================ 90 | SHA256.sig 100% |******************************************************| 2141 00:00 91 | bsd.rd 100% |******************************************************| 9971 KB 00:01 92 | checking signature: /etc/signify/openbsd-65-base.pub 93 | ================================================================================ 94 | | starting autoinstall inside vmm(4) 95 | ================================================================================ 96 | vmctl: raw imagefile created 97 | Connected to /dev/ttyp5 (speed 115200) 98 | Copyright (c) 1982, 1986, 1989, 1991, 1993 99 | The Regents of the University of California. All rights reserved. 100 | Copyright (c) 1995-2019 OpenBSD. All rights reserved. https://www.OpenBSD.org 101 | 102 | OpenBSD 6.5-beta (RAMDISK_CD) #783: Thu Mar 21 21:42:12 MDT 2019 103 | deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/RAMDISK_CD 104 | real mem = 520093696 (496MB) 105 | avail mem = 500412416 (477MB) 106 | mainbus0 at root 107 | bios0 at mainbus0 108 | acpi at bios0 not configured 109 | cpu0 at mainbus0: (uniprocessor) 110 | cpu0: Intel(R) Core(TM) i5-5300U CPU @ 2.30GHz, 2295.72 MHz, 06-3d-04 111 | cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,PCLMUL,SSSE3,FMA3,CX16,SSE4.1,SSE4.2,MOVBE,POPCNT,AES,XSAVE,AVX,F16C,RDRAND,HV,NXE,PAGE1GB,LONG,LAHF,ABM,3DNOWP,ITSC,FSGSBASE,BMI1,AVX2,SMEP,BMI2,ERMS,RDSEED,ADX,SMAP,MELTDOWN 112 | cpu0: 256KB 64b/line 8-way L2 cache 113 | pvbus0 at mainbus0: OpenBSD 114 | pci0 at mainbus0 bus 0 115 | pchb0 at pci0 dev 0 function 0 "OpenBSD VMM Host" rev 0x00 116 | virtio0 at pci0 dev 1 function 0 "Qumranet Virtio RNG" rev 0x00 117 | viornd0 at virtio0 118 | virtio0: irq 3 119 | virtio1 at pci0 dev 2 function 0 "Qumranet Virtio Network" rev 0x00 120 | vio0 at virtio1: address fe:e1:bb:d1:44:83 121 | virtio1: irq 5 122 | virtio2 at pci0 dev 3 function 0 "Qumranet Virtio Storage" rev 0x00 123 | vioblk0 at virtio2 124 | scsibus0 at vioblk0: 2 targets 125 | sd0 at scsibus0 targ 0 lun 0: SCSI3 0/direct fixed 126 | sd0: 12288MB, 512 bytes/sector, 25165824 sectors 127 | virtio2: irq 6 128 | virtio3 at pci0 dev 4 function 0 "Qumranet Virtio Storage" rev 0x00 129 | vioblk1 at virtio3 130 | scsibus1 at vioblk1: 2 targets 131 | sd1 at scsibus1 targ 0 lun 0: SCSI3 0/direct fixed 132 | sd1: 1024MB, 512 bytes/sector, 2097152 sectors 133 | virtio3: irq 7 134 | virtio4 at pci0 dev 5 function 0 "OpenBSD VMM Control" rev 0x00 135 | vmmci0 at virtio4 136 | virtio4: irq 9 137 | isa0 at mainbus0 138 | com0 at isa0 port 0x3f8/8 irq 4: ns16450, no fifo 139 | com0: console 140 | softraid0 at root 141 | scsibus2 at softraid0: 256 targets 142 | root on rd0a swap on rd0b dump on rd0b 143 | erase ^?, werase ^W, kill ^U, intr ^C, status ^T 144 | 145 | Welcome to the OpenBSD/amd64 6.5 installation program. 146 | Starting non-interactive mode in 5 seconds... 147 | (I)nstall, (U)pgrade, (A)utoinstall or (S)hell? waiting for vm openbsd-current-amd64-20190322T091544Z: 148 | Performing non-interactive install... 149 | Terminal type? [vt220] vt220 150 | System hostname? (short form, e.g. 'foo') openbsd 151 | 152 | Available network interfaces are: vio0 vlan0. 153 | Which network interface do you wish to configure? (or 'done') [vio0] vio0 154 | IPv4 address for vio0? (or 'dhcp' or 'none') [dhcp] dhcp 155 | IPv6 address for vio0? (or 'autoconf' or 'none') [none] none 156 | Available network interfaces are: vio0 vlan0. 157 | Which network interface do you wish to configure? (or 'done') [done] done 158 | DNS domain name? (e.g. 'example.com') [my.domain] my.domain 159 | Using DNS nameservers at 100.64.11.2 160 | 161 | Password for root account? 162 | Public ssh key for root account? [none] none 163 | Start sshd(8) by default? [yes] yes 164 | Change the default console to com0? [yes] yes 165 | Available speeds are: 9600 19200 38400 57600 115200. 166 | Which speed should com0 use? (or 'done') [115200] 115200 167 | Setup a user? (enter a lower-case loginname, or 'no') [no] ec2-user 168 | Full name for user ec2-user? [ec2-user] EC2 Default User 169 | Password for user ec2-user? 170 | Public ssh key for user ec2-user [none] none 171 | WARNING: root is targeted by password guessing attacks, pubkeys are safer. 172 | Allow root ssh login? (yes, no, prohibit-password) [no] no 173 | What timezone are you in? ('?' for list) [UTC] UTC 174 | 175 | Available disks are: sd0 sd1. 176 | Which disk is the root disk? ('?' for details) [sd0] sd0 177 | No valid MBR or GPT. 178 | Use (W)hole disk MBR, whole disk (G)PT or (E)dit? [whole] whole 179 | Setting OpenBSD MBR partition to whole sd0...done. 180 | URL to autopartitioning template for disklabel? [none] none 181 | The auto-allocated layout for sd0 is: 182 | # size offset fstype [fsize bsize cpg] 183 | a: 255.1M 64 4.2BSD 2048 16384 1 # / 184 | b: 290.2M 522496 swap 185 | c: 12288.0M 0 unused 186 | d: 288.2M 1116832 4.2BSD 2048 16384 1 # /tmp 187 | e: 353.2M 1706976 4.2BSD 2048 16384 1 # /var 188 | f: 1005.1M 2430432 4.2BSD 2048 16384 1 # /usr 189 | g: 447.0M 4488864 4.2BSD 2048 16384 1 # /usr/X11R6 190 | h: 1339.3M 5404416 4.2BSD 2048 16384 1 # /usr/local 191 | i: 1342.0M 8147296 4.2BSD 2048 16384 1 # /usr/src 192 | j: 5204.1M 10895776 4.2BSD 2048 16384 1 # /usr/obj 193 | k: 1759.8M 21553728 4.2BSD 2048 16384 1 # /home 194 | Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout? [a] a 195 | newfs: reduced number of fragments per cylinder group from 32648 to 32512 to enlarge last cylinder group 196 | /dev/rsd0a: 255.1MB in 522432 sectors of 512 bytes 197 | 5 cylinder groups of 63.50MB, 4064 blocks, 8192 inodes each 198 | /dev/rsd0k: 1759.8MB in 3604032 sectors of 512 bytes 199 | 9 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 200 | newfs: reduced number of fragments per cylinder group from 36880 to 36728 to enlarge last cylinder group 201 | /dev/rsd0d: 288.2MB in 590144 sectors of 512 bytes 202 | 5 cylinder groups of 71.73MB, 4591 blocks, 9216 inodes each 203 | /dev/rsd0f: 1005.1MB in 2058432 sectors of 512 bytes 204 | 5 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 205 | newfs: reduced number of fragments per cylinder group from 57216 to 56992 to enlarge last cylinder group 206 | /dev/rsd0g: 447.0MB in 915552 sectors of 512 bytes 207 | 5 cylinder groups of 111.31MB, 7124 blocks, 14336 inodes each 208 | /dev/rsd0h: 1339.3MB in 2742880 sectors of 512 bytes 209 | 7 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 210 | /dev/rsd0j: 5204.1MB in 10657952 sectors of 512 bytes 211 | 26 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 212 | /dev/rsd0i: 1342.0MB in 2748480 sectors of 512 bytes 213 | 7 cylinder groups of 202.47MB, 12958 blocks, 25984 inodes each 214 | /dev/rsd0e: 353.2MB in 723456 sectors of 512 bytes 215 | 4 cylinder groups of 88.31MB, 5652 blocks, 11392 inodes each 216 | Available disks are: sd1. 217 | Which disk do you wish to initialize? (or 'done') [done] done 218 | /dev/sd0a (9861f4b2a79df4f4.a) on /mnt type ffs (rw, asynchronous, local) 219 | /dev/sd0k (9861f4b2a79df4f4.k) on /mnt/home type ffs (rw, asynchronous, local, nodev, nosuid) 220 | /dev/sd0d (9861f4b2a79df4f4.d) on /mnt/tmp type ffs (rw, asynchronous, local, nodev, nosuid) 221 | /dev/sd0f (9861f4b2a79df4f4.f) on /mnt/usr type ffs (rw, asynchronous, local, nodev) 222 | /dev/sd0g (9861f4b2a79df4f4.g) on /mnt/usr/X11R6 type ffs (rw, asynchronous, local, nodev) 223 | /dev/sd0h (9861f4b2a79df4f4.h) on /mnt/usr/local type ffs (rw, asynchronous, local, nodev) 224 | /dev/sd0j (9861f4b2a79df4f4.j) on /mnt/usr/obj type ffs (rw, asynchronous, local, nodev, nosuid) 225 | /dev/sd0i (9861f4b2a79df4f4.i) on /mnt/usr/src type ffs (rw, asynchronous, local, nodev, nosuid) 226 | /dev/sd0e (9861f4b2a79df4f4.e) on /mnt/var type ffs (rw, asynchronous, local, nodev, nosuid) 227 | 228 | Let's install the sets! 229 | Location of sets? (disk http or 'done') [disk] http 230 | HTTP proxy URL? (e.g. 'http://proxy:8080', or 'none') [none] none 231 | HTTP Server? (hostname, list#, 'done' or '?') [cdn.openbsd.org] cdn.openbsd.org 232 | Server directory? [pub/OpenBSD/snapshots/amd64] pub/OpenBSD/snapshots/amd64 233 | 234 | Select sets by entering a set name, a file name pattern or 'all'. De-select 235 | sets by prepending a '-', e.g.: '-game*'. Selected sets are labelled '[X]'. 236 | [X] bsd [X] comp65.tgz [X] xbase65.tgz [X] xserv65.tgz 237 | [X] bsd.rd [X] man65.tgz [X] xshare65.tgz 238 | [X] base65.tgz [X] game65.tgz [X] xfont65.tgz 239 | Set name(s)? (or 'abort' or 'done') [done] done 240 | Get/Verify SHA256.sig 100% |**************************| 2141 00:00 241 | Signature Verified 242 | Get/Verify bsd 100% |**************************| 15492 KB 00:02 243 | Get/Verify bsd.rd 100% |**************************| 9971 KB 00:01 244 | Get/Verify base65.tgz 100% |**************************| 191 MB 00:27 245 | Get/Verify comp65.tgz 100% |**************************| 93001 KB 00:12 246 | Get/Verify man65.tgz 100% |**************************| 7383 KB 00:01 247 | Get/Verify game65.tgz 100% |**************************| 2740 KB 00:00 248 | Get/Verify xbase65.tgz 100% |**************************| 20664 KB 00:03 249 | Get/Verify xshare65.tgz 100% |**************************| 4448 KB 00:01 250 | Get/Verify xfont65.tgz 100% |**************************| 39342 KB 00:05 251 | Get/Verify xserv65.tgz 100% |**************************| 16684 KB 00:02 252 | Installing bsd 100% |**************************| 15492 KB 00:00 253 | Installing bsd.rd 100% |**************************| 9971 KB 00:00 254 | Installing base65.tgz 100% |**************************| 191 MB 00:18 255 | Extracting etc.tgz 100% |**************************| 256 KB 00:00 256 | Installing comp65.tgz 100% |**************************| 93001 KB 00:14 257 | Installing man65.tgz 100% |**************************| 7383 KB 00:01 258 | Installing game65.tgz 100% |**************************| 2740 KB 00:00 259 | Installing xbase65.tgz 100% |**************************| 20664 KB 00:02 260 | Extracting xetc.tgz 100% |**************************| 6935 00:00 261 | Installing xshare65.tgz 100% |**************************| 4448 KB 00:01 262 | Installing xfont65.tgz 100% |**************************| 39342 KB 00:03 263 | Installing xserv65.tgz 100% |**************************| 16684 KB 00:01 264 | Location of sets? (disk http or 'done') [done] disk 265 | Is the disk partition already mounted? [yes] no 266 | Available disks are: sd0 sd1. 267 | Which disk contains the install media? (or 'done') [sd1] sd1 268 | Pathname to the sets? (or 'done') [6.5/amd64] 6.5/amd64 269 | INSTALL.amd64 not found. Use sets found here anyway? [no] yes 270 | 271 | Select sets by entering a set name, a file name pattern or 'all'. De-select 272 | sets by prepending a '-', e.g.: '-game*'. Selected sets are labelled '[X]'. 273 | [ ] site65.tgz 274 | Set name(s)? (or 'abort' or 'done') [done] site* 275 | [X] site65.tgz 276 | Set name(s)? (or 'abort' or 'done') [done] done 277 | Directory does not contain SHA256.sig. Continue without verification? [no] yes 278 | Installing site65.tgz 100% |**************************| 372 00:00 279 | Location of sets? (disk http or 'done') [done] done 280 | Saving configuration files... done. 281 | Making all device nodes... done. 282 | Relinking to create unique kernel... done. 283 | 284 | CONGRATULATIONS! Your OpenBSD install has been successfully completed! 285 | 286 | When you login to your new system the first time, please read your mail 287 | using the 'mail' command. 288 | 289 | syncing disks... done 290 | vmmci0: powerdown 291 | rebooting... 292 | terminated vm 11 293 | stopping vm openbsd-current-amd64-20190322T091544Z: forced to terminate vm 11 294 | 295 | [SIGTERM] 296 | ================================================================================ 297 | | creating IAM role 298 | ================================================================================ 299 | { 300 | "Role": { 301 | "AssumeRolePolicyDocument": { 302 | "Version": "2012-10-17", 303 | "Statement": [ 304 | { 305 | "Action": "sts:AssumeRole", 306 | "Effect": "Allow", 307 | "Condition": { 308 | "StringEquals": { 309 | "sts:Externalid": "vmimport" 310 | } 311 | }, 312 | "Principal": { 313 | "Service": "vmie.amazonaws.com" 314 | } 315 | } 316 | ] 317 | }, 318 | "RoleId": "AROAJ724UC5U3JGJ5EZ7C", 319 | "CreateDate": "2019-03-22T09:18:45Z", 320 | "RoleName": "openbsd-current-amd64-20190322T091544Z", 321 | "Path": "/", 322 | "Arn": "arn:aws:iam::360116137065:role/openbsd-current-amd64-20190322T091544Z" 323 | } 324 | } 325 | ================================================================================ 326 | | converting image to stream-based VMDK 327 | ================================================================================ 328 | ================================================================================ 329 | | uploading image to S3 330 | ================================================================================ 331 | { 332 | "Location": "http://openbsd-current-amd64-20190322t091544z-29476.s3.amazonaws.com/" 333 | } 334 | upload: ./openbsd-current-amd64-20190322T091544Z.vmdk to s3://openbsd-current-amd64-20190322t091544z-29476/openbsd-current-amd64-20190322T091544Z.vmdk 335 | ================================================================================ 336 | | converting VMDK to snapshot 337 | ================================================================================ 338 | Progress: None% 339 | ================================================================================ 340 | | removing bucket openbsd-current-amd64-20190322t091544z-29476 341 | ================================================================================ 342 | delete: s3://openbsd-current-amd64-20190322t091544z-29476/openbsd-current-amd64-20190322T091544Z.vmdk 343 | remove_bucket: openbsd-current-amd64-20190322t091544z-29476 344 | ================================================================================ 345 | | registering AMI 346 | ================================================================================ 347 | { 348 | "ImageId": "ami-0d1cf7bb6f969621f" 349 | } 350 | ================================================================================ 351 | | removing IAM role 352 | ================================================================================ 353 | ================================================================================ 354 | | work directory: /tmp/aws-ami.p0MJZxjBcr 355 | ================================================================================ 356 | ``` 357 | 358 | Instanciate the AMI and connect to it using SSH: 359 | 360 | ``` 361 | $ ssh ec2-user@${IPADDR} 362 | ``` 363 | --------------------------------------------------------------------------------