8

Does Anyone know something like ebextensions[2] in EC2 for AWS Lambda?

The goal is to install custom fonts in the AWS Lambda execution environment.

There are many ways to provide libraries and tools with fonts but the easiest way would be to include them via OS.

Also asked in response on AWS forum: https://forums.aws.amazon.com/thread.jspa?messageID=807139&#807139

[2]How I install specific fonts on my AWS EC2 instance?

will
  • 348
  • 1
  • 3
  • 7

6 Answers6

37

Here's what I just got to work for custom fonts on AWS Lambda with pandoc/xelatex.

I created a fonts directory in my project and placed all of my fonts there. Also in that directory I created a fonts.conf file that looks like this:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <dir>/var/task/fonts/</dir>
  <cachedir>/tmp/fonts-cache/</cachedir>
  <config></config>
</fontconfig>

And then in my (node.js based) handler function before shelling out to call pandoc I set an ENV var to tell fontconfig where to find the fonts.

process.env.FONTCONFIG_PATH='/var/task/fonts'

After doing that I can refer to a font, like Bitter, in my template by name (just Bitter) and then pandoc/xelatex/fontconfig/whatever knows which version of the font to use (like Bitter-Bold.otf vs Bitter-Italic.otf) based on the styling that any bit of text is supposed to have.

I figured this out based on the tips in this project for getting RSVG to work with custom fonts on Lambda: https://github.com/claudiajs/rsvg-convert-aws-lambda-binary/blob/master/README.md#using-custom-fonts

Jeremy Green
  • 8,547
  • 1
  • 29
  • 33
  • This is the answer that helped me out. – user3768495 May 07 '19 at 00:34
  • 2
    The same strategy works on a Lambda layer, as well, but instead of `/var/task/` use `/opt` – Tomas Buteler Sep 11 '19 at 16:24
  • 1
    This worked for me too - for anyone confused, stuff you deploy to a lambda function gets dumped in /var/task - and in my case, we deploy multiple packages, so /var/task/packageName. There are also some differences between nodejs8.10 and nodejs10.x -- https://github.com/alestic/lambdash helped a lot too - I checkout out, updated for node10 and installed. Pretty handy! – Quad64Bit Nov 22 '19 at 02:06
  • 2
    this worked for me: http://techdebtcollect.blogspot.com/2018/10/how-to-get-custom-font-into-aws-lambda.html, the difference from Jeremy's fonts.conf is that the points to a relative URL "./fonts" (I haven't tried with fully qualified url, but my guess it will work as well) – Yaniv Kessler Jun 28 '20 at 08:29
  • The font config doesn't really work for me. I am using the node gm package to interact with ImageMagick (https://www.npmjs.com/package/gm), and whether or not I include the fonts.conf file, it only accepts a relative path to my font (e.g. `fonts/Roboto-Black.ttf`). – antun Nov 16 '20 at 00:24
  • the `fonts.conf` worked for me, but not the env var `FONTCONFIG_PATH`. I had to use a different env var, `FONTCONFIG_FILE`. See https://www.freedesktop.org/software/fontconfig/fontconfig-user.html – cyrf May 10 '21 at 14:12
  • Could you provide gist example on how to do that? I try to make the same with lambda function in aws amplify project – nowszy94 Mar 21 '22 at 22:33
3

A lot of the answer on this subject of using fonts on Lambda's were a bit incomplete.

My scenario required using a custom font in conjunction with Imagemagick. I checked out out this branch with Imagemagick and Freetype support and worked through the README. The key for my use case is the lambda or lambda layer used in the function needed freetype support to access my fonts. I'm using a TTF.

After deploying the lambda layer, in my Lambda function's directory I did the following:

  • At the root of my lambda create a fonts directory.
    • In the fonts directory add the TTF or your font.
      • I'm using serverless framework so this directory once deployed will be located at /var/task/fonts.
    • Also in the fonts directory include the following fonts.conf.
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <dir>/var/task/fonts/</dir>
  <cachedir>/tmp/fonts-cache/</cachedir>
  <config></config>
