Building packages on AWS Lambda

How do we do this?

Fortunately, there are a few open source projects which help make building binaries for AWS Lambda pretty straightforward. There is a GitHub project that mirrors the AWS Lambda image as a Docker image. Which you can shell onto and compile your build dependencies. Copy them off and then package them up, alongside your AWS Lambda function.

docker run -v /tmp/build:/build -it lambci/lambda:build bash

Building Debian DEBs on AWS Lambda

Debian packages are pretty straightforward. We opted not to compile dpkg-deb in order to build our deb package. You only need ar and tar to create a deb package, as it only consists of:

  • control.tar.gz a gzip archive containing all the; install scripts, revision history, rules etc
  • data.tar.gz a gzip archive containing the files to be installed. The archive directory structure will need to mirror the Debian filesystem.
ar -r zercurity.deb debian-binary control.tar.gz data.tar.gz
docker run -v /tmp/deb:/deb -it lambci/lambda:build bashyum -y install wget
wget http://ftp.gnu.org/gnu/binutils/binutils-2.29.tar.gz
tar -zxvf binutils-2.29.tar.gz
cd binutils-2.29/
./configure
make
make install
cp `which ar` /deb

Building Mac OSX PKGs on AWS Lambda

Creating Mac OSX packages are a little trickier to build and sign. There are only two binaries we need to compile on our AWS Lambda Docker container.

docker run -v /tmp/osx:/osx -it lambci/lambda:build bashyum -y install libxml2-devel wget bzip2-devel
wget https://github.com/downloads/mackyle/xar/xar-1.6.1.tar.gz
tar -zxvf xar-1.6.1.tar.gz
cd xar-1.6.1
./configure
make
make install
cd ..wget https://github.com/hogliux/bomutils/archive/debian/0.2-1.tar.gz
tar -zxvf 0.2-1.tar.gz
cd bomutils-debian-0.2-1/
make
make install
cp `which xar` /osx/.
cp `which mkbom` /osx/.

Creating an OSX package bundle

All the major walkthroughs regarding creating OSX packages involve using the X-Code distributed binaries to create your OSX package.

OSX Package

zercurity.pkg/Scripts
Create a new temporary directory that contains two files called “preinstall.sh” and “postinstall.sh”. You can pop whatever scripts you like in here. As the name suggests these two scripts will be executed pre and post install.

(cd '/path/to/_scripts' && find . | cpio -o --quiet --format odc --owner 0:0 | gzip -c) > 'Scripts'
(cd '/path/to/_payload' && find . | cpio -o --quiet --format odc --owner 0:0 | gzip -c) > 'Payload'
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<pkg-info postinstall-action="none" format-version="2" identifier="com.zercurity" version="0.1" generator-version="0.1" install-location="/" auth="root">
<payload numberOfFiles="10" installKBytes="1337"/>
<bundle-version/>
<upgrade-bundle/>
<update-bundle/>
<atomic-update-bundle/>
<strict-identifier/>
<relocate/>
<scripts>
<preinstall file="preinstall.sh"/>
<postinstall file="postinstall.sh"/>
</scripts>
</pkg-info>
mkbom -u 0 -g 0 /path/to/_payload Bom

OSX Bundle

Our bundle will encapsulate our “zercurity.pkg” package.

<?xml version="1.0" encoding="UTF-8"?>
<installer-gui-script minSpecVersion="1">
<title>Zercurity Installer</title>
<options allow-external-scripts="no" customize="allow" />
<domains enable_anywhere="true" />
<background file="background.png" alignment="topleft" scaling="none" />
<license file="license.txt" />
<welcome file="welcome.txt" />
<readme file="readme.txt" />
<conclusion file="conclusion.txt" />
<choices-outline>
<line choice="zercurity" />
</choices-outline>>
<choice description="zercurity" id="zercurity" title="Zercurity pre/post install scripts">
<pkg-ref id="com.zercurity" />
</choice>
<pkg-ref auth="root" id="com.zercurity" installKBytes="28" version="0.1">#zercurity.pkg</pkg-ref>
<pkg-ref id="com.zercurity">
<bundle-version />
</pkg-ref>
</installer-gui-script>
/zercurity.pkg/Scripts
/zercurity.pkg/Payload
/zercurity.pkg/PackageInfo
/zercurity.pkg/Bom
/Resources/en.lproj/background.png
/Resources/en.lproj/license.txt
/Resources/en.lproj/welcome.txt
/Resources/en.lproj/readme.txt
/Resources/en.lproj/conclusion.txt
/Distribution
xar --compression none -c -C /path/to/sources -f 'zercurity.pkg' .

