Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions _posts/2026-03-24-encrypted-build-secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Learn how to pass private registry tokens, API keys, and certificates into the F

## Introduction

Build secrets are already supported for [local builds and CI jobs](https://docs.openfaas.com/cli/build/#plugins-and-build-time-secrets) using `faas-cli pro build`. In that workflow, the secret files live on the build machine and are mounted directly into Docker's BuildKit. There's no network transport involved.
Build secrets are already supported for [local builds and CI jobs](https://docs.openfaas.com/cli/build/#build-time-secrets) using `faas-cli build`. In that workflow, the secret files live on the build machine and are mounted directly into Docker's BuildKit. There's no network transport involved.

The [Function Builder API](https://docs.openfaas.com/openfaas-pro/builder/) is different. It's designed for building untrusted code from third parties - your customers. A SaaS platform takes user-supplied source code, sends it to the builder over HTTP, and gets back a container image. The build happens in-cluster, without Docker, without root, and without sharing a Docker socket.

Expand Down Expand Up @@ -197,7 +197,14 @@ CMD ["fwatchdog"]

The `--mount=type=secret,id=api_key` line tells BuildKit to mount the secret at `/run/secrets/api_key` during that `RUN` step. It's only available during the build - it doesn't end up in any image layer.

Edit `stack.yaml` to add `build_secrets`:
Create a file to hold the secret value:

```bash
mkdir -p .secrets
echo -n "sk-live-my-secret-key" > .secrets/api_key.txt
```

Edit `stack.yaml` to add `build_secrets`. The values must be file paths — `faas-cli` reads the file contents before sealing and sending them to the builder:

```yaml
version: 1.0
Expand All @@ -210,7 +217,7 @@ functions:
handler: ./sealed-test
image: ttl.sh/test-build-secrets/sealed-test:2h
build_secrets:
api_key: sk-live-my-secret-key
api_key: .secrets/api_key.txt
```

### Build with the remote builder
Expand Down Expand Up @@ -274,7 +281,13 @@ The secret was encrypted on the client, sent over the wire inside the build tar,

In production, you'd use this to pass credentials for private package registries. Here's what that would look like for a Python function using the `python3-http` template.

In your `stack.yaml`:
Create a file with the index URL:

```bash
echo -n "https://token:pypi-secret@my-org.jfrog.io/artifactory/api/pypi/python-local/simple" > .secrets/pip_index_url.txt
```

In your `stack.yaml`, point `build_secrets` to the file:

```yaml
functions:
Expand All @@ -283,7 +296,7 @@ functions:
handler: ./data-processor
image: registry.example.com/data-processor:latest
build_secrets:
pip_index_url: https://token:pypi-secret@my-org.jfrog.io/artifactory/api/pypi/python-local/simple
pip_index_url: .secrets/pip_index_url.txt
```

Then in the template's Dockerfile, you'd change the `pip install` line to mount the secret:
Expand Down Expand Up @@ -340,7 +353,7 @@ We've added four new subcommands to `faas-cli secret`:

## Wrapping up

Build secrets for local builds and CI have been available for a while via `faas-cli pro build`. This feature brings the same capability to the Function Builder API, where builds happen in-cluster on behalf of third-party users and the secrets need to be protected over the wire.
Build secrets for local builds and CI have been available for a while via the `faas-cli`. This feature brings the same capability to the Function Builder API, where builds happen in-cluster on behalf of third-party users and the secrets need to be protected over the wire.

We developed this together with [Waylay](https://waylay.io) based on their production requirements, using NaCl box encryption to protect secrets over the wire. The `seal` package in the [Go SDK](https://github.com/openfaas/go-sdk) is generic and could be reused for other use-cases in the future.

Expand Down