</fontconfig>
  • Finally, in your serverless.yml add the following directory so that your fonts and fonts.conf will be included in the lambda.
package:
    include:
        - fonts/**

Because freetype is now accessible in the lambda layer any fonts in the fonts directory will be accessible. Could have also dynamically downloaded fonts needed, but I decided to choose include in my lambda function.

Zelf
  • 1,723
  • 2
  • 23
  • 40
  • What does including the `fonts/fonts.conf` file do? It didn't seem to make any difference for me. Whether I have the file or not, I have to use a path to the TTF itself, rather than refer to the font by name. – antun Nov 16 '20 at 00:22
1

The official AWS response on the forum post is still correct.

Currently, it is not possible to customize Lambda environment. If you want additional packages you can build on Amazon Linux and put them into the zip file you upload.

That's the extent to which you can "install" anything in the Lambda environment.

the easiest way would be to include them via OS.

Arguably so, but that's simply not how Lambda works.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • Exactly my thoughts. Thats why I hoped that AWS would provide something like a wrapper funcitonality, to add fonts like e.g. _ebextensions_ in EC2. – will Sep 29 '17 at 13:44
1

Package your assets along with the code or have it fetch them from s3. This is the way we generate PDFs with custom fonts with Lambda.

Things like the Serverless Framework will do this for you automatically (uploading code + deps assets).

When you deploy it will create a zip file with your code, dependencies and anything else you have in the folder. Then it will automatically upload it to S3 and deploy it with the help of CloudFormation.

Eduardo Romero
  • 1,159
  • 8
  • 10
  • Thank you for you answer. That is exactly how I'm doing it right now. But AFAIK fonts are still just assets files which have no realation to the operating system therefore in used libraries they need to be included again. Since this is not possible for me due to unexpected behaviour:(https://github.com/kangax/fabric.js/issues/4355), I hoped for something like ebextensions for lamba functions. – will Oct 04 '17 at 06:13
  • Cannot seems to bundle them correctly, can you post an example ? I think I tried everything. :( – Daniel Staleiny May 23 '18 at 20:25
0

I followed the instructions on this gist and it worked a charm (although for me in the "Configuring fontconfig" and "Installing and caching fonts" sections the /tmp/…/fontconfig seemed to really mean /var/task/<MyLambda>/headless-chrome/fontconfig)

Andrew
  • 1
0

Lambda extracts the layer contents into the /opt directory when setting up the execution environment for the function. So, fonts.conf should have /opt/.fonts under and ttf fonts should be placed there.

In addition Lambda needs to access the fontconfig library like libfontconfig.so, libexpat.so and libfreetype.so. The files can be found in phantom-lambda-fontconfig-pack.

It seems that it works in Node.JS lambda. In case of using Python Lambda, it still does not work.

At last, I created a Lambda container image based on the dockerfile in rchauhan9/image-scraper-lambda-container and then added the following code after "RUN apk add chromium..."

ENV NOTO_TC="https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/OTF/NotoSansCJKhk-VF.otf"
ENV NOTO_SC="https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/OTF/NotoSansCJKsc-VF.otf"
ENV NOTO_JP="https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/OTF/NotoSansCJKjp-VF.otf"
ENV NOTO_KR="https://github.com/googlefonts/noto-cjk/raw/main/Sans/Variable/OTF/NotoSansCJKkr-VF.otf"
RUN apk --no-cache add \
      fontconfig \
      wget \
      && mkdir -p /usr/share/fonts \
      && wget -q "${NOTO_TC}" -P /usr/share/fonts \
      && wget -q "${NOTO_SC}" -P /usr/share/fonts \
      && wget -q "${NOTO_JP}" -P /usr/share/fonts \
      && wget -q "${NOTO_KR}" -P /usr/share/fonts \
      && fc-cache -fv

ENV LANG="C.UTF-8"

It works with CJK fonts. Reference: Section "Building a Custom Image for Python" in New for AWS Lambda – Container Image Support

Cristik
  • 30,989
  • 25
  • 91
  • 127
Rico
  • 11
  • 1
  • 3