Building RHEL RPMs on AWS Lambda

In order to build your .spec file as an rpm you’ll require the rpmbuild binary which thankfully does come with the AWS image. As the AWS Lambda image is a derivative of RHEL Fedora. However, you’ll still need to compile the rpmbuild binary as the older version of the software has a bug where you can’t build packages as a non-root user. You’ll end up with this error.

error: Bad owner/group rpmbuild
docker run -v /tmp/rpm:/rpm -it lambci/lambda:build bashyum -y install wget file-devel nss-devel popt-devel libarchive-devel db4-develwget https://github.com/rpm-software-management/rpm/archive/rpm-4.14.0-release.tar.gz
tar -zxvf rpm-4.14.0-release.tar.gz
cd rpm-rpm-4.14.0-release/
sh autogen.sh -prefix=/usr -without-lua
make
make install
cp `which rpmbuild` /rpm/.

Building Windows MSI on AWS Lambda

This might surprise you but you can actually build Windows (MSI) installers on Linux. There are a few ways to do this but we chose to use msitools which mirrors a subset of the Wix functionality.

docker run -v /tmp/msitools:/msitools -it lambci/lambda:build bashyum -y install wget glib2-devel gtk-doc libxml2-devel gobject-introspection libuuid-devel libmount-devel libtool-ltdl-devel curl-devel libxml2-devel libxslt-devel glib2-devel libIDL-devel dbus-devel dbus-glib-devel polkit-devel flex popt-devel bison bzip2-devel libgcrypt-devel libcanberra-devel gtk2-devel libart_lgpl-devel libglade2-devel libtasn1-tools libxklavier-devel libsoup-devel icon-naming-utils unique-devel libcanberra-gtk2 libcanberra-devel libwnck-devel librsvg2-devel libSM-devel libXdamage-devel gobject-introspection-devel upower-devel intltool  libtasn1-devel libtool gamin-devel rarian-devel dconf-devel libsecret-devel libgnome-keyring-develwget https://github.com/GNOME/glib/archive/2.55.1.tar.gz
tar -zxvf 2.55.1.tar.gz
cd glib-2.55.1/
sh autogen.sh -with-pcre=internal
make
make install
cd ..wget https://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz
tar -zxvf graphviz.tar.gz
cd graphviz-2.40.1/
sh autogen.sh
make
make install
cd ..export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/:/usr/local/lib/pkgconfig/wget https://download.gnome.org/sources/vala/0.39/vala-0.39.7.tar.xz
tar xf vala-0.39.7.tar.xz
cd vala-0.39.7/
./configure
make
make install
cd ..wget http://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz
tar xf Python-3.6.0.tar.xz
cd Python-3.6.0/
./configure
make
make install
cd ..wget https://bootstrap.pypa.io/get-pip.py
python3.6 get-pip.py
pip3.6 install pathlib
pip3.6 install meson
wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
unzip ninja-linux.zip
cp ninja /usr/bin/
chmod +x /usr/bin/ninja
wget https://download.gnome.org/sources/gcab/1.0/gcab-1.0.tar.xz
tar xf gcab-1.0.tar.xz
mkdir build/
cd gcab-1.0/
meson . ../build/
cd ../build/
ninja all
ninja install
cd ..wget http://ftp.gnu.org/pub/gnu/gettext/gettext-0.19.8.tar.gz
tar -zxvf gettext-0.19.8.tar.gz
cd gettext-0.19.8/
sh autogen.sh --skip-gnulib
./configure
make
make install
cd ..wget https://github.com/GNOME/libgsf/archive/LIBGSF_1_14_42.tar.gz
tar -zxvf LIBGSF_1_14_42.tar.gz
cd libgsf-LIBGSF_1_14_42/
sh autogen.sh
make
make install
cd ..wget http://ftp.gnome.org/pub/GNOME/sources/msitools/0.97/msitools-0.97.tar.xz
tar xf msitools-0.97.tar.xz
cd msitools-0.97/
sh autogen.sh
make
make install
cd ..cp `which msibuild` /msitools/.
cp `which wixl` /msitools/.
wget https://10gbps-io.dl.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
tar -zxvf osslsigncode-1.7.1.tar.gz
cd osslsigncode-1.7.1
./configure
make
make install
cp `which osslsigncode` /msitools/.

Done and dusted

Phew, well done if you got through all of that. Feel free to get in touch if you need any help working through any of that.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store