├── .gitignore ├── 1-storage ├── general.tf ├── storage.tf ├── terraform.tfvars └── variables.tf ├── 2-build-machine ├── .gitignore ├── builder.tf ├── templates.tf ├── templates │ ├── build-ports.tpl │ ├── download-from-s3.tpl │ ├── init.tpl │ ├── shrc.tpl │ └── upload-to-s3.tpl ├── terraform.tfvars ├── uploads │ ├── bin │ │ ├── ebs-init │ │ └── prepare-testporting │ ├── pkglists │ │ └── default-11armv6-default │ ├── ports │ │ └── default │ │ │ └── Readme.md │ ├── poudriere.conf │ └── poudriere.d │ │ ├── make.conf │ │ ├── py35-make.conf │ │ ├── repo.key │ │ └── repo.key.pub └── variables.tf ├── LICENSE ├── Readme.md └── terraform.tfvars.example /.gitignore: -------------------------------------------------------------------------------- 1 | terraform.tfstate 2 | terraform.tfstate.backup 3 | .terraform 4 | /terraform.tfvars 5 | -------------------------------------------------------------------------------- /1-storage/general.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | } 6 | 7 | data "aws_availability_zones" "available" { 8 | state = "available" 9 | } 10 | 11 | output "availability_zone" { 12 | value = "${aws_ebs_volume.poudriere.availability_zone}" 13 | } 14 | -------------------------------------------------------------------------------- /1-storage/storage.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ebs_volume" "poudriere" { 2 | availability_zone = "${data.aws_availability_zones.available.names[0]}" 3 | size = "${var.ebs_size}" 4 | } 5 | 6 | output "ebs_id" { 7 | value = "${aws_ebs_volume.poudriere.id}" 8 | } 9 | 10 | resource "aws_s3_bucket" "packages" { 11 | bucket = "${var.s3_bucket_name}" 12 | region = "${var.aws_region}" 13 | force_destroy = "true" 14 | acl = "public-read" 15 | 16 | website { 17 | index_document = "index.html" 18 | error_document = "error.html" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /1-storage/terraform.tfvars: -------------------------------------------------------------------------------- 1 | ../terraform.tfvars -------------------------------------------------------------------------------- /1-storage/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_access_key" { } 2 | variable "aws_secret_key" { } 3 | variable "aws_region" { } 4 | variable "ebs_size" { } 5 | variable "s3_bucket_name" { } 6 | -------------------------------------------------------------------------------- /2-build-machine/.gitignore: -------------------------------------------------------------------------------- 1 | /init-ssh 2 | 3 | /uploads/ports/default/* 4 | !/uploads/ports/default/Readme.md 5 | 6 | /uploads/pkglists/* 7 | !/uploads/pkglists/default.example 8 | -------------------------------------------------------------------------------- /2-build-machine/builder.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | access_key = "${var.aws_access_key}" 4 | secret_key = "${var.aws_secret_key}" 5 | } 6 | 7 | data "terraform_remote_state" "storage-poudriere" { 8 | backend = "local" 9 | config = { 10 | path = "../1-storage/terraform.tfstate" 11 | } 12 | } 13 | 14 | resource "aws_key_pair" "port-builder" { 15 | key_name = "port-builder" 16 | public_key = "${file("${var.ssh_key}.pub")}" 17 | } 18 | 19 | resource "aws_volume_attachment" "poudriere" { 20 | device_name = "/dev/sdf" 21 | volume_id = "${data.terraform_remote_state.storage-poudriere.ebs_id}" 22 | instance_id = "${aws_instance.freebsd-builder.id}" 23 | } 24 | 25 | resource "aws_instance" "freebsd-builder" { 26 | ami = "${lookup(var.freebsd_11_0_ami, var.aws_region)}" 27 | instance_type = "${var.instance_type}" 28 | key_name = "${aws_key_pair.port-builder.key_name}" 29 | 30 | availability_zone = "${data.terraform_remote_state.storage-poudriere.availability_zone}" 31 | 32 | user_data = "${data.template_file.init.rendered}" 33 | 34 | root_block_device = { 35 | volume_size = "10" 36 | delete_on_termination = "true" 37 | } 38 | 39 | connection { 40 | type = "ssh" 41 | user = "ec2-user" 42 | private_key = "${file("${var.ssh_key}")}" 43 | timeout = "10m" 44 | } 45 | 46 | # Creates script for establishing a ssh connection 47 | provisioner "local-exec" { 48 | command = "echo ssh -i ${var.ssh_key} ec2-user@${self.public_dns} > init-ssh && chmod +x init-ssh" 49 | } 50 | 51 | # Sleeps a bit because the builder will be busy setting-up 52 | provisioner "local-exec" { 53 | command = "sleep 300" 54 | } 55 | 56 | # Creates temporary directories for port-builder and distfiles 57 | provisioner "remote-exec" { 58 | inline = [ 59 | "mkdir -p /tmp/port-builder /tmp/distfiles" 60 | ] 61 | } 62 | 63 | # Uploads port-builder's necessities 64 | provisioner "file" { 65 | source = "uploads/" 66 | destination = "/tmp/port-builder" 67 | } 68 | 69 | # Creates and uploads template files 70 | provisioner "file" { 71 | content = "${data.template_file.build-ports.rendered}" 72 | destination = "/tmp/port-builder/bin/build-ports" 73 | } 74 | provisioner "file" { 75 | content = "${data.template_file.download-from-s3.rendered}" 76 | destination = "/tmp/port-builder/bin/download-from-s3" 77 | } 78 | provisioner "file" { 79 | content = "${data.template_file.upload-to-s3.rendered}" 80 | destination = "/tmp/port-builder/bin/upload-to-s3" 81 | } 82 | provisioner "file" { 83 | content = "${data.template_file.shrc.rendered}" 84 | destination = "/home/ec2-user/.shrc" 85 | } 86 | 87 | provisioner "remote-exec" { 88 | inline = [ 89 | "sudo mkdir -p /usr/local/etc/poudriere.d /var/cache/ccache", 90 | "chmod +x /tmp/port-builder/bin/*", 91 | "sudo /tmp/port-builder/bin/download-from-s3", 92 | "sudo cp /tmp/port-builder/poudriere.conf /usr/local/etc", 93 | "sudo cp -r /tmp/port-builder/poudriere.d/* /usr/local/etc/poudriere.d", 94 | ] 95 | } 96 | } 97 | 98 | resource "null_resource" "initialisation" { 99 | depends_on = ["aws_volume_attachment.poudriere"] 100 | 101 | connection { 102 | type = "ssh" 103 | host = "${aws_instance.freebsd-builder.public_ip}" 104 | user = "ec2-user" 105 | private_key = "${file("${var.ssh_key}")}" 106 | } 107 | 108 | provisioner "remote-exec" { 109 | inline = [ 110 | "sudo /tmp/port-builder/bin/ebs-init", 111 | ] 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /2-build-machine/templates.tf: -------------------------------------------------------------------------------- 1 | data "template_file" "init" { 2 | template = "${file("templates/init.tpl")}" 3 | 4 | vars { 5 | firstboot_pkgs_list = "sudo awscli poudriere dialog4ports qemu-user-static tmux" 6 | } 7 | } 8 | 9 | data "template_file" "build-ports" { 10 | template = "${file("templates/build-ports.tpl")}" 11 | 12 | vars { 13 | trees = "${var.build_trees}" 14 | jails = "${var.build_jails}" 15 | sets = "${var.build_sets}" 16 | } 17 | } 18 | 19 | data "template_file" "download-from-s3" { 20 | template = "${file("templates/download-from-s3.tpl")}" 21 | 22 | vars { 23 | s3_bucket_name = "${var.s3_bucket_name}" 24 | aws_access_key = "${var.aws_access_key}" 25 | aws_secret_key = "${var.aws_secret_key}" 26 | aws_region = "${var.aws_region}" 27 | } 28 | } 29 | 30 | data "template_file" "upload-to-s3" { 31 | template = "${file("templates/upload-to-s3.tpl")}" 32 | 33 | vars { 34 | s3_bucket_name = "${var.s3_bucket_name}" 35 | aws_access_key = "${var.aws_access_key}" 36 | aws_secret_key = "${var.aws_secret_key}" 37 | aws_region = "${var.aws_region}" 38 | } 39 | } 40 | 41 | data "template_file" "shrc" { 42 | template = "${file("templates/shrc.tpl")}" 43 | 44 | vars { 45 | aws_access_key = "${var.aws_access_key}" 46 | aws_secret_key = "${var.aws_secret_key}" 47 | aws_region = "${var.aws_region}" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /2-build-machine/templates/build-ports.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # TODO: Check if one is root 4 | 5 | trees="${trees}" 6 | jails="${jails}" 7 | sets="${sets}" 8 | 9 | # TODO: Test if supplied input is correct -- otherwise: exit 10 | pconfd=/usr/local/etc/poudriere.d 11 | pdatad=/usr/local/poudriere 12 | pbdir=/tmp/port-builder 13 | 14 | # Ports trees 15 | for t in $sets 16 | do 17 | # TODO: Update existing (manged!) ports trees 18 | if [ ! -d $pdatad/ports/$t ] 19 | then 20 | echo 21 | echo "--> Creating ports tree: $t" 22 | echo 23 | 24 | if poudriere ports -l | tail +2 | cut -wf 1 | grep '^$t$' >/dev/null 2>&1 25 | then 26 | echo "--> Poudriere claims that ports tree exists but it doesn't." 27 | echo " Deleting the ports tree in poudriere's cache..." 28 | poudriere -d -p $t 29 | echo 30 | fi 31 | poudriere ports -c -p $t 32 | fi 33 | 34 | # Copies user provided ports to ports tree 35 | test -d $pbdir/ports/$t && cp -vr $pbdir/ports/$t/* /usr/local/poudriere/ports/$t 36 | 37 | # If there are jails for ARM prepare for crossbuilding 38 | case "$jails" in 39 | *arm*) 40 | echo 41 | echo "--> Preparing for crossbuilding" 42 | echo 43 | 44 | # Sets crossbuilding flag 45 | crossbuilding="-x" 46 | 47 | # Gets /usr/src for building native-xtools 48 | fetch -o /tmp ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/11.0-RELEASE/src.txz 49 | tar -C / -xzvf /tmp/src.txz 50 | 51 | service qemu_user_static onestart &>/dev/null 52 | ;; 53 | esac 54 | 55 | for j in $jails 56 | do 57 | method=$(echo $j | cut -d '_' -f 1) 58 | name=$(echo $j | cut -d '_' -f 2) 59 | arch=$(echo $j | cut -d '_' -f 3) 60 | rel=$(echo $j | cut -d '_' -f 4) 61 | 62 | if [ ! -d $pdatad/jails/$j ] 63 | then 64 | echo 65 | echo "--> Creating jail: $name" 66 | echo " method: $method" 67 | echo " architecture: $arch" 68 | echo " release: $rel" 69 | echo 70 | 71 | if poudriere jail -l | tail +2 | cut -wf 1 | grep '^$name$' >/dev/null 2>&1 72 | then 73 | echo "--> Poudriere claims that jail exists but it doesn't." 74 | echo " Deleting the jail in pourdiere's cache..." 75 | poudriere -d -j $name 76 | echo 77 | fi 78 | 79 | # TODO: I am not sure whether this works bc of $crossbuilding flag at 80 | # the end 81 | poudriere jail -c -j $name -a $arch -v $rel -m $method $crossbuilding 82 | fi 83 | 84 | # Sets 85 | for z in $sets 86 | do 87 | echo 88 | echo "--> Building ports from list $pkglist" 89 | echo " tree: $t" 90 | echo " jail: $name" 91 | echo " set: $z" 92 | echo 93 | 94 | pkglist=$pbdir/pkglists/$t-$name-$z 95 | 96 | if [ -f $pkglist ] 97 | then 98 | poudriere bulk -p $t -j $name -z $z -f $pkglist 99 | else 100 | echo "Cannot build ports: No pkglist provided for above combination." 101 | fi 102 | done 103 | done 104 | done 105 | 106 | upload-to-s3 107 | 108 | # vim:set ft=sh: 109 | -------------------------------------------------------------------------------- /2-build-machine/templates/download-from-s3.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export AWS_ACCESS_KEY_ID=${aws_access_key} 3 | export AWS_SECRET_ACCESS_KEY=${aws_secret_key} 4 | export AWS_DEFAULT_REGION=${aws_region} 5 | 6 | # Copies poudriere configuration from S3 7 | aws s3 sync s3://${s3_bucket_name}/pdr /usr/local/etc --only-show-errors 8 | 9 | # vim:set ft=sh: 10 | -------------------------------------------------------------------------------- /2-build-machine/templates/init.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if grep -q firstboot_pkgs_list /etc/rc.conf 4 | then 5 | sed -Ie 's/^firstboot_pkgs_list=.*$/firstboot_pkgs_list="${firstboot_pkgs_list}"/' /etc/rc.conf 6 | else 7 | echo 'firstboot_pkgs_list="${firstboot_pkgs_list}"' >> /etc/rc.conf 8 | fi 9 | 10 | echo 'ZFS_ENABLE="YES"' >> /etc/rc.conf 11 | mkdir -p /usr/local/etc/sudoers.d 12 | echo 'ec2-user ALL=(ALL) NOPASSWD: ALL' >> /usr/local/etc/sudoers.d/ec2-user 13 | 14 | # vim: set ft=sh: 15 | -------------------------------------------------------------------------------- /2-build-machine/templates/shrc.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export AWS_ACCESS_KEY_ID=${aws_access_key} 3 | export AWS_SECRET_ACCESS_KEY=${aws_secret_key} 4 | export AWS_DEFAULT_REGION=${aws_region} 5 | 6 | export PATH=$PATH:/tmp/port-builder/bin 7 | 8 | # vim:set ft=sh: 9 | -------------------------------------------------------------------------------- /2-build-machine/templates/upload-to-s3.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export AWS_ACCESS_KEY_ID=${aws_access_key} 3 | export AWS_SECRET_ACCESS_KEY=${aws_secret_key} 4 | export AWS_DEFAULT_REGION=${aws_region} 5 | 6 | # Copies poudriere configuration to S3 7 | aws s3 sync /usr/local/etc s3://${s3_bucket_name}/pdr \ 8 | --acl 'public-read' \ 9 | --only-show-errors \ 10 | --delete \ 11 | --exclude "*" \ 12 | --include "poudriere*" 13 | 14 | # Copies built packages to S3 15 | for dir in /usr/local/poudriere/data/packages/*/ 16 | do 17 | if [ -d "$dir" ] 18 | then 19 | aws s3 sync "$dir.latest/" "s3://${s3_bucket_name}/pkg/$(basename $dir)" \ 20 | --acl 'public-read' \ 21 | --only-show-errors \ 22 | --delete 23 | fi 24 | done 25 | 26 | # vim:set ft=sh: 27 | -------------------------------------------------------------------------------- /2-build-machine/terraform.tfvars: -------------------------------------------------------------------------------- 1 | ../terraform.tfvars -------------------------------------------------------------------------------- /2-build-machine/uploads/bin/ebs-init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Description: This script initialises the attached EBS drive. 4 | 5 | ZPOOL=tank 6 | 7 | # Note: It is important to use `zpool import` instead of `zpool status`. If 8 | # there *is* a pool available but it is detached, `zpool status` will claim 9 | # that there are no pools available. If a new EBS was created that has never 10 | # been attached, `zpool import` echos nothing but terminates with an error. 11 | if ! zpool import 2>&1 12 | then 13 | # Creates the initial ZFS pool (only needed when attaching *new* EBS) 14 | # Note: This will automatically import it 15 | echo "Initialising ZFS pool..." 16 | zpool create $ZPOOL /dev/xbd5 17 | elif zpool import 2>&1 | grep -q -e "tank" -e "pool can be imported" 18 | then 19 | # Imports created zpool 20 | echo "Importing ZFS pool..." 21 | zpool import $ZPOOL 22 | else 23 | echo "Some error occured while creating or importing the ZFS pool." 24 | exit 1 25 | fi 26 | 27 | -------------------------------------------------------------------------------- /2-build-machine/uploads/bin/prepare-testporting: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pconfd=/usr/local/etc/poudriere.d 4 | pdatad=/usr/local/poudriere 5 | pbdir=/tmp/port-builder 6 | 7 | # Ports tree 8 | for t in default 9 | do 10 | poudriere ports -c -p $t 11 | 12 | # Copies user provided ports to ports tree 13 | cp -r $pbdir/ports/$t/* $pdatad/ports/$t 14 | 15 | # Jail 16 | for j in 11amd64 17 | do 18 | poudriere jail -c -j $j -v 11.0-RELEASE 19 | done 20 | done 21 | 22 | # vim:set ft=sh: 23 | -------------------------------------------------------------------------------- /2-build-machine/uploads/pkglists/default-11armv6-default: -------------------------------------------------------------------------------- 1 | www/chromium 2 | www/firefox 3 | -------------------------------------------------------------------------------- /2-build-machine/uploads/ports/default/Readme.md: -------------------------------------------------------------------------------- 1 | Everything under this directory will be added to poudriere's default ports 2 | tree. 3 | -------------------------------------------------------------------------------- /2-build-machine/uploads/poudriere.conf: -------------------------------------------------------------------------------- 1 | 2 | # Poudriere can optionally use ZFS for its ports/jail storage. For 3 | # ZFS define ZPOOL, otherwise set NO_ZFS=yes 4 | # 5 | #### ZFS 6 | # The pool where poudriere will create all the filesystems it needs 7 | # poudriere will use tank/${ZROOTFS} as its root 8 | # 9 | # You need at least 7GB of free space in this pool to have a working 10 | # poudriere. 11 | # 12 | ZPOOL=tank 13 | 14 | ### NO ZFS 15 | # To not use ZFS, define NO_ZFS=yes 16 | #NO_ZFS=yes 17 | 18 | # root of the poudriere zfs filesystem, by default /poudriere 19 | ZROOTFS=/poudriere 20 | 21 | # the host where to download sets for the jails setup 22 | # You can specify here a host or an IP 23 | # replace _PROTO_ by http or ftp 24 | # replace _CHANGE_THIS_ by the hostname of the mirrors where you want to fetch 25 | # by default: ftp://ftp.freebsd.org 26 | # 27 | # Also note that every protocols supported by fetch(1) are supported here, even 28 | # file:/// 29 | # Suggested: https://download.FreeBSD.org 30 | FREEBSD_HOST=https://download.FreeBSD.org 31 | 32 | # By default the jails have no /etc/resolv.conf, you will need to set 33 | # RESOLV_CONF to a file on your hosts system that will be copied has 34 | # /etc/resolv.conf for the jail, except if you don't need it (using an http 35 | # proxy for example) 36 | RESOLV_CONF=/etc/resolv.conf 37 | 38 | # The directory where poudriere will store jails and ports 39 | BASEFS=/usr/local/poudriere 40 | 41 | # The directory where the jail will store the packages and logs 42 | # by default a zfs filesystem will be created and set to 43 | # ${BASEFS}/data 44 | # 45 | #POUDRIERE_DATA=${BASEFS}/data 46 | 47 | # Use portlint to check ports sanity 48 | USE_PORTLINT=no 49 | 50 | # When building packages, a memory device can be used to speedup the build. 51 | # Only one of MFSSIZE or USE_TMPFS is supported. TMPFS is generally faster 52 | # and will expand to the needed amount of RAM. MFS is a slower since it 53 | # uses UFS and several abstraction layers. 54 | 55 | # If set WRKDIRPREFIX will be mdmfs of the given size (mM or gG) 56 | #MFSSIZE=4G 57 | 58 | # Use tmpfs(5) 59 | # This can be a space-separated list of options: 60 | # wrkdir - Use tmpfs(5) for port building WRKDIRPREFIX 61 | # data - Use tmpfs(5) for poudriere cache/temp build data 62 | # localbase - Use tmpfs(5) for LOCALBASE (installing ports for packaging/testing) 63 | # all - Run the entire build in memory, including builder jails. 64 | # yes - Only enables tmpfs(5) for wrkdir 65 | # no - Disable use of tmpfs(5) 66 | # EXAMPLE: USE_TMPFS="wrkdir data" 67 | USE_TMPFS=yes 68 | 69 | # How much memory to limit tmpfs size to for *each builder* in GiB 70 | # (default: none) 71 | #TMPFS_LIMIT=8 72 | 73 | # How much memory to limit jail processes to for *each builder* 74 | # in GiB (default: none) 75 | #MAX_MEMORY=8 76 | 77 | # How many file descriptors to limit each jail process to (default: 1024) 78 | #MAX_FILES=1024 79 | 80 | # If set the given directory will be used for the distfiles 81 | # This allows to share the distfiles between jails and ports tree 82 | DISTFILES_CACHE=/tmp/distfiles 83 | 84 | # If set the ports tree or source tree marked to use svn will use the defined 85 | # mirror (default: svn.FreeBSD.org) 86 | # The SSL fingerprints are published here: 87 | # https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/svn.html#svn-mirrors 88 | #SVN_HOST=svn.FreeBSD.org 89 | 90 | # Automatic OPTION change detection 91 | # When bulk building packages, compare the options from kept packages to 92 | # the current options to be built. If they differ, the existing package 93 | # will be deleted and the port will be rebuilt. 94 | # Valid options: yes, no, verbose 95 | # verbose will display the old and new options 96 | #CHECK_CHANGED_OPTIONS=verbose 97 | 98 | # Automatic Dependency change detection 99 | # When bulk building packages, compare the dependencies from kept packages to 100 | # the current dependencies for every port. If they differ, the existing package 101 | # will be deleted and the port will be rebuilt. This helps catch changes such 102 | # as DEFAULT_RUBY_VERSION, PERL_VERSION, WITHOUT_X11 that change dependencies 103 | # for many ports. 104 | # Valid options: yes, no 105 | #CHECK_CHANGED_DEPS=yes 106 | 107 | 108 | # Path to the RSA key to sign the PKGNG repo with. See pkg-repo(8) 109 | PKG_REPO_SIGNING_KEY=/usr/local/etc/poudriere.d/repo.key 110 | 111 | 112 | # ccache support. Supply the path to your ccache cache directory. 113 | # It will be mounted into the jail and be shared among all jails. 114 | CCACHE_DIR=/var/cache/ccache 115 | # 116 | 117 | # parallel build support. 118 | # 119 | # By default poudriere uses hw.ncpu to determine the number of builders. 120 | # You can override this default by changing PARALLEL_JOBS here, or 121 | # by specifying the -J flag to bulk/testport. 122 | # 123 | # Example to define PARALLEL_JOBS to one single job 124 | # PARALLEL_JOBS=1 125 | 126 | # How many jobs should be used for preparing the build? These tend to 127 | # be more IO bound and may be worth tweaking. Default: PARALLEL_JOBS * 1.25 128 | # PREPARE_PARALLEL_JOBS=1 129 | 130 | 131 | # If set, failed builds will save the WRKDIR to ${POUDRIERE_DATA}/wrkdirs 132 | # SAVE_WRKDIR=yes 133 | 134 | # Choose the default format for the workdir packing: could be tar,tgz,tbz,txz 135 | # default is tbz 136 | # WRKDIR_ARCHIVE_FORMAT=tbz 137 | 138 | # Disable linux support 139 | # NOLINUX=yes 140 | 141 | # By default poudriere sets FORCE_PACKAGE 142 | # To disable it (useful when building public packages): 143 | # NO_FORCE_PACKAGE=yes 144 | 145 | # By default poudriere sets PACKAGE_BUILDING 146 | # To disable it: 147 | # NO_PACKAGE_BUILDING=yes 148 | 149 | # If you are using a proxy define it here: 150 | # export HTTP_PROXY=bla 151 | # export FTP_PROXY=bla 152 | # 153 | # Cleanout the restricted packages 154 | # NO_RESTRICTED=yes 155 | 156 | # By default MAKE_JOBS is disabled to allow only one process per cpu 157 | # Use the following to allow it anyway 158 | # ALLOW_MAKE_JOBS=yes 159 | 160 | # List of packages that will always be allowed to use MAKE_JOBS 161 | # regardless of ALLOW_MAKE_JOBS. This is useful for allowing ports 162 | # which holdup the rest of the queue to build more quickly. 163 | #ALLOW_MAKE_JOBS_PACKAGES="pkg ccache py*" 164 | 165 | # Timestamp every line of build logs 166 | # Default: no 167 | #TIMESTAMP_LOGS=no 168 | 169 | # URL where your POUDRIERE_DATA/logs are hosted 170 | # This will be used for giving URL hints to the HTML output when 171 | # scheduling and starting builds 172 | #URL_BASE=http://yourdomain.com/poudriere/ 173 | 174 | 175 | # This defines the max time (in seconds) that a command may run for a build 176 | # before it is killed for taking too long. Default: 86400 177 | #MAX_EXECUTION_TIME=86400 178 | 179 | # This defines the time (in seconds) before a command is considered to 180 | # be in a runaway state for having no output on stdout. Default: 7200 181 | #NOHANG_TIME=7200 182 | 183 | 184 | # The repository is updated atomically if set yes. This leaves the 185 | # repository untouched until the build completes. This involves using 186 | # hardlinks and symlinks. The operations are fast, but can be intrusive 187 | # for remote syncing or backups. 188 | # Recommended to always keep on. 189 | # Default: yes 190 | #ATOMIC_PACKAGE_REPOSITORY=yes 191 | 192 | # When using ATOMIC_PACKAGE_REPOSITORY, commit the packages if some 193 | # packages fail to build. Ignored ports are considered successful. 194 | # This can be set to 'no' to only commit the packages once no failures 195 | # are encountered. 196 | # Default: yes 197 | #COMMIT_PACKAGES_ON_FAILURE=yes 198 | 199 | # Keep older package repositories. This can be used to rollback a system 200 | # or to bisect issues by changing the repository to one of the older 201 | # versions and reinstalling everything with `pkg upgrade -f` 202 | # ATOMIC_PACKAGE_REPOSITORY is required for this. 203 | # Default: no 204 | #KEEP_OLD_PACKAGES=no 205 | 206 | # How many old package repositories to keep with KEEP_OLD_PACKAGES 207 | # Default: 5 208 | #KEEP_OLD_PACKAGES_COUNT=5 209 | 210 | # Make testing errors fatal. 211 | # If set to 'no', ports with test failure will be marked as failed but still 212 | # packaged to permit testing dependent ports (useful for bulk -t -a) 213 | # Default: yes 214 | #PORTTESTING_FATAL=yes 215 | 216 | # Define the building jail hostname to be used when building the packages 217 | # Some port/packages hardcode the hostname of the host during build time 218 | # This is a necessary setup for reproducible builds. 219 | #BUILDER_HOSTNAME=pkg.FreeBSD.org 220 | 221 | # Define to get a predictable timestamp on the ports tree 222 | # This is a necessary setup for reproducible builds. 223 | #PRESERVE_TIMESTAMP=yes 224 | 225 | # Define to yes to build and stage as a regular user 226 | # Default: no. 227 | # Note that to use ccache with BUILD_AS_NON_ROOT you will need to 228 | # use a non-shared CCACHE_DIR that is only built by PORTBUILD_USER and chowned 229 | # to that user. Then set CCACHE_DIR_NON_ROOT_SAFE to yes. 230 | #BUILD_AS_NON_ROOT=no 231 | 232 | # Define to the username to build as when BUILD_AS_NON_ROOT is yes. 233 | # Default: nobody (uid PORTBUILD_UID) 234 | #PORTBUILD_USER=nobody 235 | 236 | # Define to the uid to use for PORTBUILD_USER if the user does not 237 | # already exist in the jail. 238 | # Default: 65532 239 | #PORTBUILD_UID=65534 240 | 241 | # Define pkgname globs to boost priority for 242 | # Default: none 243 | #PRIORITY_BOOST="pypy openoffice*" 244 | 245 | # Define format for buildnames 246 | # Default: %Y-%m-%d_%Hh%Mm%Ss 247 | # ISO8601: 248 | #BUILDNAME_FORMAT="%FT%TZ" 249 | 250 | # Define format for build duration times 251 | # Default: %H:%M:%S 252 | #DURATION_FORMAT="%H:%M:%S" 253 | 254 | # Use colors when in a TTY 255 | # Default: yes 256 | #USE_COLORS=yes 257 | 258 | # Only build what is requested. Do not rebuild build deps if nothing requested 259 | # depends on them. This can create an inconsistent repository if you often 260 | # build one-off packages but expect the repository to stay consistent. 261 | # Defaut: yes 262 | #TRIM_ORPHANED_BUILD_DEPS=yes 263 | -------------------------------------------------------------------------------- /2-build-machine/uploads/poudriere.d/make.conf: -------------------------------------------------------------------------------- 1 | OPTIONS_UNSET+= DOCS NLS X11 EXAMPLES 2 | -------------------------------------------------------------------------------- /2-build-machine/uploads/poudriere.d/py35-make.conf: -------------------------------------------------------------------------------- 1 | DEFAULT_VERSIONS= python=3.5 python2=2.7 python3=3.5 2 | .if ${.CURDIR:M*/py*} 3 | PYTHON_VERSION=3.5 4 | .endif 5 | -------------------------------------------------------------------------------- /2-build-machine/uploads/poudriere.d/repo.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /2-build-machine/uploads/poudriere.d/repo.key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDO1lGu5gMnrS3G0tv6ZlYURPgHAlvtI3dvW+8yudqhz6/dVk9wT9KMMbyBikvl4WPZigzDa43MHaolzhFKf5kLQXZ2DOQzo74X6YVQAM1U13BkKER0kCvMAoBntWXBsxrSNEsm01FtLvbxHfFvenqMHnE9eDxwzm3DO1PW9THYPSZpL3g6vUQQTVyn0oFlg4jniSNSSjxrFc2LIJ8bRkHZwp3vHAl4cA/LlKFZG1ZZ9lJvAb1Z5dbqR0Hk7sdVHeIlTovwC6ilQ02Eg7KwwnOQmBdsp7ETQD5xm5cFgIi7jbuHAjdS8SDbJnCVTU43yz4KvdK9MctozXfM8hj1x9NOegEoM4+erb7UFY7gykuhc6i6niyL2VloH9aJXdOnStuO+GBLG9I7f1HsmG/5BYpxPJgLHQWS3WtQ6EPk53DrsKQwzmcdbNc3Y+F8d9gC1mldD5j5lH+Z+IR6hE1H8azB68iUlZZtKyfmj25zrDbVSMkCCucdMXcLg1YJO1bzPJ0QQMZwvo6ZCqT+KVREec1ZQzZIl9R1zR8Mbvyyv9X3VulwpRf5IvHIjcSTxVmx4OT1DfQ9L39H6LuUzo8j0O7N8kZxJYaMBdrErkuTM/+pYRNMsmvDOXKVTEtZix4nwJBuF53VltnHbii9RgJQ/rLe9ElC6jjaknxkxXbaNC+Icw== poudriere repo-key 2 | -------------------------------------------------------------------------------- /2-build-machine/variables.tf: -------------------------------------------------------------------------------- 1 | variable "instance_type" { } 2 | 3 | variable "aws_access_key" { } 4 | variable "aws_secret_key" { } 5 | variable "aws_region" { } 6 | variable "s3_bucket_name" { } 7 | 8 | 9 | variable "freebsd_11_0_ami" { 10 | type = "map" 11 | default = { 12 | us-east-1 = "ami-6ceaab7b" 13 | us-west-1 = "ami-a3f9b7c3" 14 | us-west-2 = "ami-6926f809" 15 | sa-east-1 = "ami-a1ff6dcd" 16 | eu-west-1 = "ami-36581e45" 17 | eu-central-1 = "ami-2352ae4c" 18 | ap-northeast-1 = "ami-a236e9c3" 19 | ap-northeast-2 = "ami-a49044ca" 20 | ap-southeast-1 = "ami-c39337a0" 21 | ap-southeast-2 = "ami-5920133a" 22 | ap-south-1 = "ami-7c3a4e13" 23 | } 24 | } 25 | 26 | variable "ssh_key" { 27 | default = "~/.ssh/id_rsa" 28 | } 29 | 30 | variable "build_trees" { } 31 | variable "build_jails" { } 32 | variable "build_sets" { } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Niklaas Baudet von Gersdorff 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Building [FreeBSD][4] ports for a variety of servers and clients takes 4 | a lot of computational resources. Since mine are sparse, using the cloud 5 | for building is attractive. This repository provides a skeleton for 6 | creating a temporary [poudriere][1] build machine running as an [EC2 7 | instance][2] on [Amazon AWS][3]. The machine is created with the help of 8 | [Terraform][7] and multiple `sh` scripts. 9 | 10 | The approach offers some outstanding characteristics: The skeleton is 11 | split into two layers: one for permanent, and one for temporary cloud 12 | infrastructure -- storage and build machine respectively. While building, 13 | poudriere's state is saved on an EBS. When building is completed, the 14 | packages are stored on a S3 bucket. In sum, this offers two huge 15 | advantages: 16 | 17 | 1. Since poudriere's state is on an EBS, created ports trees, jails and 18 | packages are stored independently from the build machine itself. Thus, 19 | you can deploy a very powerful machine in the cloud, use and pay it 20 | only as long as you really need it, and destroy it afterwards. The next 21 | time you want to compile packages, simply deploy a new instance -- it 22 | will re-attach the EBS and already created ports trees, jails, and 23 | packages are at hand. 24 | 25 | 2. Serving the bucket as static website, the packages can be made 26 | available for any FreeBSD machine easily. 27 | 28 | The idea was inspired by [JoergFiedler/freebsd-build-machine][5] using 29 | [Vagrant][6], its [AWS Provider][9], and [Ansible][10]. I prefer my 30 | approach because Terraform, on the contrary to Vagrant, was originally 31 | built for the cloud. Additionally, no knowledge of Ansible is necessary to 32 | understand what is actually happening: despite Terraform's configuration 33 | files everything is `sh`. This is up for discussion and I'm happy for any 34 | suggested improvement. 35 | 36 | # Prerequisites 37 | 38 | Some tasks the skeleton cannot handle for you automagically yet. The 39 | following is a list of things you must take care of manually. 40 | 41 | 1. You must subscribe to Amazon AWS and have your "Access Key" and "Secret 42 | Key" at hand. 43 | 44 | 2. If you don't have one, create a SSH keyfile that is *not* 45 | password-protected (with its corresponding public key 46 | `insecure-keyfile.pub`) e.g., `ssh-keygen -t rsa -b 4096 -N '' -f 47 | ~/.ssh/insecure-keyfile`. Remember where you put that file. 48 | 49 | 3. You need some basic understanding of Terraform and poudriere. While 50 | this skeleton automates a lot, it is not as user-friendly as it should 51 | be. So you should be aware of sharp edges. 52 | 53 | # Step-by-step Guide 54 | 55 | 0. Install Terraform from [the official download page][8]. Place it 56 | somewhere in your `$PATH` to ease execution. 57 | 58 | Note: Because of a bug, I highly recommend using `terraform` version 59 | 0.8.8 (not the newer 0.9.x branch). 60 | 61 | 1. Clone this repository to some place of your liking. `cd` into the 62 | directory of the repository. 63 | 64 | 2. Copy `terraform.tfvars.example` to `terraform.tfvars` and open the 65 | latter. Adjust the variables accordingly i.e., 66 | 67 | - `s3_bucket_name` is the name of the bucket where the build machine 68 | stores the compiled packages. Later you will access these packages 69 | from there. 70 | 71 | - `ssh_key` is the *private* part of your insecure keyfile i.e., in the 72 | case above it would be `~/.ssh/insecure-keyfile`. Terraform will upload 73 | its public part to AWS and associate it with the build machine. 74 | 75 | - `build_trees`, `build_jails`, and `build_sets` are special as they 76 | need the most time configuring. Here you start deciding how and which 77 | packages `poudriere` shall build for you. 78 | 79 | In the example given, `poudriere` will create a ports tree named 80 | "default". Further it will create a jail with method `svn+https`, 81 | call it "11armv6", create it according to the `arm.armv6` 82 | architecture, and base it on `release/11.0.1`. As you can see, you 83 | supply download method, name, architecture, and release separated by 84 | `_`. Last but not least, `poudriere` assumes a set called "default". 85 | 86 | In these variables you can specify multiple entries each separated by 87 | space. The build script will iterate through all of them. 88 | 89 | 3. Obviously, you must also tell `poudriere` which packages to build. You 90 | do so by listing their portname in package lists that you create in 91 | `uploads/pkglists`. The name of each list must correspond to the 92 | `build_trees`, `build_jails`, and `build_sets` that you configured in 93 | `terraform.tfvars`. E.g., `uploads/pkglists/default-11armv6-default` 94 | contains packages for the ports tree named "default", the jail 95 | "11armv6", and set "default". 96 | 97 | As mentioned previously, the build script will iterate through all 98 | combinations of `build_trees`, `build_jails`, and `build_sets`. 99 | However, it will not build anything, if there does not exist 100 | a `pkglist` that fits to a combination provided. 101 | 102 | 4. Configuring what to build exactly is a bit difficult. Nevertheless, 103 | this makes it possible to build a variety of different package sets and 104 | preserves the versatility of `poudriere`. Especially custom options, 105 | port blacklists, custom `poudriere.conf`, `make.conf` and `src.conf` 106 | files can all be set as documented in `poudriere(8)`. The corresponding 107 | `poudriere.d` directory you can find in `uploads/poudriere.d`. 108 | 109 | 5. As you might have already noticed, the skeleton consists of two parts: 110 | `1-storage` and `2-build-machine`. Each of these is, according to 111 | Terraform's principles, one "layer". The structure makes it possible to 112 | deploy a consistent, permanent and an inconsistent, temporary part of 113 | infrastructure in the cloud. The first part creates an EBS and a S3 114 | bucket. The EBS will be used for storing a ZFS pool that comprises 115 | poudriere's data output (created ports trees, jails, packages, etc.). 116 | The S3 bucket is used to store the package repository and poudriere's 117 | configuration. 118 | 119 | Thus, when configuration is all set you `cd 1-storage` and run 120 | `terraform apply`. You will be asked about the size of the EBS. The 121 | size highly depends on the amount of ports trees, jails, and packages 122 | you plan to set-up. 123 | 124 | * If you want to import an already existing bucket that has a folder 125 | structure as required by this script, you can do so by executing 126 | `terraform import aws_s3_bucket.packages ` within 127 | `1-storage`. This will import the bucket into terraform's current 128 | state. 129 | 130 | * The same works for an EBS volume, in case you already created one but 131 | lost your terraform state. Execute `terraform import 132 | aws_ebs_volume.poudriere ` in `1-storage`. 133 | 134 | Next, you `cd ../2-build-machine` and run `terraform apply` to create 135 | the build machine. You will be asked to specify the instance type. This 136 | mainly depends on the amount of money and time you want to spend. For 137 | testing, it makes sense to use an `t2.micro` instance. 138 | 139 | * You can find an overview of available instances (and there 140 | corresponding key) at [Amazon EC2 Instance 141 | Types](https://aws.amazon.com/ec2/instance-types). I recommend general 142 | purpose instances such as M4. 143 | 144 | * [AWS Simple Monthly 145 | Calculator](http://calculator.s3.amazonaws.com/index.html) can help you 146 | to get an idea how much usage might cost. 147 | 148 | 6. Once the infrastructure was deployed, run `./init-ssh` to connect to 149 | the machine. 150 | 151 | 7. Your're now on the remote machine. Start `tmux` and run `sudo 152 | build-ports` (it is important to run this command as root). This will 153 | start the build process (as complicated as you configured it). 154 | Depending on the amount of jails and packages that are created, this 155 | will take a while. When the build process itself is finished, the 156 | packages and poudriere's configuration are uploaded to the S3 bucket. 157 | 158 | 8. When you're done, run `sudo zpool export tank` on the remote side. This 159 | will release the attached EBS drive. If you don't, the builder cannot 160 | be destroyed with the next command. 161 | 162 | 9. Don't forget to run `terraform destroy` *within* `2-build-machine`. 163 | Otherwise your Amazon AWS bill will rise. Do *not* destroy the first 164 | layer (`1-storage`) because it holds both the EBS and S3 bucket. 165 | 166 | 10. Let your FreeBSD clients' `pkg` know about the S3 bucket. They can 167 | find packages under `http:///pkg`. 168 | 169 | The next time you want to compile packages, you don't need to re-create 170 | the `1-storage` layer. Only run `terraform apply` on the second layer 171 | `2-build-machine`. When doing so, terraform will re-attach the EBS, the 172 | build machine will mount the ZFS pool, and compilation can continue where 173 | it stopped the last time. 174 | 175 | # Structure of `2-build-machine` 176 | 177 | - `builder.tf` is the most important file. It includes the rules for 178 | `terraform` on how to create the infrastructure. 179 | - `init-ssh` is automatically created by terraform when deploying the 180 | infrastructure. It includes a simple `ssh` command that lets you connect 181 | to the correct instance. 182 | - `templates` includes several template files that are converted according 183 | to your configuration/use case when deploying the infrastructure. 184 | - The file created from `init.tpl` is passed to the build machine 185 | before it actually starts. It configures the machine to install some 186 | packages during boot time (as configured in `builder.tf` and sets up 187 | `sudo` for the user `ec2-user`. 188 | - The script `build-ports.tpl` is used to build the ports. It will be 189 | created according to the ports trees, jails, and sets you defined in 190 | `variables.tf`. 191 | - The file created from `shrc.tpl` sets up environment variables for 192 | the user `ec2-user`. This makes interaction with the S3 storage 193 | easier. 194 | - The script created from `upload-to-s3` is used to upload the 195 | compiled packages to S3. 196 | - `uploads` includes several scripts and configuration files that are 197 | needed remotely to build the ports properly. 198 | - `ports/` can include ports that have not been uploaded to 199 | the official ports tree yet. According to the name of the directory, 200 | these will be added to the to one of the trees configured by you and 201 | created by the builder. 202 | - `poudriere.conf` is the configuration file for poudriere. 203 | - `poudriere.d` includes further configuration for poudriere. 204 | 205 | # Terraform's hiccups 206 | 207 | - hashicorp/terraform#13423 : Too many SSH connection attempts result in 208 | huge disk usage (at least for me) 209 | 210 | [1]: https://github.com/freebsd/poudriere 211 | 212 | [2]: https://aws.amazon.com/ec2/instance-types 213 | 214 | [3]: https://aws.amazon.com 215 | 216 | [4]: https://www.freebsd.org 217 | 218 | [5]: https://github.com/JoergFiedler/freebsd-build-machine 219 | 220 | [6]: https://www.vagrantup.com 221 | 222 | [7]: https://www.terraform.io 223 | 224 | [8]: https://www.terraform.io/downloads.html 225 | 226 | [9]: https://github.com/mitchellh/vagrant-aws 227 | 228 | [10]: https://ansible.com 229 | -------------------------------------------------------------------------------- /terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | aws_region = "INSERT HERE" 2 | aws_access_key = "INSERT HERE" 3 | aws_secret_key = "INSERT HERE" 4 | s3_bucket_name = "INSERT HERE" 5 | ssh_key = "~/.ssh/id_rsa" 6 | build_trees = "default" 7 | build_jails = "svn+https_11armv6_arm.armv6_release/11.0.1" 8 | build_sets = "default" 9 | --------------------------------------------------------------------------------